cmake source_group 分组功能辅助函数
cmake 的 source_group 可以对VS工程的源码文件进行分组,使用方法参考
https://cmake.org/cmake/help/latest/command/source_group.html
但是该命令使用起来很不方便,必须跟 add_executable 或者 add_library 写在同一个CMakeLists.txt文件中才能生效,无法在 add_subdirectory 引入的子 CMakeLists.txt 使用。原因是官方文档中所述:The group is scoped in the directory where the command is called, and applies to sources in targets created in that directory。
为了实现类似 target_source 命令这种层级化的使用方式,开发了以下辅助函数(函数在文件SourceGroup.cmake 中)
# 添加分组(命令参数含义可参考 source_group 命令)
# group_name 分组名称
# FILES 分组包含的文件
# TREE 按给定的目录结构组织分组文件
function(add_source_group group_name)if(DEFINED group_name AND "${group_name}" STREQUAL "_add_source_group_<EMPTYNAME>")message(FATAL_ERROR "group name cannot be ${group_name}.")endif ()cmake_parse_arguments(_add_source_group """TARGET""FILES;TREE"${ARGN})# 分组名称get_property(group_names GLOBAL PROPERTY _add_source_group_names_${_add_source_group_TARGET})if(DEFINED group_name AND "${group_name}" STREQUAL "")if(NOT DEFINED _add_source_group_TREE)message(FATAL_ERROR "group name cannot be empty.")else()list(APPEND group_names "_add_source_group_<EMPTYNAME>")endif()else()list(APPEND group_names ${group_name})endif()set_property(GLOBAL PROPERTY _add_source_group_names_${_add_source_group_TARGET} ${group_names})# 分组树目录get_property(group_trees GLOBAL PROPERTY _add_source_group_trees_${_add_source_group_TARGET})if (DEFINED _add_source_group_TREE)list(APPEND group_trees ${_add_source_group_TREE})else()list(APPEND group_trees "_add_source_group_<EMPTYTREE>")endif()set_property(GLOBAL PROPERTY _add_source_group_trees_${_add_source_group_TARGET} ${group_trees})# 分组文件if (_add_source_group_FILES)string(REPLACE ";" "|" GROUP_SOURCES "${_add_source_group_FILES}")get_property(group_files GLOBAL PROPERTY _add_source_group_files_${_add_source_group_TARGET})list(APPEND group_files "${GROUP_SOURCES}")set_property(GLOBAL PROPERTY _add_source_group_files_${_add_source_group_TARGET} ${group_files})endif() endfunction()# 应用分组(在所有分组添加完毕后调用)
function(apply_source_group)if(${ARGC} GREATER 1)message(FATAL_ERROR "too many parameters for apply_Source_group.")endif ()if (${ARGC} EQUAL 1)set(target_name ${ARGV0})else()set(target_name "")endif()get_property(group_names GLOBAL PROPERTY _add_source_group_names_${target_name})get_property(group_trees GLOBAL PROPERTY _add_source_group_trees_${target_name})get_property(group_files GLOBAL PROPERTY _add_source_group_files_${target_name})#message(apply_source_group_values: ${group_names}, ${group_trees}, ${group_files})# 确保两个列表长度相同list(LENGTH group_names NAME_LENGTH)list(LENGTH group_files FILE_LENGTH)if(NOT ${NAME_LENGTH} EQUAL ${FILE_LENGTH})message(FATAL_ERROR "source group names and files length must be equal.")endif()# 遍历列表索引math(EXPR MAX_INDEX "${NAME_LENGTH} - 1")foreach(INDEX RANGE ${MAX_INDEX})list(GET group_names ${INDEX} GROUP_NAME)list(GET group_trees ${INDEX} GROUP_TREE)list(GET group_files ${INDEX} GROUP_FILE)string(REPLACE "|" ";" GROUP_FILE "${GROUP_FILE}")if("${GROUP_TREE}" STREQUAL "_add_source_group_<EMPTYTREE>")source_group(${GROUP_NAME} FILES ${GROUP_FILE})else()if("${GROUP_NAME}" STREQUAL "_add_source_group_<EMPTYNAME>")source_group(TREE ${GROUP_TREE} FILES ${GROUP_FILE})else()source_group(TREE ${GROUP_TREE} PREFIX ${GROUP_NAME} FILES ${GROUP_FILE})endif()endif()endforeach()
endfunction()# 重置分组
function(reset_source_group)if(${ARGC} GREATER 1)message(FATAL_ERROR "too many parameters for reset_source_group.")endif ()if (${ARGC} EQUAL 1)set(target_name ${ARGV0})else()set(target_name "")endif()set_property(GLOBAL PROPERTY _add_source_group_names_${target_name} "")set_property(GLOBAL PROPERTY _add_source_group_trees_${target_name} "")set_property(GLOBAL PROPERTY _add_source_group_files_${target_name} "")
endfunction()
辅助函数使用方法
1. 在根 CMakeLists.txt 中引入辅助函数
include(SourceGroup.cmake)
2. 调用 add_source_group 设置需要分组的源码文件
add_source_group(<name> [TARGET <target>] [TREE <root>] FILES <src>...)
add_source_group 可在根 CMakeLists.txt 及子 CMakeLists.txt 中使用。
TARGET 参数在多工程时用于区分不同工程的分组设置
如果不设置参数 [TREE <root>] 对应 source_group 的
source_group(<name> FILES <src>...)
如果设置参数 [TREE <root>] 对应 source_group 的
source_group(TREE <root> [PREFIX <prefix>] FILES <src>...)
此时 <name> 对应 <prefix> 参数
3. 调用 apply_source_group 应用分组
apply_source_group([TARGET <target>])
apply_source_group 必须跟 add_executable 或者 add_library 写在同一个CMakeLists.txt文件中。
完整示例
https://download.csdn.net/download/ayang1986/90803035
效果如下图: