如何从子目录CMakeLists.txt导入变量到顶层CMakeLists.txt?
解决CMake子目录变量传递及源文件组织问题
方案一:通过PARENT_SCOPE传递变量并修正路径
默认情况下,set()定义的变量仅在当前作用域生效。要让顶层CMakeLists.txt获取子目录的变量,需在子目录的set()命令中添加PARENT_SCOPE参数,同时修正源文件路径(避免顶层找不到子目录文件):
子目录subfolder/CMakeLists.txt修改为:
set(SUB_SRC ${CMAKE_CURRENT_LIST_DIR}/A.h ${CMAKE_CURRENT_LIST_DIR}/A.cpp ${CMAKE_CURRENT_LIST_DIR}/B.h ${CMAKE_CURRENT_LIST_DIR}/B.cpp PARENT_SCOPE )
${CMAKE_CURRENT_LIST_DIR}表示当前CMakeLists.txt所在目录,确保路径指向正确。PARENT_SCOPE将变量提升到父级作用域(即顶层CMakeLists.txt所在作用域)。
顶层CMakeLists.txt无需修改原include逻辑:
include(subfolder/CMakeLists.txt) add_library(foo STATIC ${SUB_SRC} C.h C.cpp D.h D.cpp ) target_include_directories(foo INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
方案二:使用add_subdirectory创建对象库(更符合CMake规范)
这种方式无需传递变量,而是将子目录的源文件打包为对象库,顶层直接复用该对象库的编译结果,更契合CMake模块化设计:
子目录subfolder/CMakeLists.txt修改为:
add_library(subfolder_obj OBJECT A.h A.cpp B.h B.cpp ) # 若子目录头文件需要被顶层访问,添加包含目录 target_include_directories(subfolder_obj PUBLIC ${CMAKE_CURRENT_LIST_DIR})
顶层CMakeLists.txt修改为:
add_subdirectory(subfolder) add_library(foo STATIC $<TARGET_OBJECTS:subfolder_obj> C.h C.cpp D.h D.cpp ) target_include_directories(foo INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) # 继承子目录对象库的包含目录(按需添加) target_link_libraries(foo PUBLIC subfolder_obj)
- 对象库
subfolder_obj仅编译源文件但不生成最终库,顶层通过$<TARGET_OBJECTS:>引用其编译产物。 - 该方式更利于子目录代码独立维护,后续子目录新增文件只需修改自身CMakeLists.txt即可。
注意事项
- 避免使用
file(GLOB)自动收集源文件:虽然写法简洁,但CMake不会自动识别新增源文件,必须手动重新运行CMake才能生效,不利于项目维护。 - 路径正确性:无论哪种方案,都要确保源文件路径指向准确,避免因相对路径导致文件找不到的问题。
内容的提问来源于stack exchange,提问作者Abdo21
相关产品推荐
相关产品推荐

