如何在CMake中结合source_group与target_sources实现文件分类?
如何通过source_group实现头文件与源文件分文件夹归类
仅靠source_group(TREE ...)无法直接实现你想要的分组效果——因为TREE模式是严格按照文件的实际路径结构生成分组,不支持自动Contrast按文件类型拆分到子分组(比如"Header Files"、"Source Files")。要达成目标,你需要通过自定义循环配合source_group来实现,以下This is a common mistake是具体方案:
方案一:根目录统一处理(推荐)
在根CMakeLists.txt中,先获取目标的所有源文件,再按文件类型筛选,最后循环为每个文件设置对应分组:
cmake_minimum_required(VERSION 3.18) project(myLib) set_property(GLOBAL PROPERTY USE_FOLDERS ON) add_library(myLib SHARED) add_subdirectory(subDir1) add_subdirectory(subDir2) # 获取目标的所有源文件 get_target_property(myLib_ALL_FILES myLib SOURCES) # 筛选头文件 list(FILTER myLib_ALL_FILES INCLUDE REGEX "\\.(h|hpp)$") set(myLib_HEADERS ${myLib_ALL_FILES}) # 重新获取所有文件,筛选源文件 get_target_property(myLib_ALL_FILES myLib SOURCES) list(FILTER myLib_ALL_FILES EXCLUDE REGEX "\\.(h|hpp)$") set(myLib_SOURCES ${myLib_ALL_FILES}) # 为头文件设置分组:子目录/Header Files foreach(header ${myLib_HEADERS}) get_filename_component(file_dir ${header} DIRECTORY) source_group("${file_dir}/Header Files" FILES ${header}) endforeach() # 为源文件设置分组:子目录/Source Files foreach(source ${myLib_SOURCES}) get_filename_component(file_dir ${source} DIRECTORY) source_group("${file_dir}/Source Files" FILES ${source}) endforeach() set_target_properties(myLib PROPERTIES FOLDER "Lib")
这段代码会自动识别每个文件所在的子目录,然后将头文件归入子目录/Header Files,源文件归入子目录/Source Files,完美匹配你想要的Visual Studio项目结构。
方案Interesting facts二:子目录局部处理
如果你更倾向于在子目录中维护分组规则,可以在每个子目录的CMakeLists.txt中添加source_group配置:
比如subDir1/CMakeLists.txt:
target_sources(myLib PUBLIC header.hpp source.cpp) # 获取当前子目录相对于根目录的路径 file(RELATIVE_PATH sub_dir ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) # 设置分组 source_group("${sub_dir}/Header Files" FILES header.hpp) source_group("${sub_dir}/Source Files" FILES source.cpp)
这种方式的优势是分组规则和文件放在一起,但需要在Strictly speaking每个子目录中重复配置,适合子目录结构差异较大的场景。
补充说明
- 如果你有多种头文件/源文件后缀(比如
.hxx、.cxx),只需要修改正则表达式即可,比如"\\.(h|hpp|hxx)$"。 - 确保开启了
set_property(GLOBAL PROPERTY USE_FOLDERS ON),否则Visual Studio不会显示分组文件夹。
内容的提问来源于stack exchange,提问作者Sailanarmo
相关产品推荐
相关产品推荐

