CMake的set(PARENT_SCOPE)仅向上一级传值?如何让变量直达根目录?
解决CMake三层目录变量传递到根目录的问题
针对你的场景,这里有几种不需要file(GLOB)的可行方案,按推荐程度排序:
1. 目标驱动的方式(最推荐)
这是现代CMake的最佳实践——通过**目标(target)**管理文件,而非直接传递变量。子子目录将源码打包成对象库或静态库,上层目录通过链接目标来复用代码,根目录无需关心具体文件列表。
示例代码:
- 子子目录(
src/sub/subsub/CMakeLists.txt):
# 创建对象库(仅编译源码,不生成最终库文件) add_library(subsub_objects OBJECT file1.cpp file2.cpp ) # 如果需要对外暴露头文件路径 target_include_directories(subsub_objects PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
- 子目录(
src/sub/CMakeLists.txt):
add_subdirectory(subsub) # 打包子子目录的对象到当前层级的对象库 add_library(sub_objects OBJECT $<TARGET_OBJECTS:subsub_objects>) # 传递头文件路径 target_include_directories(sub_objects PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
- 根目录(
CMakeLists.txt):
add_subdirectory(src/sub) # 链接对象库生成可执行文件 add_executable(myapp main.cpp $<TARGET_OBJECTS:sub_objects>) # 如果用静态库,直接链接即可:target_link_libraries(myapp sub)
这种方式完全避免了变量传递的麻烦,还能自动处理头文件依赖、编译选项等,维护性更强。
2. 逐层向上传递变量
既然PARENT_SCOPE只能传递到上一级,那就通过两层传递让变量到达根目录。这是最直观的新手友好方案。
示例代码:
- 子子目录(
src/sub/subsub/CMakeLists.txt):
# 将文件列表传递到父目录(子目录) set(SUBSUB_SOURCES file1.cpp file2.cpp PARENT_SCOPE )
- 子目录(
src/sub/CMakeLists.txt):
add_subdirectory(subsub) # 再将拿到的变量传递到根目录 set(SUB_SOURCES ${SUBSUB_SOURCES} PARENT_SCOPE)
- 根目录(
CMakeLists.txt):
add_subdirectory(src/sub) # 直接使用传递上来的变量 add_executable(myapp main.cpp ${SUB_SOURCES})
注意:变量名最好加前缀(比如PROJECT_),避免和其他模块的变量冲突。
3. 使用全局属性传递
通过CMake的**全局属性(Global Property)**存储变量,根目录直接读取。这种方式不需要逐层传递,但要注意全局命名空间的污染问题。
示例代码:
- 子子目录(
src/sub/subsub/CMakeLists.txt):
set(SUBSUB_SOURCES file1.cpp file2.cpp) # 设置全局属性,建议用项目前缀避免冲突 set_property(GLOBAL PROPERTY PROJECT_SUBSUB_SOURCES "${SUBSUB_SOURCES}")
- 根目录(
CMakeLists.txt):
add_subdirectory(src/sub/subsub) # 读取全局属性 get_property(SUBSUB_SOURCES GLOBAL PROPERTY PROJECT_SUBSUB_SOURCES) add_executable(myapp main.cpp ${SUBSUB_SOURCES})
4. 用函数封装子目录逻辑
通过自定义函数封装子目录的添加逻辑,利用函数的PARENT_SCOPE直接将变量返回给根目录。
示例代码:
- 根目录(
CMakeLists.txt):
function(add_my_subsub_module) # 函数内部添加子子目录 add_subdirectory(src/sub/subsub) # 将子子目录的变量传递到函数的父作用域(根目录) set(SUBSUB_SOURCES ${SUBSUB_SOURCES} PARENT_SCOPE) endfunction() # 调用函数获取变量 add_my_subsub_module() add_executable(myapp main.cpp ${SUBSUB_SOURCES})
- 子子目录(
src/sub/subsub/CMakeLists.txt):
set(SUBSUB_SOURCES file1.cpp file2.cpp)
内容的提问来源于stack exchange,提问作者Rob S
相关产品推荐
相关产品推荐

