web-dev-qa-db-ja.com

cmakeを使用してネストされたサブディレクトリにVisual Studio Filtersを設定する方法

私は以下の構造を持っています

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

Main/CMakeLists.txt

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

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

Main/Dir/CmakeLists.txt

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

Visual Studioで次の構造を生成しました
enter image description here

欲しいもの:

enter image description hereenter 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})

Main/Dir/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を使用したくない
  • 実際の構造は、多くの層の深い入れ子構造です。だから、どのレベルのサブディレクトリでも機能する解決策を提案してください
20
Jai

CMake for Visual Studioを使用したEclipseのようなソースツリーの動作を模倣する、すぐに使用できる、または適応可能なソリューションがいくつかあります(例 ADD_SRC_SUBFOLDER DESTINATION_SRCS from Zobraまたは GroupSources from Luca) 。

これは、ユースケース用の縮小バージョンです。

_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})
_
19
Florian

CMake .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})
5
squareskittles

CMAKE glob関数の使用は通常不快感を覚えます: なぜCMAKE glob evilなのか ですが、myの場合は各ファイルに明示的に名前を付けるよりも適切です。 GLOBを使用してFlorianの回答の修正版を含めると考えました。

# This code sorts the project files as they appear in the root directory

# Generate a list of all .c & .h files in the current directory and sub directores.
file(
     GLOB_RECURSE source_list RELATIVE
     "${CMAKE_CURRENT_SOURCE_DIR}"
     *.c *.h
    )
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()  
message(STATUS "Tree reorganized")
2
joeshmo