How to create Xcode groups with CMake? [duplicate] - c++

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.
I do not want to use single CmakeFile.txt in Main directory having filters
Actual structure is many layers deep nesting structure. So please suggest the solution which will work for any level sub directory

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

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

Related

why add_subdirectory() command did not work for my CMakeLists.txt?

I have a simple exercise on cmake with following file tree:
proj01/
include/
functions.h
src/
main.cpp
functions.cpp
CMakeLists.txt
CMakeLists.txt
README
My project CMakeLists.txt is like this:
cmake_minimum_required(VERSION 3.21)
project (test01)
add_subdirectory(src)
set(SOURCES
main.cpp
functions.cpp
)
add_executable(myProgram ${SOURCES})
and when I tried to build, I got error:
# Error!
CMake Error at CMakeLists.txt:18 (add_executable):
Cannot find source file:
main.cpp
CMake Error at CMakeLists.txt:18 (add_executable):
No SOURCES given to target: myProgram
If I change the project CMakeLists.txt by giving the absolute path(relative to the project), it worked!
#add_subdirectory(src)
set(SOURCES
src/main.cpp
src/functions.cpp
)
add_executable(myProgram ${SOURCES})
When there is multiple source files in multiple subdirectories, it would be better to explicitly list all source files including their paths as what is done with my working version of the CMakeLists.txt.
Spent hours to search for command add_subdirectories(), this, this, and this, but no luck.
The closest one would be this question, but there is no solution for that question so far.
What did I miss with my add_subdirectory(src) in this simple specific scenario? Any help is appreciated.
add_subdirectory(src) results in cmake parsing src/CMakeLists.txt creating a new directory src in the build tree for building the part of the project in this cmake file.
It doesn't result in you being able to use shorter paths in the CMakeLists.txt file containing the add_subdirectory command.
If you move the target to src/CMakeLists.txt you could use the shorter paths:
CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
project (test01)
add_subdirectory(src) # add src/CMakeLists.txt to this project
src/CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
set(SOURCES
main.cpp
functions.cpp
)
add_executable(myProgram ${SOURCES})
Personally I'd avoid adding an additional CMakeLists.txt file just to shorten the paths. It's easy to remove the duplication of the src dir, if that's what you're worried about.
set(SOURCES
main.cpp
functions.cpp
)
list(TRANSFORM SOURCES PREPEND "src/")
or
function(subdir_files VAR DIR FILE1)
set(FILES)
foreach(SRC IN ITEMS ${FILE1} ${ARGN})
list(APPEND FILES ${DIR}/${SRC})
endforeach()
set(${VAR} ${FILES} PARENT_SCOPE)
endfunction()
subdir_files(SOURCES src
main.cpp
functions.cpp
)

add_subdirectory not working with custom source macro

I'm pretty new to CMake, and have just gotten into setting it up. I've gone ahead and implemented a simple opengl boilerplate, whose tree is like this
CMakeLists.txt
include
glad
KHR
src
glad
glad.c
CMakeLists.txt
main.cpp
CMakeLists.txt
lib
.gitignore
.gitmodules
CMakePresets.json
README.md
My Root CMakeLists is this:
cmake_minimum_required (VERSION 3.8)
project ("GameBro")
set(APP_NAME "GameBro")
# Opengl stuff
find_package( OpenGL REQUIRED )
# GLFW stuff
set(BUILD_SHARED_LIBS OFF CACHE BOOL "")
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "")
set(GLFW_BUILD_TESTS OFF CACHE BOOL "")
set(GLFW_BUILD_DOCS OFF CACHE BOOL "")
set(GLFW_INSTALL OFF CACHE BOOL "")
# MSVC related stuff
if( MSVC )
SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:mainCRTStartup" )
endif()
# Macro to add sources from subdirs
macro (add_sources)
file (RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
foreach (_src ${ARGN})
if (_relPath)
list (APPEND sources "${_relPath}/${_src}")
else()
list (APPEND sources "${_src}")
endif()
endforeach()
if (_relPath)
# propagate SRCS to parent directory
set (sources ${sources} PARENT_SCOPE)
endif()
endmacro()
# Library subdir
add_subdirectory( lib )
# Add sources
add_subdirectory( src )
# Add executable
include_directories( ${OPENGL_INCLUDE_DIRS} lib/glfw/include lib/glfw/deps include )
add_executable ( ${APP_NAME} ${sources} )
target_link_libraries (${APP_NAME} glfw ${GLFW_LIBRARIES})
My src CMakeLists is like this
add_sources( main.cpp )
#add_sources( glad/glad.c )
add_subdirectory (glad)
My src/glad CMakeLists is like this
add_sources( glad.c )
The problem is, when i try to compile - i get errors like undefined reference to glad_glCreateShader etc....
But, when i put glad.c in the same dir as main.cpp and modify CMakeLists accordingly, it works properly and compiles, and displays a rectangle. WHat am I doing wrong here?
So, I seem to have finally fixed my problem. Here's how I did it.
SO, as #fabian pointed out, PARENT_SCOPE only refers to the immediately above scope. NOT the top-level scope. To fix this what I did was to add
set (sources ${sources} PARENT_SCOPE)
to each and every CMakeLists.txt file. Although this is a hacky workaround - it solves my purpose.

How to include properly all files with CMake

I want to build my C++ project with CMake and I want to include automatically every new file on "cmake ." my project structure is:
Application/ Graphics/ CMakeLists.txt CMakeLists.txt.user main.cpp
./Application:
CMakeLists.txt Logger/ Recovery/ application.cpp application.hpp firstclass.cpp firstclass.hpp singleton.hpp
./Application/Logger:
CMakeLists.txt logger.cpp logger.hpp
./Application/Recovery:
CMakeLists.txt recovery.cpp recovery.hpp
./Graphics:
CMakeLists.txt drawableobject.cpp drawableobject.hpp graphics.cpp graphics.hpp
Each folder has own CMakeLists.txt
I did so far this in master CMake:
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Asteri VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
message("Source dir: ${SOURCE_DIR}")
#file(GLOB_RECURSE SRC_FILES ${SOURCE_DIR}/*.cpp)
#file(GLOB_RECURSE HEADER_FILES ${HEADER_DIR}/*.hpp)
set(PROJECT_NAME "Asteri")
macro(SUBDIRLIST result curdir)
file(GLOB children RELATIVE ${curdir} ${curdir}/*)
set(dirlist "")
foreach(child ${children})
if(IS_DIRECTORY ${curdir}/${child})
list(APPEND dirlist ${child})
endif()
endforeach()
set(${result} ${dirlist})
endmacro()
SUBDIRLIST(SUBDIRS ${CMAKE_CURRENT_SOURCE_DIR})
foreach(subdir ${SUBDIRS})
message("Subdirectory: ${subdir}")
add_subdirectory(${subdir})
endforeach()
add_executable(${Asteri} main.cpp)
The question is how to connect all pieces together?
What I need in other CMakeLists.txt?
How to communicate children -> parent or I misunderstood the concept of CMake?
No need for other CMakeLists.
I guess you want something like this in top CMakeLists:
cmake_minimum_required(VERSION 3.12)
project(Asteri VERSION 1.0)
file(GLOB_RECURSE ASTERI_SRC_FILES CONFIGURE_DEPENDS
"${PROJECT_SOURCE_DIR}/Application/*.cpp"
"${PROJECT_SOURCE_DIR}/Graphics/*.cpp"
)
add_executable(Asteri main.cpp ${ASTERI_SRC_FILES})
It's worth noting that GLOB/GLOB_RECURSE -even with CONFIGURE_DEPENDS- is bad practice: it's slow, specially on Windows from my experience, and may not work as expected depending on generator used.
I found out the answer to my problems.
set(SOURCES "${PROJECT_DIR}/main.cpp" CACHE INTERNAL STRINGS)
add_subdirectory(application)
FOREACH(it ${SOURCES})
message("source file: ${it}")
ENDFOREACH()
add_executable(Asteri ${SOURCES})
In this way I store main.cpp path into variable SOURCES
You can see your variables after 'make' in CMakeCache.txt.
After this is done, my variable SOURCES looks like:
/STRINGS
SOURCES:INTERNAL=/home/default/cpp_testing_project/cmake_project/source/main.cpp;
After that in application subdirectory I have CMakeLists.txt:
cmake_minimum_required(VERSION 3.7)
# Get source files
file(GLOB CPP_LIST "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
set(SOURCES ${SOURCES} ${CPP_LIST} CACHE INTERNAL STRINGS)
And now SOURCES looks like:
SOURCES:INTERNAL=/home/default/cpp_testing_project/cmake_project/source/main.cpp;/home/default/cpp_testing_project/cmake_project/source/application/application.cpp;/home/default/cpp_testing_project/cmake_project/source/application/drawableobject.cpp;/home/default/cpp_testing_project/cmake_project/source/application/firstclass.cpp;/home/default/cpp_testing_project/cmake_project/source/application/graphics.cpp;/home/default/cpp_testing_project/cmake_project/source/application/application.hpp;/home/default/cpp_testing_project/cmake_project/source/application/drawableobject.hpp;/home/default/cpp_testing_project/cmake_project/source/application/firstclass.hpp;/home/default/cpp_testing_project/cmake_project/source/application/graphics.hpp;

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

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.
I do not want to use single CmakeFile.txt in Main directory having filters
Actual structure is many layers deep nesting structure. So please suggest the solution which will work for any level sub directory
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})
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")

CMake - dependencies (headers) between apps/libraries in same project

I have the following project structure:
CMakeLists.txt
lib1/CMakeLists.txt and all cpp and header files of the lib
lib2/CMakeLists.txt and all cpp and header files of the lib
app/CMakeLists.txt and all cpp and header files of the app
The main CMakeLists.txt looks like:
PROJECT( ${PROJECT_NAME} )
add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(app)
The lib1/CMakeLists.txt looks eg like (stripped):
SET(SOURCE
file.cpp
)
SET(HEADERS
some_lib_header.h
)
add_library( lib1 ${SOURCE} ${HEADERS} )
and the one for the app looks the same except of ADD_EXECUTABLE:
SET(SOURCE
main.cpp
)
SET(HEADERS
some_header.h
)
add_library( lib1 ${SOURCE} ${HEADERS} )
ADD_EXECUTABLE( app ${SOURCE} ${HEADERS} )
I found the setup working well this way because out of this, I can generate one Visual Studio solution file which contains all those three projects. But my problem is that my app includes header files of lib1 (and also of lib2, which depends on lib1). When I do
$mkdir build
$cd build
$cmake -C ..\myproject
it generates out-of-source VS .sln file as I want it, but the app doesn't compile because it can't find the header files of lib1 (obviously).
Now I read and tried many things, like TARGET_LINK_LIBRARIES( app lib1 ) (which got the app to link with the lib1, but not solve the header include issue), and things like add_subdirectory( ../lib1 ) in various variants in the CMakeLists.txt of app (which all throwed errors that I couldn't fix), and also find_package (which I guess is the wrong approach).
So how can I solve this (I guess simple...) problem?
Here's one possible solution:
Root CMakeLists.txt:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(${PROJECT_NAME})
add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(app)
lib1/CMakeLists.txt:
project(Lib1)
add_library(lib1 lib1.cpp lib1.h)
lib2/CMakeLists.txt:
project(Lib2)
add_library(lib2 lib2.cpp lib2.h)
# Add /lib1 to #include search path
include_directories(${Lib1_SOURCE_DIR})
# Specify lib2's dependency on lib1
target_link_libraries(lib2 lib1)
app/CMakeLists.txt:
project(App)
add_executable(app main.cpp some_header.h)
# Add /lib1 and /lib2 to #include search path
include_directories(${Lib1_SOURCE_DIR} ${Lib2_SOURCE_DIR})
# Specify app's dependency on lib2.
# lib2's dependency on lib1 is automatically added.
target_link_libraries(app lib2)
There are plenty of different ways to achieve the same end result here. For a relatively small project, I'd probably just use a single CMakeLists.txt:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(Test)
add_library(lib1 lib1/lib1.cpp lib1/lib1.h)
add_library(lib2 lib2/lib2.cpp lib2/lib2.h)
add_executable(app app/main.cpp app/some_header.h)
include_directories(${CMAKE_SOURCE_DIR}/lib1 ${CMAKE_SOURCE_DIR}/lib2)
target_link_libraries(lib2 lib1)
target_link_libraries(app lib2)
For further info on the relevant commands and their rationale, run:
cmake --help-command add_subdirectory
cmake --help-command include_directories
cmake --help-command target_link_libraries
Project
CMakeLists.txt
\-lib1
CMakeLists.txt
\- include \ lib1
\- src
\-lib2
CMakeLists.txt
\- include \ lib2
\- src
\-app
CMakeLists.txt
\- src
Suppose dependencies as follow:
lib1 ---> lib2 ---> app
\--------------> app
Something like this:
CMakeLists.txt:
add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(app)
lib1/CMakeLists.txt:
file(GLOB_RECURSE _HDRS "include/*.hpp")
file(GLOB_RECURSE _SRCS "src/*.[hc]pp")
add_library(lib1 ${_HDRS} ${_SRCS})
#target_link_libraries(lib1)
target_include_directories(lib1 PUBLIC include)
install(TARGETS lib1 DESTINATION lib)
install(FILES ${_HDRS} DESTINATION include/lib1)
lib2/CMakeLists.txt:
file(GLOB_RECURSE _HDRS "include/*.hpp")
file(GLOB_RECURSE _SRCS "src/*.[hc]pp")
add_library(lib2 ${_HDRS} ${_SRCS})
target_link_libraries(lib2 lib1)
target_include_directories(lib2 PUBLIC include)
install(TARGETS lib2 DESTINATION lib)
install(FILES ${_HDRS} DESTINATION include/lib2)
so in lib2/src/file.cpp you could do #include <lib1/header.hpp>
app/CMakeLists.txt:
file(GLOB_RECURSE _SRCS "src/*.[hc]pp")
add_executable(app ${_SRCS})
target_link_libraries(app lib1 lib2)
install(TARGETS app DESTINATION bin)
so in app/src/file.cpp you could do #include <lib1/header.hpp> and #include <lib2/header.hpp>
The magic is target_include_directories which attach the "include" directory to the target, so when linking with it you pull the include directory also ;)