如何在CMake中将父工程变量传递到子工程?
父CMake工程向子工程传递变量的可行性与实现方法
当然可行!CMake里变量的传递规则取决于变量的作用域类型,我结合你的代码场景详细说明:
一、缓存变量:自动传递到子目录
你最初代码里用的option(FOO "foo var" "MyFoo"),本质是创建了一个缓存变量(CMake里option是set(... CACHE ...)的语法糖)。缓存变量属于全局作用域,会自动被所有子目录继承,所以你的子工程a其实已经能直接访问FOO变量了。
比如你最初的子目录代码:
if("${FOO}" STREQUAL "MyFoo") message("Using Foo from Parent") else() message("Foo not passed from Parent") endif()
理论上应该直接输出Using Foo from Parent,除非你在父目录的option之后又用普通变量(不带CACHE的set)覆盖了FOO——普通变量仅在当前作用域生效,不会传递到子目录。
二、普通变量:需要手动传递
如果你用的是普通变量(没有CACHE关键字的set),比如父目录里写set(FOO "MyFoo"),那这个变量默认只在父目录作用域有效,子目录无法直接访问。这时候有两种可靠的传递方式:
方式1:转为缓存变量
像你更新代码里做的那样,把普通变量转为缓存变量,就能实现全局传递:
# 父目录CMakeLists.txt unset(FOO_VAR CACHE) set(FOO_VAR ${FOO} CACHE STRING "foo variable") add_subdirectory(a)
子目录里直接用${FOO_VAR}就能访问到对应的值。
方式2:在add_subdirectory时显式传递
CMake 3.13+支持在add_subdirectory时通过CMAKE_ARGS显式传递变量,适合需要临时传递值的场景:
# 父目录CMakeLists.txt set(FOO "MyFoo") add_subdirectory(a ${CMAKE_CURRENT_BINARY_DIR}/a CMAKE_ARGS -DFOO=${FOO})
这种方式更灵活,不会污染全局缓存,但内部子目录场景下用缓存变量会更简洁。
三、常见坑点提醒
- 不要混淆普通变量和缓存变量:如果父目录里先定义了缓存变量
FOO,又用set(FOO "Other")定义了普通变量,当前作用域会优先使用普通变量,但子目录仍会读取缓存变量的值。 - 如果要修改已存在的缓存变量,记得加上
FORCE关键字,比如set(FOO "NewValue" CACHE STRING "foo var" FORCE),否则第一次设置后的值不会被覆盖。
内容的提问来源于stack exchange,提问作者Hari
相关产品推荐
相关产品推荐

