cmake: how to create visual studio filters

I found it easier to do this and thought it might be helpful to others. Make sure you are using the latest version of 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()

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

Just be aware that

  • the source_group() command only works in combination with add_library() or add_executable() commands listing the same sources (the paths must match)
  • the source_group() command does not check if the file actually exists (so it takes anything you give it and during project file generation it tries to match the given source group file names against files used in the project)

I have given your code a try by adding a corresponding add_library() target and it works as expected (CMake 3.3.2 and 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})

Results in

Solution Explorer with Filters

Here is a more generalized version taken from 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()