CMake中如何区分变量与值?同名目录与目标使用困惑
CMake常见疑问解答:无引号字符串与跨作用域目标引用
一、关于CMake中无引号字符串的问题
CMake的语法逻辑更偏向脚本语言,和常规编程语言的字符串规则不同:
- 当参数是不含空格、特殊字符(如
$、;、@)的标识符、路径或关键字时,不需要用引号包裹。比如你代码里的MathFunctions、cxx_std_11、TRUE都属于这类情况。 - 只有当参数包含空格、特殊字符,或者需要确保变量展开后整体作为单个参数时,才需要用双引号包裹,比如
"${PROJECT_BINARY_DIR}/src",这里的引号是为了避免路径被拆分成多个参数。
二、同名目录与目标的区分及跨作用域引用规则
你遇到的MathFunctions既是目录名又是目标名的情况,CMake通过上下文和全局作用域规则来区分,具体规则如下:
1. 目录名与目标名的上下文区分
add_subdirectory(MathFunctions):这里的MathFunctions是目录路径,CMake会在当前CMakeLists.txt所在目录下查找同名子目录,执行其中的CMakeLists.txt脚本。- 子目录中
add_library(MathFunctions mysqrt.cxx):这里的MathFunctions是目标名称,CMake会创建一个库目标(默认静态库),这个目标名称在整个项目中全局唯一,不能重复创建。
2. 跨作用域目标引用规则
CMake中的目标是全局可见的:
- 当你通过
add_subdirectory执行子目录的CMakeLists.txt后,子目录中创建的所有目标会自动加入全局目标空间,父目录(以及后续所有被处理的CMakeLists.txt)都可以直接通过目标名称引用它。 - 你代码中
list(APPEND EXTRA_LIBS MathFunctions)里的MathFunctions是字符串,但target_link_libraries这类命令会优先将字符串参数匹配已创建的目标。因为子目录已经创建了MathFunctions目标,所以CMake会将这个字符串解析为目标,而非系统库文件名。
3. 核心规则总结
- 目标名称全局唯一:同一项目中不能创建两个同名目标,否则CMake会直接报错。
- 目标全局可见:子目录创建的目标,父目录无需特殊语法即可直接引用。
- 字符串自动匹配目标:对于接受目标作为参数的命令(如
target_link_libraries、target_include_directories),CMake会优先将字符串参数与已存在的目标匹配,匹配成功则按目标处理,失败则按普通字符串(如系统库名)处理。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

