设置和使用变量的CMake语法是什么?

Civ*_*Fan 143 cmake

我问这个是下次我使用CMake的时候提醒自己的.它永远不会坚持,谷歌的结果也不是很好.

在CMake中设置和使用变量的语法是什么?

Flo*_*ian 245

在编写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})

文档

范围或"我的变量有什么价值?"

首先是"正常变量"以及您需要了解的关于其范围的事项:

  • 普通变量是可见的CMakeLists.txt,他们在一切从那里叫(集和add_subdirectory(),include(),macro()function()).
  • add_subdirectory()function()命令是特殊的,因为他们的开拓自己的范围.
    • 意义变量set(...)只在那里可见,它们复制了它们被调用的范围级别的所有正常变量(称为父范围).
    • 因此,如果您位于子目录或函数中,则可以使用父作用域修改已存在的变量 set(... PARENT_SCOPE)
    • 您可以通过将变量名称作为函数参数传递来在函数中使用它.一个例子function(xyz _resultVar)是设置set(${_resultVar} 1 PARENT_SCOPE)
  • 另一方面,您设置的所有内容include()macro()脚本将直接在调用它们的范围内修改变量.

其次是"全局变量缓存".您需要了解的有关缓存的事项:

  • 如果在当前作用域中没有定义具有给定名称的普通变量,则CMake将查找匹配的Cache条目.
  • 缓存值存储在CMakeCache.txt二进制输出目录中的文件中.
  • 在生成之前,可以在CMake的GUI应用程序中修改Cache中的值.因此,与正常变量相比,它们具有a type和a docstring.我通常不使用GUI,所以我set(... CACHE INTERNAL "")用来设置我的全局和持久值.

    请注意,INTERNAL缓存变量类型确实意味着FORCE

  • 在CMake脚本中,如果使用set(... CACHE ... FORCE)语法,则只能更改现有的Cache条目.这种行为是由CMake本身使用的,因为它通常不会强制Cache条目本身,因此您可以使用其他值预先定义它.

  • 您可以使用命令行使用语法设置Cache中的条目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_...命令-如果成功的话-不要写自己的结果缓存变量"这样没有呼叫将再次搜索"
  • CMake中的列表只是带有分号分隔符的字符串,因此引号很重要
    • set(MyVar a b c)"a;b;c"set(MyVar "a b c")"a b c"
    • 建议您在要将列表作为列表时始终使用带有一个例外的引号
    • 通常更喜欢list()处理列表的命令
  • 整个范围问题如上所述.特别是建议使用functions()而不是macros()因为您不希望局部变量显示在父作用域中.
  • CMake使用的很多变量都是使用project()enable_language()调用设置的.因此,在使用这些命令之前设置一些变量可能很重要.
  • 环境变量可能与CMake生成make环境的位置以及make文件的使用时间不同.
    • 环境变量的更改不会重新触发生成过程.
    • 特别是生成的IDE环境可能与命令行不同,因此建议将环境变量转换为缓存的内容.

有时只有调试变量有帮助.以下内容可以帮助您:

  • 只需使用命令即可使用旧的printf调试样式message().CMake本身附带了一些随时可用的模块:CMakePrintHelpers.cmake,CMakePrintSystemInformation.cmake
  • 查看CMakeCache.txt二进制输出目录中的文件.如果make环境的实际生成失败,甚至会生成此文件.
  • 使用variable_watch()查看读/写/删除变量的位置.
  • 查看目录属性CACHE_VARIABLESVARIABLES
  • 打电话cmake --trace ...来查看CMake的完整解析过程.这是最后一种储备,因为它会产生大量的输出.

特殊语法

  • 环境变量
    • 您可以读取$ENV{...}和写入set(ENV{...} ...)环境变量
  • 发电机表达
    • 生成器表达式$<...>仅在CMake的生成器写入make环境时进行评估(它与解析器"就地"替换的普通变量进行比较)
    • 非常方便,例如在编译器/链接器命令行和多配置环境中
  • 参考
    • 有了${${...}}你可以给一个变量的变量名,并引用其内容.
    • 通常在将变量名称作为函数/宏参数时使用.
  • 常量值(参见if()命令)
    • 有了if(MyVariable)你可以直接检查变量真/假(无需这里封闭${...})
    • 真,如果常数是1,ON,YES,TRUE,Y,或一个非零数.
    • 假如果常数0,OFF,NO,FALSE,N,IGNORE,NOTFOUND,空字符串,或后缀结尾-NOTFOUND.
    • 这种语法通常用于类似的东西if(MSVC),但对于不知道这种语法快捷方式的人来说可能会让人感到困惑.
  • 递归替换
    • 您可以使用变量构造变量名称.在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)
    • 好消息是,随着政策CMP0054的引入,这在CMake 3.1中得到了修复.我建议始终设置cmake_policy(SET CMP0054 NEW)为"仅if()在不引用时将参数解释为变量或关键字".
  • option()命令
    • 主要只是缓存的字符串,只能是ON或者OFF它们允许一些特殊处理,例如依赖
    • 要注意,不要弄错了optionset命令.给定的值option实际上只是"初始值"(在第一个配置步骤中一次转移到缓存),然后由用户通过CMake的GUI进行更改.

参考


Civ*_*Fan 14

以下是一些快速而肮脏的基本示例.

一个项目变量

设置变量:

SET(INSTALL_ETC_DIR "etc")
Run Code Online (Sandbox Code Playgroud)

使用变量:

SET(INSTALL_ETC_CROND_DIR "${INSTALL_ETC_DIR}/cron.d")
Run Code Online (Sandbox Code Playgroud)

多项变量(即列表)

设置变量:

SET(PROGRAM_SRCS
        program.c
        program_utils.c
        a_lib.c
        b_lib.c
        config.c
        )
Run Code Online (Sandbox Code Playgroud)

使用变量:

add_executable(program "${PROGRAM_SRCS}")
Run Code Online (Sandbox Code Playgroud)

CMake关于变量的文档


par*_*ish 6

$ENV{FOO}对于使用,FOO从环境变量中获取。否则使用 as ${FOO},其中FOO是其他变量。对于设置,SET(FOO "foo")将在 CMake 中使用。


归档时间:

查看次数:

106724 次

最近记录:

5 年,11 月 前