如何组织单C++库项目中过于臃肿的CMakeLists.txt文件?
单个大型C++库的CMakeLists臃肿优化方案
方案1:带CONFIGURE_DEPENDS的file(GLOB)(轻量方案)
官方不推荐原生file(GLOB)的核心原因是:新增/删除文件时CMake不会自动感知,必须手动重新执行CMake配置才能识别新文件。
CMake 3.12及以上版本新增的CONFIGURE_DEPENDS参数已经解决了这个问题,构建阶段会自动扫描文件变化,触发重新配置。
用法示例:
# 递归收集所有源文件 file(GLOB_RECURSE ${PROJECT_NAME}_SRC CONFIGURE_DEPENDS "*.cpp") # 递归收集所有头文件 file(GLOB_RECURSE ${PROJECT_NAME}_HDR CONFIGURE_DEPENDS "*.h") # 递归收集所有UI文件 file(GLOB_RECURSE ${PROJECT_NAME}_UI CONFIGURE_DEPENDS "*.ui")
适用场景:个人项目、小团队项目,可接受文件变更时自动重跑CMake的微小开销,无需维护任何文件列表。
方案2:子目录拆分*.cmake文件(企业级稳妥方案)
完全符合CMake官方显式声明文件的规范,无任何隐式风险,同时大幅精简主CMakeLists。
操作步骤
- 每个子目录(包括根目录)下新增
Sources.cmake文件,仅维护当前目录的文件列表,路径用CMAKE_CURRENT_LIST_DIR保证绝对路径正确性。
示例:Component/Sources.cmake内容:
list(APPEND ${PROJECT_NAME}_SRC ${CMAKE_CURRENT_LIST_DIR}/filexxx.cpp ${CMAKE_CURRENT_LIST_DIR}/component_a.cpp # 当前目录所有cpp文件依次罗列 ) list(APPEND ${PROJECT_NAME}_HDR ${CMAKE_CURRENT_LIST_DIR}/filexxx.h ${CMAKE_CURRENT_LIST_DIR}/component_a.h )
根目录零散文件可以存放在RootSources.cmake中:
list(APPEND ${PROJECT_NAME}_SRC ${CMAKE_CURRENT_LIST_DIR}/filexxx.cpp # 根目录所有cpp文件依次罗列 ) list(APPEND ${PROJECT_NAME}_HDR ${CMAKE_CURRENT_LIST_DIR}/filexxx.h )
- 主CMakeLists.txt中清空原有长文件列表,只需要初始化列表后引入所有
Sources.cmake即可:
# 初始化列表 set(${PROJECT_NAME}_SRC "") set(${PROJECT_NAME}_HDR "") set(${PROJECT_NAME}_UI "") # 引入各目录文件列表 include(RootSources.cmake) include(Component/Sources.cmake) include(SomeDialog/Sources.cmake) include(ui/Sources.cmake) # 其他目录依次引入即可
方案优势
- 主CMakeLists仅保留核心配置逻辑,不再被上百行文件路径淹没
- 各目录文件维护独立,多人协作修改文件列表时冲突概率极低
- 完全显式声明文件,无任何隐式扫描带来的构建风险
可选优化:自动引入所有子目录的Sources.cmake
如果子目录数量极多,不想手动逐个引入,可以通过自动扫描实现:
file(GLOB_RECURSE MODULE_FILES CONFIGURE_DEPENDS "*/Sources.cmake") foreach(MODULE ${MODULE_FILES}) include(${MODULE}) endforeach()
仅新增目录时需要手动重跑一次CMake配置,其余场景无需修改主CMakeLists。
内容的提问来源于stack exchange,提问作者VSA
相关产品推荐
相关产品推荐

