I have following structure
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
)
It generated the following structure in Visual Studio
What I want:


What I tried:
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})
What I get:

Please help me regarding this.
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
GLOBto 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})
                        As of CMake 3.8, the source_group command offers a TREE argument to recursively search the files paths of your sources, and structures the source groups to match your file system structure. Now, this offers a much cleaner solution:
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})
                        I wanted to comment on https://stackoverflow.com/users/3987854/squareskittles 's answer, but I couldn't due to the lack of "reputation" ?
Anyway,
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCE_LIST})
works like a charm, but I also needed to set this:
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
                        I know that using the CMAKE glob function is usually frowned upon: Why is CMAKE glob evil, but in my case I found it to better than explicitly naming each file. I figured I would include a modified version of Florian's answer using GLOB.
# 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")
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With