设置和使用变量的 CMake 语法是什么? [英] What's the CMake syntax to set and use variables?
问题描述
我问这个是为了提醒自己下次使用 CMake 时.它永远不会坚持,而且 Google 的结果也不是很好.
I'm asking this as a reminder to myself the next time I use CMake. It never sticks, and Google results aren't great.
在 CMake 中设置和使用变量的语法是什么?
What's the syntax to set and use variables in CMake?
推荐答案
在编写 CMake 脚本时,您需要了解很多有关语法以及如何在 CMake 中使用变量的知识.
When writing CMake scripts there is a lot you need to know about the syntax and how to use variables in 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})
- CMake/语言语法
- CMake:变量列表字符串
- CMake:有用的变量
- CMake
set()
命令一个> - CMake
string()
Command - CMake
list()
命令一个> - Cmake:生成器表达式
- CMake/Language Syntax
- CMake: Variables Lists Strings
- CMake: Useful Variables
- CMake
set()
Command - CMake
string()
Command - CMake
list()
Command - Cmake: Generator Expressions
首先是正常变量"以及您需要了解的有关其范围的内容:
First there are the "Normal Variables" and things you need to know about their scope:
- 普通变量对
CMakeLists.txt
是可见的,它们被设置在里面并且从那里调用的所有东西(add_subdirectory()
,include()
,macro()
和function()
). add_subdirectory()
和function()
命令很特别,因为它们打开了自己的作用域.- 意义变量
set(...)
只在那里可见,它们复制了调用它们的范围级别(称为父范围)的所有正常变量. - 因此,如果您在子目录或函数中,您可以使用
set(... PARENT_SCOPE)
修改父作用域中已经存在的变量 - 您可以使用它,例如在函数中通过将变量名作为函数参数传递.一个例子是
function(xyz _resultVar)
正在设置set(${_resultVar} 1 PARENT_SCOPE)
- Normal variables are visible to the
CMakeLists.txt
they are set in and everything called from there (add_subdirectory()
,include()
,macro()
andfunction()
). - The
add_subdirectory()
andfunction()
commands are special, because they open-up their own scope.- Meaning variables
set(...)
there are only visible there and they make a copy of all normal variables of the scope level they are called from (called parent scope). - So if you are in a sub-directory or a function you can modify an already existing variable in the parent scope with
set(... PARENT_SCOPE)
- You can make use of this e.g. in functions by passing the variable name as a function parameter. An example would be
function(xyz _resultVar)
is settingset(${_resultVar} 1 PARENT_SCOPE)
其次是全局变量缓存".关于缓存你需要知道的事情:
Second there is the "Global Variables Cache". Things you need to know about the Cache:
- 如果在当前作用域中没有定义具有给定名称的普通变量,CMake 将查找匹配的 Cache 条目.
- 缓存值存储在二进制输出目录中的
CMakeCache.txt
文件中. Cache中的值可以在CMake 的 GUI 应用程序在生成之前.因此,与普通变量相比,它们具有
type
和docstring
.我通常不使用 GUI,所以我使用set(... CACHE INTERNAL "")
来设置我的全局和持久值.
- If no normal variable with the given name is defined in the current scope, CMake will look for a matching Cache entry.
- Cache values are stored in the
CMakeCache.txt
file in your binary output directory. The values in the Cache can be modified in CMake's GUI application before they are generated. Therefore they - in comparison to normal variables - have a
type
and adocstring
. I normally don't use the GUI so I useset(... CACHE INTERNAL "")
to set my global and persistant values.
请注意,
INTERNAL
缓存变量类型确实意味着FORCE
Please note that the
INTERNAL
cache variable type does implyFORCE
在 CMake 脚本中,如果您使用
set(... CACHE ... FORCE)
语法,您只能更改现有的缓存条目.这种行为是利用例如通过 CMake 本身,因为它通常不会强制缓存条目本身,因此您可以使用另一个值预定义它.In a CMake script you can only change existing Cache entries if you use the
set(... CACHE ... FORCE)
syntax. This behavior is made use of e.g. by CMake itself, because it normally does not force Cache entries itself and therefore you can pre-define it with another value.缓存是全局的,您几乎可以在 CMake 脚本中的任何位置设置它们.但我建议您三思在何处使用 Cache 变量(它们是全局的并且是持久的).我通常更喜欢
set_property(GLOBAL PROPERTY ...)
和set_property(GLOBAL APPEND PROPERTY ...)
语法来定义我自己的非持久性全局变量.The Cache is global and you can set them virtually anywhere in your CMake scripts. But I would recommend you think twice about where to use Cache variables (they are global and they are persistant). I normally prefer the
set_property(GLOBAL PROPERTY ...)
andset_property(GLOBAL APPEND PROPERTY ...)
syntax to define my own non-persistant global variables.为了避免陷阱,您应该了解以下有关变量的信息:
To avoid pitfalls you should know the following about variables:
- 如果局部变量具有相同的名称,它们会隐藏缓存的变量
find_...
命令 - 如果成功 - 将其结果写入缓存变量这样就不会再次搜索调用"- CMake 中的列表只是带有分号分隔符的字符串,因此引号很重要
set(MyVar abc)
是"a;b;c"
而set(MyVar "abc")
是"abc"
- 建议您始终使用引号,但当您想将列表作为列表提供时除外
- 通常更喜欢使用
list()
命令来处理列表
- Local variables do hide cached variables if both have the same name
- The
find_...
commands - if successful - do write their results as cached variables "so that no call will search again" - Lists in CMake are just strings with semicolons delimiters and therefore the quotation-marks are important
set(MyVar a b c)
is"a;b;c"
andset(MyVar "a b c")
is"a b c"
- The recommendation is that you always use quotation marks with the one exception when you want to give a list as list
- Generally prefer the
list()
command for handling lists
- 环境变量的更改不会重新触发生成过程.
- 特别是生成的 IDE 环境可能与您的命令行不同,因此建议将您的环境变量转移到缓存中.
有时只有调试变量才有帮助.以下内容可能对您有所帮助:
Sometimes only debugging variables helps. The following may help you:
- 通过使用
message()
命令,只需使用旧的printf
调试样式.还有一些随 CMake 自带的现成模块:CMakePrintHelpers.cmake, CMakePrintSystemInformation.cmake - 查看二进制输出目录中的
CMakeCache.txt
文件.如果您的 make 环境的实际生成失败,甚至会生成此文件. - 使用 variable_watch() 查看变量的位置读/写/删除.
- 查看目录属性 CACHE_VARIABLES 和 变量
- 调用
cmake --trace ...
查看CMake的完整解析过程.这是最后的储备,因为它产生了大量的产出.
- Simply use old
printf
debugging style by using themessage()
command. There also some ready to use modules shipped with CMake itself: CMakePrintHelpers.cmake, CMakePrintSystemInformation.cmake - Look into
CMakeCache.txt
file in your binary output directory. This file is even generated if the actual generation of your make environment fails. - Use variable_watch() to see where your variables are read/written/removed.
- Look into the directory properties CACHE_VARIABLES and VARIABLES
- Call
cmake --trace ...
to see the CMake's complete parsing process. That's sort of the last reserve, because it generates a lot of output.
- 环境变量
- 您可以读取
$ENV{...}
和写入set(ENV{...} ...)
环境变量
- Environment Variables
- You can can read
$ENV{...}
and writeset(ENV{...} ...)
environment variables
- 生成器表达式
$<...>
仅在 CMake 的生成器编写 make 环境时进行评估(它与由解析器就地"替换的普通变量进行比较)莉> - 非常方便,例如在编译器/链接器命令行和多配置环境中
- Generator expressions
$<...>
are only evaluated when CMake's generator writes the make environment (it comparison to normal variables that are replaced "in-place" by the parser) - Very handy e.g. in compiler/linker command lines and in multi-configuration environments
- 使用
${${...}}
,您可以在变量中指定变量名称并引用其内容. - 常用于将变量名作为函数/宏参数给出.
- With
${${...}}
you can give variable names in a variable and reference its content. - Often used when giving a variable name as function/macro parameter.
- 使用
if(MyVariable)
你可以直接检查变量的真/假(这里不需要封闭的${...}
) - True if the constant is
1
,ON
,YES
,TRUE
,Y代码>,或非零数字.
- 假如果常数是
0
、OFF
、NO
、FALSE
、N
、IGNORE
、NOTFOUND
、空字符串,或以后缀-NOTFOUND
结尾. - 此语法通常用于诸如
if(MSVC)
之类的内容,但对于不知道此语法快捷方式的人来说可能会感到困惑.
- With
if(MyVariable)
you can directly check a variable for true/false (no need here for the enclosing${...}
) - True if the constant is
1
,ON
,YES
,TRUE
,Y
, or a non-zero number. - False if the constant is
0
,OFF
,NO
,FALSE
,N
,IGNORE
,NOTFOUND
, the empty string, or ends in the suffix-NOTFOUND
. - This syntax is often use for something like
if(MSVC)
, but it can be confusing for someone who does not know this syntax shortcut.
- 您可以使用变量构造变量名称.CMake 替换变量后,它会再次检查结果是否是变量本身.这是 CMake 本身使用的非常强大的功能,例如作为一种模板
set(CMAKE_${lang}_COMPILER ...)
- 但是请注意这会让您在
if()
命令中头疼.这是一个示例,其中CMAKE_CXX_COMPILER_ID
是"MSVC"
而MSVC
是"1"
:if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
为真,因为它的计算结果为if("1" STREQUAL "1")
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
为假,因为它的计算结果为if("MSVC" STREQUAL "1")
- 所以这里最好的解决方案是 - 见上文 - 直接检查
if(MSVC)
- You can construct variable names using variables. After CMake has substituted the variables, it will check again if the result is a variable itself. This is very powerful feature used in CMake itself e.g. as sort of a template
set(CMAKE_${lang}_COMPILER ...)
- But be aware this can give you a headache in
if()
commands. Here is an example whereCMAKE_CXX_COMPILER_ID
is"MSVC"
andMSVC
is"1"
:if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
is true, because it evaluates toif("1" STREQUAL "1")
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
is false, because it evaluates toif("MSVC" STREQUAL "1")
- So the best solution here would be - see above - to directly check for
if(MSVC)
- 主要只是缓存字符串,只能是
ON
或OFF
并且它们允许一些特殊处理,例如依赖项 - 但是要注意,不要将
option
与set
命令混淆.赋予option
的值实际上只是初始值"(在第一个配置步骤中传输一次到缓存中),之后由用户通过 CMake 的 GUI.
- Mainly just cached strings that only can be
ON
orOFF
and they allow some special handling like e.g. dependencies - But be aware, don't mistake the
option
with theset
command. The value given tooption
is really only the "initial value" (transferred once to the cache during the first configuration step) and is afterwards meant to be changed by the user through CMake's GUI.
- CMake 是如何使用的?
- cmake, 迷失在全局变量的概念中(和 PARENT_SCOPE 或 add_subdirectory 替代)
- 遍历字符串列表
- 如何存储 CMake 构建设置
- CMake 与空字符串比较,STREQUAL 失败
- 什么时候应该引用变量?
这篇关于设置和使用变量的 CMake 语法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- You can can read
- 您可以读取
- Meaning variables
- 意义变量