Перед оптимизацией необходимо провести замеры:
Профилирование сборки:
# CMake с генерацией временных меток
cmake --build . --target clean
time cmake --build . -j1 # Замер однопоточной сборки
time cmake --build . -j$(nproc) # Замер параллельной сборки
Анализ зависимостей:
# Для Makefile
make -Bnkw | wc -l # Оценка количества компилируемых файлов
# Для Ninja
ninja -t commands | grep c++ | wc -l
Рекомендации:
Использовать Ninja вместо Make:
cmake -G Ninja ..
Оптимальное количество потоков:
# Обычно ядра * 1.5
cmake --build . -j$(($(nproc) * 3 / 2))
Проблемные места:
Решение:
Forward declarations вместо включений:
// Вместо #include "BigClass.h"
class BigClass; // Предварительное объявление
Проверка зависимостей:
g++ -M main.cpp # Показать зависимости
Настройка в CMake:
target_precompile_headers(my_target PUBLIC
<vector>
<string>
<memory>
"common.h"
)
Активация в CMake:
set_target_properties(my_target PROPERTIES
UNITY_BUILD ON
UNITY_BUILD_BATCH_SIZE 5 # Количество файлов в одном unity-файле
)
Настройка ccache:
# В .bashrc или .zshrc
export CCACHE_SLOPPINESS="pch_defines,time_macros"
export CCACHE_MAXSIZE=10G
Интеграция с CMake:
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PROGRAM})
endif()
Проблема: Избыточное инстанцирование шаблонов в разных единицах трансляции
Решение:
// header.h
template<typename T>
void my_template_func(T param);
// source.cpp
template void my_template_func<int>(int);
template void my_template_func<float>(float);
Советы для CMake:
Отключение ненужных компонентов:
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
Оптимизация зависимостей:
set(CMAKE_SKIP_RPATH ON)
set(BUILD_SHARED_LIBS ON) # Использование динамических библиотек
Правила:
Clang Build Analyzer:
cmake -DCMAKE_CXX_COMPILER=clang++ ..
ninja -t commands | awk '/c++/ {print $0}' > build_commands.txt
Visual Studio Build Insights (для Windows)
GCC -ftime-report:
g++ -ftime-report -c file.cpp
Фильтрация ненужных include:
include-what-you-use -Xiwyu --mapping_file=qt5_11.imp main.cpp
Модули C++20 (если доступны):
// Вместо #include <vector>
import std.vector;
distcc:
export DISTCC_HOSTS="localhost host2 host3"
distcc g++ -c file.cpp
icecc (Icecream):
export PATH=/usr/lib/icecc/bin:$PATH
icecc g++ -c file.cpp
Золотой линкер (gold):
-fuse-ld=gold
LLD (еще быстрее gold):
-fuse-ld=lld
Оптимизация библиотек:
# Создание thin-архивов
ar --thin -rcs libthin.a *.o
Резюмируем: ускорение сборки требует комплексного подхода — от оптимизации структуры кода до настройки инструментов сборки. Начинать следует с анализа узких мест, затем последовательно применять описанные техники, замеряя улучшения после каждого изменения.