Я прошу об этом в качестве напоминания о себе в следующий раз, когда я использую 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")
.