Я прошу об этом в качестве напоминания о себе в следующий раз, когда я использую CMake. Он никогда не придерживается, и результаты Google невелики.
Какой синтаксис устанавливать и использовать переменные в CMake?
Я прошу об этом в качестве напоминания о себе в следующий раз, когда я использую CMake. Он никогда не придерживается, и результаты Google невелики.
Какой синтаксис устанавливать и использовать переменные в CMake?
При написании сценариев CMake нужно много знать о синтаксисе и о том, как использовать переменные в CMake.
Строки с использованием set():
set(MyString "Some Text")set(MyStringWithVar "Some other Text: ${MyString}")set(MyStringWithQuot "Some quote: \"${MyStringWithVar}\"") Или со string():
string(APPEND MyStringWithContent " ${MyString}") Списки, использующие set():
set(MyList "a" "b" "c")set(MyList ${MyList} "d") Или лучше со list():
list(APPEND MyList "a" "b" "c")list(APPEND MyList "d")Списки имен файлов:
set(MySourcesList "File.name" "File with Space.name")list(APPEND MySourcesList "File.name" "File with Space.name")add_excutable(MyExeTarget ${MySourcesList})set()string() командаlist()Сначала есть "Нормальные переменные" и вещи, которые вы должны знать об их области действия:
CMakeLists.txt они установлены, и все, что оттуда add_subdirectory(), include(), macro() и function()).add_subdirectory() и function() являются специальными, потому что они открывают свою собственную область видимости. set(...) там видны только там, и они копируют все нормальные переменные уровня области действия, из которого они вызываются (называемые родительской областью действия).set(... PARENT_SCOPE)function(xyz _resultVar) которой установлено значение set(${_resultVar} 1 PARENT_SCOPE)include() или macro() будет изменять переменные непосредственно в области их вызова.Во-вторых, это "Кэш глобальных переменных". Что нужно знать о кеше:
CMakeCache.txt в вашей директории двоичного вывода. Значения в Cache могут быть изменены в приложении CMake GUI перед их генерацией. Поэтому они - по сравнению с обычными переменными - имеют type и docstring. Обычно я не использую графический интерфейс, поэтому я использую set(... CACHE INTERNAL "") для установки моих глобальных и постоянных значений.
Обратите внимание, что тип переменной INTERNAL кеша подразумевает FORCE
В сценарии CMake вы можете изменять существующие записи в кэше, только если используете синтаксис set(... CACHE... FORCE). Это поведение используется, например, самим CMake, потому что обычно оно не заставляет сами записи Cache, и поэтому вы можете предварительно -D определить его с другим значением.
cmake -D var:type=value, просто cmake -D var=value или cmake -C CMakeInitialCache.cmake.unset(... CACHE). Кэш является глобальным, и вы можете установить его практически в любом месте ваших сценариев CMake. Но я бы порекомендовал вам дважды подумать о том, где использовать переменные Cache (они глобальные и постоянные). Обычно я предпочитаю set_property(GLOBAL PROPERTY...) и set_property(GLOBAL APPEND PROPERTY...) определять свои собственные непостоянные глобальные переменные.
Чтобы избежать ошибок, вы должны знать следующее о переменных:
find_... - в случае успеха - записывают свои результаты в виде кэшированных переменных, "чтобы ни один вызов не выполнялся снова"set(MyVar abc) - "a;b;c" а set(MyVar "abc") - "abc"list() для обработки списковfunctions() вместо macros() потому что вы не хотите, чтобы ваши локальные переменные отображались в родительской области.project() и enable_language(). Поэтому может быть важно установить некоторые переменные перед использованием этих команд.Иногда помогают только отладочные переменные. Следующее может помочь вам:
printf с помощью команды message(). Есть также некоторые готовые к использованию модули, поставляемые с самим CMake: CMakePrintHelpers.cmake, CMakePrintSystemInformation.cmakeCMakeCache.txt в вашей директории двоичного вывода. Этот файл генерируется даже в случае сбоя фактической генерации среды make.cmake --trace... чтобы увидеть полный процесс разбора CMake. Такого рода последний резерв, потому что он генерирует много продукции.$ENV{...} и записывать переменные окружения set(ENV{...}...)$<...> оцениваются только тогда, когда генератор CMake записывает среду make (это сравнение с обычными переменными, которые заменяются парсером "на месте")${${...}} вы можете давать имена переменных в переменной и ссылаться на ее содержимое.if()) if(MyVariable) вы можете напрямую проверить переменную на true/false (здесь нет необходимости для вложенных ${...})1, ON, YES, TRUE, Y или ненулевое число.0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, пустая строка или заканчивается суффиксом -NOTFOUND.if(MSVC), но он может сбивать с толку тех, кто не знает этого ярлыка синтаксиса.set(CMAKE_${lang}_COMPILER...) шаблонов set(CMAKE_${lang}_COMPILER...)if(). Вот пример, где CMAKE_CXX_COMPILER_ID равен "MSVC" а MSVC равен "1": if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") имеет значение true, поскольку оно оценивается как if("1" STREQUAL "1")if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") имеет значение false, поскольку оно оценивается как if("MSVC" STREQUAL "1")if(MSVC)cmake_policy(SET CMP0054 NEW) значение "интерпретировать аргументы if() как переменные или ключевые слова в кавычках".option() ON или OFF и они допускают некоторую специальную обработку, например, зависимостиoption с командой set. Значение, данное option на самом деле является только "начальным значением" (переданным один раз в кэш на первом этапе настройки) и впоследствии должно быть изменено пользователем через графический интерфейс CMake.Вот пара основных примеров, чтобы начать быстро и грязно.
Установить переменную:
SET(INSTALL_ETC_DIR "etc")
Используйте переменную:
SET(INSTALL_ETC_CROND_DIR "${INSTALL_ETC_DIR}/cron.d")
Установить переменную:
SET(PROGRAM_SRCS
program.c
program_utils.c
a_lib.c
b_lib.c
config.c
)
Используйте переменную:
add_executable(program "${PROGRAM_SRCS}")
$ENV{FOO} для использования, где FOO выбирается из переменной среды. в противном случае используйте как ${FOO}, где FOO - некоторая другая переменная. Для настройки в CMake будет использоваться SET(FOO "foo").