如何使用cmake为嵌套子目录设置Visual Studio过滤器

时间:2015-07-15 06:09:48

标签: c++ visual-studio visual-studio-2012 cmake

我有以下结构

Main (dir)
      +-- CMakeLists.txt
      +-- File.cpp
      +-- File.hpp
      +-- Dir (dir)
          +-- CMakeLists.txt
          +-- File1.cpp
          +-- File1.hpp
          +-- File2.cpp
          +-- File2.hpp

主要/的CMakeLists.txt

CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11)
PROJECT(Main)
FILE(GLOB SOURCE
    "*.hpp"
    "*.cpp"
)

ADD_SUBDIRECTORY(Dir)
ADD_EXECUTABLE(Main ${SOURCE})

主要/风向/的CMakeLists.txt

FILE(GLOB LOCAL_SOURCE
    "*.hpp"
    "*.cpp"
)
SET(SOURCE
    ${SOURCE}
    ${LOCAL_SOURCE}
    PARENT_SCOPE
)

它在Visual Studio中生成了以下结构 enter image description here

我想要的是什么:

enter image description here enter image description here

我尝试了什么:

Main / CMakeLists.txt

CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11)
PROJECT(Main)
FILE(GLOB LOCAL_SOURCE
    "*.hpp"
    "*.cpp"
)

SET(SOURCE 
    ${LOCAL_SOURCE}
)

ADD_SUBDIRECTORY(Dir)

SOURCE_GROUP(Main FILES ${LOCAL_SOURCE})
ADD_EXECUTABLE(Main ${SOURCE})

主/风向/的CMakeLists.txt

FILE(GLOB LOCAL_SOURCE
    "*.hpp"
    "*.cpp"
)
SET(SOURCE
    ${SOURCE}
    ${LOCAL_SOURCE}
    PARENT_SCOPE
)

SOURCE_GROUP(Dir FILES ${LOCAL_SOURCE})

我得到了什么:

enter image description here

请帮我解决这个问题。

  • 我不想在具有过滤器的主目录中使用单个CmakeFile.txt
  • 实际结构是多层深嵌套结构。因此,请建议适用于任何级别子目录的解决方案

4 个答案:

答案 0 :(得分:17)

有几个随时可用或适应性强的解决方案来模仿源树行为,就像在Eclipse中使用CMake for Visual Studio(例如来自Zobra的ADD_SRC_SUBFOLDER DESTINATION_SRCS或来自Luca的GroupSources)。

以下是我的缩减版本用于您的用例:

cmake_minimum_required(VERSION 2.8.10)

project(Main CXX)

set(
    source_list
    "File.cpp"
    "File.hpp"
    "Dir/File1.cpp"
    "Dir/File1.hpp"
    "Dir/File2.cpp"
    "Dir/File2.hpp"
)

add_executable(Main ${source_list})

foreach(source IN LISTS source_list)
    get_filename_component(source_path "${source}" PATH)
    string(REPLACE "/" "\\" source_path_msvc "${source_path}")
    source_group("${source_path_msvc}" FILES "${source}")
endforeach()

请参阅source_group()的文档,您必须为子目录提供双反斜杠。

为什么我将file(GLOB ...)替换为所有源文件的专用列表,我想引用CMake的file()命令文档:

  

我们不建议使用GLOB从中收集源文件列表   你的源代码树。如果源没有更改CMakeLists.txt文件   添加或删除然后生成的构建系统无法知道何时   让CMake重新生成。

这是我的故障安全版本(检查绝对路径)用作函数:

function(assign_source_group)
    foreach(_source IN ITEMS ${ARGN})
        if (IS_ABSOLUTE "${_source}")
            file(RELATIVE_PATH _source_rel "${CMAKE_CURRENT_SOURCE_DIR}" "${_source}")
        else()
            set(_source_rel "${_source}")
        endif()
        get_filename_component(_source_path "${_source_rel}" PATH)
        string(REPLACE "/" "\\" _source_path_msvc "${_source_path}")
        source_group("${_source_path_msvc}" FILES "${_source}")
    endforeach()
endfunction(assign_source_group)

您可以使用

在示例中调用
assign_source_group(${source_list})

答案 1 :(得分:1)

我知道这是使用臭名昭著的CMAKE glob函数Why is CMAKE glob evil,但是在 my 的情况下,这可能比显式命名每个文件更好。我想我会使用GLOB包括@Florian答案的修改版本。

{"defense"=>
  [{:id=>30,
    :source=>"Hacker News",
    :title=>
     "China-based campaign breached satellite, defense companies: Symantec",
    :link=>
     "https://www.reuters.com/article/us-china-usa-cyber/china-based-campaign-breached-satellite-defense-companies-symantec-idUSKBN1JF2X0"}]}

答案 2 :(得分:1)

从CMake 3.8开始,source_group命令提供了一个TREE参数,用于递归搜索源文件的路径,以构造源组以匹配文件系统结构。现在,这提供了一种更清洁的解决方案:

project(Main)

set(SOURCE_LIST
    "File.cpp"
    "File.hpp"
    "Dir/File1.cpp"
    "Dir/File1.hpp"
    "Dir/File2.cpp"
    "Dir/File2.hpp"
)

add_executable(Main ${SOURCE_LIST})

# Create the source groups for source tree with root at CMAKE_CURRENT_SOURCE_DIR.
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCE_LIST})

答案 3 :(得分:1)

我想评论https://stackoverflow.com/users/3987854/squareskittles的答案,但是由于缺乏“声誉”而无法发表我的看法?

反正

source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCE_LIST})

就像一个饰物一样工作,但我还需要进行以下设置:

set_property(GLOBAL PROPERTY USE_FOLDERS ON)