【问题标题】:cmake: how to create visual studio filterscmake:如何创建视觉工作室过滤器
【发布时间】:2016-02-21 20:14:12
【问题描述】:

我已经环顾四周(StackOverflow 等),我正在尝试使用 cmake 生成 Visual Studio 过滤器。我有以下文件夹:

src/math  
src/import  
src/ui  

我想生成类似上面的过滤器。
math:包含 src/math 中的所有 cpp & h 文件
import:包含 src/import 中的所有 cpp & h 文件ui: 包含src/ui中的所有cpp & h文件

我尝试了几种解决方案,但似乎都没有工作!!!

这是CMakeList.txt中代码的最后一个版本:

set(VD_SRC "${VisualDesigner_SOURCE_DIR}/src/visualdesigner")

file(GLOB_RECURSE SRC_UI
    "${VD_SRC}/ui/*.cpp", "${VD_SRC}/ui/*.h")
file(GLOB_RECURSE SRC_IMPORT
    "${VD_SRC}/import/*.cpp",
    "${VD_SRC}/import/*.h")

source_group("ui"            FILES ${SRC_UI})
source_group("import"        FILES ${SRC_IMPORT})

欢迎任何帮助!

【问题讨论】:

  • 我想你想获得文件的目标?或者过滤器是什么意思?这是 Visual Studio 特有的吗?
  • 是的,Visual Studio 在“解决方案”中有某种“文件夹”,他们称之为“过滤器”。它允许组织所有文件,如 VS 中的文件夹!

标签: visual-studio filter cmake


【解决方案1】:

How to set Visual Studio Filters for nested sub directory using cmake

请注意

  • source_group() 命令只能与列出相同源的add_library()add_executable() 命令结合使用(路径必须匹配)
  • source_group() 命令不会检查文件是否确实存在(因此它会接受您提供的任何内容,并且在项目文件生成期间,它会尝试将给定的源组文件名与项目中使用的文件进行匹配)

我已通过添加相应的add_library() 目标来尝试您的代码,它按预期工作(CMake 3.3.2 和 VS2015):

set(VD_SRC "${VisualDesigner_SOURCE_DIR}/src/visualdesigner")

file(GLOB_RECURSE SRC_UI
    "${VD_SRC}/ui/*.cpp"
    "${VD_SRC}/ui/*.h"
)
file(GLOB_RECURSE SRC_IMPORT
    "${VD_SRC}/import/*.cpp"
    "${VD_SRC}/import/*.h"
)

add_library(VisalDesigner ${SRC_UI} ${SRC_IMPORT})

source_group("ui"            FILES ${SRC_UI})
source_group("import"        FILES ${SRC_IMPORT})

结果

这是取自Visual Studio as an editor for CMake friendly project的更通用的版本:

set(_src_root_path "${VisualDesigner_SOURCE_DIR}/src/visualdesigner")
file(
    GLOB_RECURSE _source_list 
    LIST_DIRECTORIES false
    "${_src_root_path}/*.c*"
    "${_src_root_path}/*.h*"
)

add_library(VisualDesigner ${_source_list})

foreach(_source IN ITEMS ${_source_list})
    get_filename_component(_source_path "${_source}" PATH)
    file(RELATIVE_PATH _source_path_rel "${_src_root_path}" "${_source_path}")
    string(REPLACE "/" "\\" _group_path "${_source_path_rel}")
    source_group("${_group_path}" FILES "${_source}")
endforeach()

【讨论】:

    【解决方案2】:

    我发现这样做更容易,并认为它可能对其他人有所帮助。确保您使用的是最新版本的 CMAKE。

    file(GLOB_RECURSE _source_list *.cpp* *.h* *.hpp*)
    foreach(_source IN ITEMS ${_source_list})
        get_filename_component(_source_path "${_source}" PATH)
        string(REPLACE "${CMAKE_SOURCE_DIR}" "" _group_path "${_source_path}")
        string(REPLACE "/" "\\" _group_path "${_group_path}")
        source_group("${_group_path}" FILES "${_source}")
    endforeach()
    

    【讨论】:

    • 这真的很好用!我将它与 Visual Studio 2017 和 CMake 3.8 一起使用
    • 使用 cmake 3.14.1 和 Visual Studio 2019,这行得通,除了我必须将标题添加到 add_exectuableadd_library。如果我不这样做,过滤器/VS 项目中只会显示 .cpp 文件。我在docs 中找不到任何关于此的内容。也许是一个错误,或者我错过了一些东西。
    【解决方案3】:

    从 CMake 3.8 开始,source_group 命令提供了一个 TREE 参数来递归搜索源的文件路径以构建源组以匹配您的文件系统结构。现在,解决方案是 lot 更清洁,无需循环:

    set(VD_SRC "${VisualDesigner_SOURCE_DIR}/src/visualdesigner")
    file(GLOB_RECURSE UI_IMPORT_MATH_SRCS
        "${VD_SRC}/ui/*.cpp"
        "${VD_SRC}/ui/*.h"
        "${VD_SRC}/import/*.cpp"
        "${VD_SRC}/import/*.h"
        "${VD_SRC}/math/*.cpp"
        "${VD_SRC}/math/*.h"
    )
    
    add_library(VisualDesigner ${UI_IMPORT_MATH_SRCS})
    
    # Create the source groups for source tree with root at VD_SRC.
    source_group(TREE ${VD_SRC} FILES ${UI_IMPORT_MATH_SRCS})
    

    此外,如果您觉得有用,请查看可以与 source_group 一起使用的新 PREFIX 参数。

    免责声明:我建议尽可能不要使用GLOB (see here)。

    【讨论】:

    【解决方案4】:

    对于那些想要在“头文件”和“源文件”下创建它们的人:

    您可以使用source_group。这是一个具体的例子。

    假设您的目录结构如下:

    |-include
        | some.h
        |-sub
           | someother.h 
    |-src
       | some.cpp
       |-sub
          |-someother.cpp
    

    收集文件(有些人 - 包括文档 - 不鼓励使用 GLOB,但我把它留给你,如果你愿意,你可以逐个列出它们,尽管我发现 GLOB 很多次都很好):

    file(GLOB HEADER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h")
    file(GLOB HEADER_FILES_SUB "${CMAKE_CURRENT_SOURCE_DIR}/include/sub/*.h")
    file(GLOB SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h")
    file(GLOB SOURCE_FILES_SUB "${CMAKE_CURRENT_SOURCE_DIR}/src/sub/*.h")
    
    # Setup your library or executable:
    add_library(MY_LIB ${HEADER_FILES} ${HEADER_FILES_SUB}
                       ${SOURCE_FILES} ${SOURCE_FILES_SUB})
    
    # Here's the important part ("Header Files" and "Source Files" are literals.)
    source_group("Header Files\\sub" ${HEADER_FILES_SUB})
    source_group("Source Files\\sub" ${SOURCE_FILES_SUB})
    

    【讨论】:

    • @swdon 提出的解决方案是最正确和最简单的解决方案 - 以前的解决方案对我不起作用。
    • 我认为你错过了FILES source_group("Header Files\\sub" FILES ${HEADER_FILES_SUB})
    【解决方案5】:

    以上所有答案通常都有效。如果您有多个库目标并希望为每个 targets 创建精美的过滤器,那么您需要小心一点。

    经过大量的头撞后,我认为您应该将 source_group 调用保留在您执行 add_library(target ..)add_executable(target ..) 的同一 CMakeLists.txt 文件中。您可以在任何地方缓存(内部)“源\标题列表”并在此处使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-10
      • 2017-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-11
      • 1970-01-01
      相关资源
      最近更新 更多