CMake指令:source_group()
目录
1.简介
2.核心功能与用法
2.1. 按文件类型分组(如头文件、源文件)
2.2.按目录结构分组(自动映射文件夹层级)
2.3.与 target_sources 结合使用
3. TREE 参数
4.高级用法
5.总结
1.简介
在 CMake 中,source_group
命令用于在集成开发环境(IDE,如 Visual Studio、Xcode、CLion 等)中组织源代码的逻辑分组显示,使项目结构在 IDE 的文件视图中更清晰易读,类似Visual Studio提供的filter机制来分类显示源文件。它不会影响编译逻辑,仅用于调整 IDE 中源文件的分组展示方式。
该命令相当于VS里面给编译需要的文件归类,把一些相同性质的文件放一个类里面,这些“类”,可以在VS 图形界面下左边(一般情况下),看到header文件夹下面的H文件,source文件夹下的C/C++源文件,resource文件夹下的res资源脚本文件。
基本语法:
source_group(<group_name> FILES <file1> <file2> ...)
<group_name>
:指定 IDE 中显示的分组名称(支持嵌套路径,如Headers/Utils
)。<file1> <file2>...
:需要归入该分组的源文件路径(相对当前 CMake 目录)。
2.核心功能与用法
2.1. 按文件类型分组(如头文件、源文件)
# 将所有头文件归入 "Headers" 分组
source_group("Headers" FILES ${PROJECT_SOURCE_DIR}/include/*.h ${PROJECT_SOURCE_DIR}/include/*.hpp)# 将所有源文件归入 "Sources" 分组
source_group("Sources" FILES ${PROJECT_SOURCE_DIR}/src/*.cpp ${PROJECT_SOURCE_DIR}/src/*.cxx)
- 在 IDE 中会显示为独立的
Headers
和Sources
文件夹分组。
2.2.按目录结构分组(自动映射文件夹层级)
若源代码目录结构为:
project/
├─ include/
│ ├─ utils/
│ │ └─ math.h
│ └─ main.h
└─ src/├─ utils/│ └─ math.cpp└─ main.cpp
可通过以下方式在 IDE 中映射目录结构:
# 递归按目录结构分组(需结合 file(GLOB_RECURSE))
file(GLOB_RECURSE HEADERS "${PROJECT_SOURCE_DIR}/include/**/*.h" "${PROJECT_SOURCE_DIR}/include/**/*.hpp")
file(GLOB_RECURSE SOURCES "${PROJECT_SOURCE_DIR}/src/**/*.cpp" "${PROJECT_SOURCE_DIR}/src/**/*.cxx")# 为头文件生成分组路径(如 "include/utils/math.h" 对应 IDE 中的 "include/utils" 分组)
foreach(HEADER ${HEADERS})get_filename_component(REL_PATH ${HEADER} RELATIVE_TO ${PROJECT_SOURCE_DIR}/include)string(REPLACE "\\" "/" GROUP_PATH "include/${REL_PATH}")string(REPLACE "/${REL_PATH}" "" GROUP_PATH ${GROUP_PATH}) # 提取目录部分作为分组名source_group(${GROUP_PATH} FILES ${HEADER})
endforeach()# 同理处理源文件(分组名以 "src/" 开头)
foreach(SOURCE ${SOURCES})get_filename_component(REL_PATH ${SOURCE} RELATIVE_TO ${PROJECT_SOURCE_DIR}/src)string(REPLACE "\\" "/" GROUP_PATH "src/${REL_PATH}")string(REPLACE "/${REL_PATH}" "" GROUP_PATH ${GROUP_PATH})source_group(${GROUP_PATH} FILES ${SOURCE})
endforeach()
- 最终在 IDE 中,文件会按实际目录层级显示在对应的分组下(如
include/utils
和src/utils
分组)。
2.3.与 target_sources
结合使用
通常在使用 target_sources
向目标添加文件前,先用 source_group
定义分组:
add_executable(my_app)# 定义分组
source_group("Headers" FILES ${HEADERS})
source_group("Sources" FILES ${SOURCES})# 添加文件到目标(分组信息会传递给 IDE)
target_sources(my_app PRIVATE ${HEADERS} ${SOURCES})
3. TREE
参数
首先看条命令:
source_group(TREE "${PROJECT_SOURCE_DIR}/include/minidocx"PREFIX "Header Files" FILES ${headers})
source_group
命令是 CMake 中用于在 IDE 中组织源代码显示的高级用法,特别是使用了 TREE
参数 来自动映射目录结构。这条命令的作用是:将 include/minidocx
目录下的头文件按原目录层级映射到 IDE 的 "Header Files" 分组中。
命令解析
source_group(TREE "${PROJECT_SOURCE_DIR}/include/minidocx" # 源目录(作为分组根)PREFIX "Header Files" # 分组前缀(IDE 中显示的顶级分组名)FILES ${headers} # 要分组的文件列表(通常是头文件集合)
)
核心参数说明
1.TREE <directory>
- 指定源目录,CMake 会递归遍历该目录的结构,并以此为基础生成 IDE 中的分组。
- 例如,若源目录为
include/minidocx/utils
,则该目录下的文件会在 IDE 中显示为Header Files/utils
分组。
2.PREFIX <prefix>
- 指定 IDE 中显示的顶级分组名称。所有子分组都会嵌套在这个名称下。
- 例如,设置为
"Header Files"
时,IDE 会显示为:
Header Files/
├─ core/
├─ utils/
└─ format/
3.FILES <files>
- 列出要分组的文件(通常是通过
file(GLOB)
收集的头文件列表)。 - 这些文件必须位于
TREE
指定的目录或其子目录中。
实际效果示例
假设目录结构如下:
project/
└─ include/└─ minidocx/├─ core/│ └─ document.h├─ utils/│ ├─ string_utils.h│ └─ file_utils.h└─ format/└─ xml_writer.h
使用上述命令后,在 Visual Studio 或 CLion 中会显示为:
Header Files/
├─ core/
│ └─ document.h
├─ utils/
│ ├─ string_utils.h
│ └─ file_utils.h
└─ format/└─ xml_writer.h
与传统 source_group
的对比
传统方式需要手动为每个子目录定义分组:
source_group("Header Files\\core" FILES ${headers_core})
source_group("Header Files\\utils" FILES ${headers_utils})
source_group("Header Files\\format" FILES ${headers_format})
而 TREE
参数可以自动处理嵌套结构,避免手动维护大量分组定义,特别适合大型项目。
注意事项:路径匹配要求
FILES
中的文件必须位于TREE
指定的目录或其子目录中,否则会被忽略。- 例如,若
TREE
为include/minidocx
,但FILES
包含src/main.cpp
,则该文件不会被分组。
4.高级用法
1.正则表达式与动态分组
若需按文件名模式(如测试文件、生成文件)分组,可结合 file(GLOB)
和正则表达式:
# 提取所有测试文件并归入 "Tests" 分组
file(GLOB TEST_SOURCES "${PROJECT_SOURCE_DIR}/tests/*.cpp")
string(REGEX REPLACE "${PROJECT_SOURCE_DIR}/" "" TEST_SOURCES "${TEST_SOURCES}") # 转换为相对路径
source_group("Tests" FILES ${TEST_SOURCES})
2.同时处理头文件和源文件
# 头文件分组
source_group(TREE "${PROJECT_SOURCE_DIR}/include/minidocx"PREFIX "Header Files"FILES ${headers}
)# 源文件分组
source_group(TREE "${PROJECT_SOURCE_DIR}/src"PREFIX "Source Files"FILES ${sources}
)
3.排除特定目录
若要排除 include/minidocx/internal
目录,可先过滤文件列表:
file(GLOB_RECURSE headers "${PROJECT_SOURCE_DIR}/include/minidocx/*.h")
list(FILTER headers EXCLUDE REGEX "${PROJECT_SOURCE_DIR}/include/minidocx/internal/")source_group(TREE "${PROJECT_SOURCE_DIR}/include/minidocx"PREFIX "Header Files"FILES ${headers}
)
5.总结
source_group
适合需要多人协作或复杂目录结构的工程。source_group(TREE ...)
更是通过自动映射目录结构,避免了手动维护复杂分组的繁琐工作。提升了项目在 IDE 中的可读性和可维护性。
相关链接
- CMake 官网 CMake - Upgrade Your Software Build System
- CMake 官方文档:CMake Tutorial — CMake 4.0.2 Documentation
- CMake 源码:https://github.com/Kitware/CMake
- CMake 源码:Sign in · GitLab