CMakeMiddleExperience
Расскажите о случае, когда вы решали проблему с CMake: incident, optimization, migration, debugging или CI/CD.
Типичная проблема — несовместимые версии зависимостей после обновления системных библиотек. Решается через явное указание путей через CMAKE_PREFIX_PATH и переход на FetchContent для воспроизводимых сборок.
Реальный случай: сломанная сборка после обновления CI-образа
На одном проекте (C++ микросервис) CI внезапно начал падать с ошибкой Could not find a package configuration file provided by "Boost" with any of the following names: BoostConfig.cmake. Локально всё собиралось — проблема только в GitLab CI.
Диагностика
# Посмотреть, что нашёл CMake и где искал
cmake -B build --debug-find 2>&1 | grep -A5 "Boost"
# Проверить переменные пути
cmake -B build -DCMAKE_VERBOSE_MAKEFILE=ON
# Напечатать все CMake-переменные (помогает понять окружение)
cmake -B build -LA | grep -i boost
Оказалось, что CI-образ обновили с Ubuntu 20.04 до 22.04, а Boost в системе сменил версию с 1.71 на 1.74 — конфиг-файлы переехали в другой путь.
Решение 1: явный CMAKE_PREFIX_PATH
cmake -B build \
-DCMAKE_PREFIX_PATH="/usr/lib/x86_64-linux-gnu/cmake" \
-DBoost_NO_SYSTEM_PATHS=ON
Решение 2: переход на FetchContent (долгосрочное)
include(FetchContent)
FetchContent_Declare(
Boost
URL https://github.com/boostorg/boost/releases/download/boost-1.84.0/boost-1.84.0.tar.xz
URL_HASH SHA256=2e64e5d79a738d0fa6fb546c6e5c2bd28f88d268a2a080546f74e5ff98f29d0e
)
set(BOOST_INCLUDE_LIBRARIES filesystem system)
FetchContent_MakeAvailable(Boost)
target_link_libraries(my_service PRIVATE Boost::filesystem Boost::system)
Решение 3: кэширование зависимостей в CI
# .gitlab-ci.yml
build:
cache:
key: cmake-deps-$CI_COMMIT_REF_SLUG
paths:
- build/_deps/
script:
- cmake -B build -DCMAKE_BUILD_TYPE=Release
- cmake --build build --parallel $(nproc)
Другой кейс: медленная сборка в CI
Генерация Unix Makefiles вместо Ninja удваивала время сборки. Правка:
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
ninja -C build -j$(nproc)
Подводные камни
- Локальное окружение разработчика и CI-образ могут иметь разные версии системных библиотек — всегда фиксируйте версии через FetchContent или vcpkg.
find_package(X REQUIRED)без указания версии даёт первую найденную — это может быть несовместимая версия из/usr/local.- Кэш CMake (
CMakeCache.txt) хранит абсолютные пути — копирование build-директории между машинами или контейнерами ломает сборку. - Переменная
CMAKE_INSTALL_PREFIXпо умолчанию/usr/local— в CI без sudo приводит к ошибке установки; всегда переопределяйте. - Переключение между Debug и Release требует пересборки с нуля или отдельной build-директории —
cmake -B build-releasevsbuild-debug. - FetchContent скачивает зависимости при каждой свежей CI-джобе без кэша — добавьте кэш по хэшу URL или используйте vcpkg с baseline.
What hurts your answer
- Выдумывать опыт или говорить слишком общими фразами
- Не объяснять свою личную роль в работе с CMake
- Не показывать результат, метрики или извлечённые уроки
What they're listening for
- Может подготовить честный пример использования CMake
- Показывает свою роль, решения и результат
- Умеет рефлексировать над trade-offs и уроками