Проект медленно собирается. Как можно ускорить?cplus-24

Анализ текущей ситуации

Перед оптимизацией необходимо провести замеры:

  1. Профилирование сборки:

    # CMake с генерацией временных меток
    cmake --build . --target clean
    time cmake --build . -j1  # Замер однопоточной сборки
    time cmake --build . -j$(nproc)  # Замер параллельной сборки
    
  2. Анализ зависимостей:

    # Для Makefile
    make -Bnkw | wc -l  # Оценка количества компилируемых файлов
    
    # Для Ninja
    ninja -t commands | grep c++ | wc -l
    

Основные направления оптимизации

1. Параллелизация сборки

Рекомендации:

  • Использовать Ninja вместо Make:

    cmake -G Ninja ..
    
  • Оптимальное количество потоков:

    # Обычно ядра * 1.5
    cmake --build . -j$(($(nproc) * 3 / 2))
    

2. Оптимизация структуры include

Проблемные места:

  • Циклические зависимости заголовков
  • Избыточные включения

Решение:

  • Forward declarations вместо включений:

    // Вместо #include "BigClass.h"
    class BigClass;  // Предварительное объявление
    
  • Проверка зависимостей:

    g++ -M main.cpp  # Показать зависимости
    

3. Использование предкомпилированных заголовков

Настройка в CMake:

target_precompile_headers(my_target PUBLIC
    <vector>
    <string>
    <memory>
    "common.h"
)

4. Unity Builds

Активация в CMake:

set_target_properties(my_target PROPERTIES
    UNITY_BUILD ON
    UNITY_BUILD_BATCH_SIZE 5  # Количество файлов в одном unity-файле
)

5. Кэширование компиляции

Настройка 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()

6. Оптимизация шаблонов и инстанцирования

Проблема: Избыточное инстанцирование шаблонов в разных единицах трансляции

Решение:

  • Явное инстанцирование:
    // 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);
    

7. Оптимизация системы сборки

Советы для CMake:

  1. Отключение ненужных компонентов:

    set(CMAKE_DISABLE_SOURCE_CHANGES ON)
    set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
    
  2. Оптимизация зависимостей:

    set(CMAKE_SKIP_RPATH ON)
    set(BUILD_SHARED_LIBS ON)  # Использование динамических библиотек
    

8. Инкрементальная сборка

Правила:

  • Минимизация изменений в заголовочных файлах
  • Разделение на мелкие модули
  • Использование forward declarations

Инструменты для анализа

  1. Clang Build Analyzer:

    cmake -DCMAKE_CXX_COMPILER=clang++ ..
    ninja -t commands | awk '/c++/ {print $0}' > build_commands.txt
    
  2. Visual Studio Build Insights (для Windows)

  3. GCC -ftime-report:

    g++ -ftime-report -c file.cpp
    

Оптимизация зависимостей

  1. Фильтрация ненужных include:

    include-what-you-use -Xiwyu --mapping_file=qt5_11.imp main.cpp
    
  2. Модули C++20 (если доступны):

    // Вместо #include <vector>
    import std.vector;
    

Распределенная сборка

  1. distcc:

    export DISTCC_HOSTS="localhost host2 host3"
    distcc g++ -c file.cpp
    
  2. icecc (Icecream):

    export PATH=/usr/lib/icecc/bin:$PATH
    icecc g++ -c file.cpp
    

Оптимизация линковки

  1. Золотой линкер (gold):

    -fuse-ld=gold
    
  2. LLD (еще быстрее gold):

    -fuse-ld=lld
    
  3. Оптимизация библиотек:

    # Создание thin-архивов
    ar --thin -rcs libthin.a *.o
    

Резюмируем: ускорение сборки требует комплексного подхода — от оптимизации структуры кода до настройки инструментов сборки. Начинать следует с анализа узких мест, затем последовательно применять описанные техники, замеряя улучшения после каждого изменения.