CMake配置Visual Studio解决方案过滤器:实现含头文件的目录结构展示及非代码资源文件夹添加
我完全懂你想要在VS里用CMake生成和本地目录结构一致的解决方案过滤器的心情——毕竟原生CMake视图的操作体验确实不如传统VS解决方案顺手。针对你遇到的头文件不显示、过滤器层级不对的问题,还有最后提到的资源文件夹需求,我给你一步步拆解解决办法:
一、先解决核心问题:头文件不显示的原因及修复
你当前的配置有几个关键疏漏,直接导致了头文件和部分目录没出现在VS里:
1. 漏加了vendor文件到目标集合
看你的代码,你用FILE(GLOB_RECURSE)收集了vendor_files,但最后把all_sources传给source_group时,没把vendor_files加进去!这就导致vendor目录的头文件(甚至cpp文件)都没被纳入过滤器和VS解决方案。
修正这行代码:
set(all_sources ${source_files} ${include_files} ${vendor_files} ${glad_files} ${imgui_files} ${stb_image_files} )
2. GLOB_RECURSE的路径写法错误,没收集到子目录文件
你现在写的include/*.hpp只会匹配include根目录下的头文件,不会递归子目录!CMake的GLOB_RECURSE需要用**通配符来表示“所有子目录”,才能收集到嵌套目录里的文件。
修正文件收集的写法:
# 收集src目录下所有cpp/c文件(含子目录) FILE(GLOB_RECURSE source_files ${CMAKE_CURRENT_SOURCE_DIR}/src/**/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/**/*.c ) # 收集include目录下所有hpp/h文件(含子目录) FILE(GLOB_RECURSE include_files ${CMAKE_CURRENT_SOURCE_DIR}/include/**/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/**/*.h ) # 收集vendor1目录下所有cpp/hpp文件(含子目录,后续新增子目录也能自动匹配) FILE(GLOB_RECURSE vendor_files ${CMAKE_CURRENT_SOURCE_DIR}/vendor/vendor1/**/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/vendor/vendor1/**/*.hpp )
3. 必须将所有文件关联到CMake目标
这是最容易忽略的点:CMake只会把**添加到target(可执行文件/库)**的文件传递给VS生成解决方案。你要确保把all_sources传给add_executable或add_library:
add_executable(YourProjectName ${all_sources})
做完这三步,再删除CMakeCache.txt和整个build目录,重新配置CMake,你应该就能看到include目录、所有头文件(包括vendor下的)都出现在VS过滤器里了。
二、替代GLOB的更规范写法(推荐长期使用)
你也提到用GLOB是临时方案——确实,GLOB的问题是新增文件后CMake不会自动检测,必须手动重新运行配置。所以长期来看,更可靠的做法是手动指定文件,搭配更灵活的source_group设置:
# 1. 先定义目标 add_executable(YourProjectName) # 2. 给目标添加源文件和头文件,按目录分类 target_sources(YourProjectName PRIVATE # src目录文件 src/src.cpp src/subdirectory/xxx.cpp # include目录文件 include/source.hpp include/subdirectory/xxx.hpp # vendor目录文件 vendor/vendor1/vendor.cpp vendor/vendor1/vendor.hpp ) # 3. 为每个目录生成对应过滤器,子目录会自动嵌套 # src目录的过滤器 source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/src PREFIX "src" FILES src/src.cpp src/subdirectory/xxx.cpp ) # include目录的过滤器 source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/include PREFIX "include" FILES include/source.hpp include/subdirectory/xxx.hpp ) # vendor目录的过滤器 source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/vendor PREFIX "vendor" FILES vendor/vendor1/vendor.cpp vendor/vendor1/vendor.hpp )
这种写法虽然麻烦一点,但CMake会自动检测文件变化,而且不会出现GLOB漏收文件的问题。
三、添加assets资源文件夹到VS过滤器
要让VS显示assets文件夹及其子目录,需要把资源文件添加到目标,但标记为“不编译”,避免CMake尝试编译它们:
# 1. 收集assets目录下的所有文件(含子目录) file(GLOB_RECURSE asset_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} assets/**/* ) # 2. 把资源文件添加到目标 target_sources(YourProjectName PRIVATE ${asset_files}) # 3. 标记资源文件为“仅头文件”,告诉CMake不要编译它们 set_source_files_properties(${asset_files} PROPERTIES HEADER_FILE_ONLY TRUE ) # 4. 生成assets对应的过滤器,保持和本地一致的目录结构 source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/assets PREFIX "assets" FILES ${asset_files})
这样,assets文件夹就会出现在VS解决方案的过滤器里,和本地目录结构完全一致,而且不会被编译。
最后提醒
每次修改CMakeLists.txt或者新增文件后,记得删除CMakeCache.txt和整个build目录,然后重新运行CMake配置——CMake的缓存有时候会导致修改不生效,这是新手常踩的坑。
内容来源于stack exchange




