CMakeMiddleTechnical
Что такое cache variables в CMake и как их определять и использовать?
Cache-переменные CMake хранятся в CMakeCache.txt, переживают перезапуск конфигурации и задаются через set(VAR value CACHE TYPE docstring) или option(); пользователь может переопределить их флагом -D при вызове cmake.
Что такое cache-переменные в CMake
Cache-переменные — это переменные, которые CMake сохраняет в файле CMakeCache.txt в директории сборки. В отличие от обычных переменных, которые существуют только во время выполнения скрипта, cache-переменные переживают перезапуск cmake и доступны пользователю для изменения через cmake-gui, ccmake или флаг -D.
Объявление cache-переменных
Синтаксис команды set с ключевым словом CACHE:
set(<variable> <value> CACHE <type> <docstring> [FORCE])
Типы переменных:
BOOL— логическое значение (ON/OFF)STRING— произвольная строкаFILEPATH— путь к файлуPATH— путь к директорииINTERNAL— скрыто в GUI, используется самим CMake
Практические примеры
# Флаг включения тестов — пользователь может переопределить через -D
set(BUILD_TESTS ON CACHE BOOL "Build unit tests")
# Путь к внешней библиотеке
set(OPENSSL_ROOT_DIR "" CACHE PATH "Path to OpenSSL root directory")
# Выбор бэкенда рендеринга
set(RENDERER "vulkan" CACHE STRING "Renderer backend (vulkan/opengl/metal)")
set_property(CACHE RENDERER PROPERTY STRINGS vulkan opengl metal)
# Принудительная перезапись даже если пользователь уже изменил значение
set(INTERNAL_VERSION "1.2.3" CACHE STRING "" FORCE)
Использование cache-переменных из командной строки
# Установка при первом configure
cmake -S . -B build -DBUILD_TESTS=OFF -DOPENSSL_ROOT_DIR=/usr/local/ssl
# Изменение уже закешированного значения
cmake -S . -B build -DRENDERER=opengl
# Просмотр всех cache-переменных
cmake -L build/ # только пользовательские
cmake -LA build/ # включая ADVANCED
cmake -LAH build/ # с docstring
Разница между обычной переменной и cache-переменной
# Обычная переменная — локальная, не сохраняется между запусками cmake
set(MY_LOCAL "hello")
# Cache-переменная — сохраняется в CMakeCache.txt
set(MY_CACHED "hello" CACHE STRING "Cached value")
# ВАЖНО: обычная переменная перекрывает cache-переменную того же имени
set(MY_CACHED "override") # теперь ${MY_CACHED} == "override", cache не тронут
unset(MY_CACHED) # после этого ${MY_CACHED} снова берётся из cache
Опция option() как синтаксический сахар для BOOL cache-переменных
# Эквивалентно set(ENABLE_ASAN OFF CACHE BOOL "Enable AddressSanitizer")
option(ENABLE_ASAN "Enable AddressSanitizer" OFF)
if(ENABLE_ASAN)
target_compile_options(myapp PRIVATE -fsanitize=address)
target_link_options(myapp PRIVATE -fsanitize=address)
endif()
Подводные камни
- Stale cache после изменения CMakeLists.txt: если переименовали переменную, старое значение остаётся в
CMakeCache.txtи сбивает с толку. Решение: удалитьbuild/CMakeCache.txtили всю директорию сборки. - FORCE не обновляет значение в GUI немедленно:
FORCEперезаписывает cache на диске, ноcmake-guiможет показывать старое значение до перезагрузки. - Порядок приоритетов: обычная переменная в текущем scope перекрывает cache-переменную того же имени — это неочевидный источник багов.
- INTERNAL-переменные не видны в GUI: использование типа
INTERNALдля скрытия «служебных» значений — осознанное решение, но может запутать при отладке. - Документирующая строка обязательна: пустой docstring (
"") — плохая практика, особенно для публичного проекта;cmake-guiпоказывает его как подсказку. - Multi-config генераторы игнорируют CMAKE_BUILD_TYPE: при использовании Ninja Multi-Config или Visual Studio cache-переменная
CMAKE_BUILD_TYPEне работает — нужен--config Releaseпри сборке. - set_property STRINGS: без него
cmake-guiпоказывает STRING-переменную как свободный ввод, а не как выпадающий список — пользователь может ввести некорректное значение.
Common mistakes
- Объяснять cache variables только по синтаксису, без жизненного цикла и стоимости.
- Игнорировать ошибки, null/empty состояния, порядок инициализации или режим сборки.
- Давать пример, который работает в демо, но ломается при изменении владельца ресурса.
- Трактовать CMake как shell-скрипт вместо описания графа таргетов.
What the interviewer is testing
- Кандидат формулирует точную модель для cache variables, а не только определение.
- Пример компилируем, безопасен по lifetime и соответствует версии технологии.
- Названы trade-off, ограничения и диагностируемые симптомы ошибки.
- Разделяет configure/generate/build и использует target-based подход.