下次我使用CMake时,我会问这个提醒自己。它永远不会坚持,谷歌的结果也不是很好。
在CMake中设置和使用变量的语法是什么?
答案 0 :(得分:206)
在编写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()
Command string()
Command list()
Command 首先是"正常变量"以及你需要了解的范围:
CMakeLists.txt
可见,并且从那里调出所有内容(add_subdirectory()
,include()
,macro()
和function()
)。< / LI>
add_subdirectory()
和function()
命令很特殊,因为它们打开了自己的范围。
set(...)
只有在那里可见,它们会复制调用它们的范围级别的所有正常变量(称为父范围)。set(... PARENT_SCOPE)
function(xyz _resultVar)
正在设置set(${_resultVar} 1 PARENT_SCOPE)
include()
或macro()
脚本中设置的所有内容都将直接在调用它们的范围内修改变量。 其次是&#34;全局变量缓存&#34;。您需要了解的有关缓存的事项:
CMakeCache.txt
文件中。可以在CMake's GUI应用程序中修改Cache中的值,然后再生成它们。因此,与正常变量相比,它们具有type
和docstring
。我通常不使用GUI,因此我使用set(... CACHE INTERNAL "")
来设置我的全局和持久值。
请注意,INTERNAL
缓存变量类型确实意味着FORCE
在CMake脚本中,如果使用set(... CACHE ... FORCE)
语法,则只能更改现有的缓存条目。这种行为是利用例如由CMake本身,因为它通常不会强制缓存条目本身,因此您可以使用其他值预先定义它。
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_...
命令 - 如果成功 - 将结果写为缓存变量&#34;这样任何呼叫都不会再次搜索&#34; set(MyVar a b c)
为"a;b;c"
,set(MyVar "a b c")
为"a b c"
list()
命令来处理列表functions()
代替macros()
,因为您不希望局部变量显示在父范围内。 project()
和enable_language()
调用设置的。因此,在使用这些命令之前设置一些变量可能很重要。有时只有调试变量才有帮助。以下内容可以为您提供帮助:
printf
命令简单地使用旧message()
调试样式。还有一些随时可以使用CMake自带的模块:CMakePrintHelpers.cmake,CMakePrintSystemInformation.cmake CMakeCache.txt
文件。如果生成环境的实际生成失败,则甚至会生成此文件。cmake --trace ...
以查看CMake的完整解析过程。这是最后一次保留,因为它产生了大量的输出。$ENV{...}
并撰写set(ENV{...} ...)
环境变量$<...>
仅在CMake的生成器写入make环境时进行评估(它与被替换的正常变量进行比较&#34;就地#34;由解析器进行比较)${${...}}
,您可以在变量中提供变量名称并引用其内容。if()
命令)
if(MyVariable)
,您可以直接检查变量是否为true / false(此处不需要封闭${...}
)1
,ON
,YES
,TRUE
,Y
或非零数字,则为真。 0
,OFF
,NO
,FALSE
,N
,IGNORE
,NOTFOUND
,则为假空字符串,或以后缀-NOTFOUND
结尾。if(MSVC)
之类的内容,但对于不知道此语法快捷方式的人来说,这可能会让人感到困惑。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")
为false,因为它的评估结果为if("MSVC" STREQUAL "1")
if(MSVC)
cmake_policy(SET CMP0054 NEW)
设置为&#34;仅在不加引号时将if()
参数解释为变量或关键字。&#34; option()
命令
ON
或OFF
,并且它们允许一些特殊处理,例如dependencies option
与set
命令混淆。给option
的值实际上只是&#34;初始值&#34; (在第一个配置步骤中将一次转移到缓存中),然后由用户通过CMake's GUI进行更改。答案 1 :(得分:11)
以下是一些快速而简单的基本示例。
设置变量:
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}")
答案 2 :(得分:0)
$ENV{FOO}
用于使用,其中FOO是从环境变量中获取的。否则使用${FOO}
,其中FOO是其他变量。对于设置,SET(FOO "foo")
将用于cmake。