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

前端 未结 4 571
北海茫月
北海茫月 2020-11-30 04:57

I have following structure

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


        
4条回答
  •  一向
    一向 (楼主)
    2020-11-30 05:47

    There are several ready to use or adaptable solutions out there to mimic a Source Tree behavior like in Eclipse with CMake for Visual Studio (e.g. ADD_SRC_SUBFOLDER DESTINATION_SRCS from Zobra or GroupSources from Luca).

    Here is my reduced version for your use case:

    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()
    

    See the documentation of source_group() that you have to give the sub-directories with double backslashes.

    For the reason why I replaced your file(GLOB ...) with a dedicated list of all source files I like to quote from CMake's file() command documentation:

    We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.

    And here is my fail-safe version (that checks for absolute paths) to be used as a function:

    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)
    

    Which you would call in the example with

    assign_source_group(${source_list})
    

提交回复
热议问题