раздел 03 · практика
СОБИРАЕМ БЫСТРО И ВОСПРОИЗВОДИМО
Шесть шагов от пустой папки до проекта, который собирается одной командой, кэшируется и масштабируется на все ядра.
01дерево проекта
Структура проекта
Исходники отделены от заголовков, сборка живёт вне дерева исходников (out-of-source).
engine-lab/
├── CMakeLists.txt
├── CMakePresets.json
├── src/
│ ├── main.cpp
│ ├── parser.cpp
│ └── engine.cpp
├── include/engine/
│ ├── parser.h
│ └── engine.h
├── tests/
│ └── test_parser.cpp
└── build/ # создаётся автоматически
02CMakeLists.txt
Базовый CMakeLists
Современный CMake — это цели и их свойства, а не глобальные переменные.
cmake_minimum_required(VERSION 3.25)
project(engine_lab VERSION 0.1.0 LANGUAGES CXX)
add_library(core
src/parser.cpp
src/engine.cpp)
target_include_directories(core PUBLIC include)
add_executable(app src/main.cpp)
target_link_libraries(app PRIVATE core)
enable_testing()
add_subdirectory(tests)cmake -B build && cmake --build build -j
03CMakePresets.json
Пресеты: конфигурации как код
Именованные конфигурации в файле. Все разработчики и CI собирают идентично.
{
"version": 6,
"configurePresets": [
{ "name": "dev",
"binaryDir": "${sourceDir}/build/dev",
"generator": "Ninja",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_COMPILER_LAUNCHER": "ccache" } },
{ "name": "release",
"inherits": "dev",
"binaryDir": "${sourceDir}/build/release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": "ON" } }
]
}cmake --preset dev && cmake --build --preset dev
04терминал
Кэширование компиляции
ccache хранит результаты компиляции по хэшу входов. Повторная сборка попадает в кэш.
# установка и подключение
sudo apt install ccache
cmake -B build -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
# статистика
ccache -s
# cache hit rate: 92.4 %Совет: в CI прогревайте кэш артефактом между запусками.
05CMakeLists.txt — ускорение
Ускоряем: PCH, unity, параллелизм
Три рычага: предкомпилированные заголовки, слияние единиц трансляции и параллельная сборка.
target_precompile_headers(core PRIVATE
<vector> <string> <memory>)
set_target_properties(core PROPERTIES
UNITY_BUILD ON
UNITY_BUILD_BATCH_SIZE 8)ninja -C build -j$(nproc)
06CMakeLists.txt — генераторные выражения
Флаги, санитайзеры, LTO
Debug ловит ошибки санитайзерами, Release выжимает скорость через LTO.
target_compile_options(core PRIVATE
$<$<CONFIG:Release>:-O2 -march=native>
$<$<CONFIG:Debug>:-O0 -g -fsanitize=address,undefined>)
set_target_properties(app PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)бонус
Калькулятор параллельной сборки
Модель учитывает конфигурацию и линковку — разгон всегда меньше числа ядер.
Последовательно, -j16 мин 0 с
Параллельно, -j849 с
×7.3
разгон · эффективность: 92%