Reputation: 360
My project is organized in subdirectories (a dozen), there are some includes between subdirectories. Some of these subdirectories contains only header files (dir1 for example).
Here is a look at the organization of the project:
project
|
|----- src -- dir1 <-- header-only library
| | |--- dir1.h
| | |--- CMakeLists.txt
| |
| |
| | --- dir2
| | |--- dir2.cpp
| | |--- dir2.h
| | |--- CMakeLists.txt
| |
| | --- file.h
| | --- CMakeLists.txt
|
|
|----- test -- dir1 -- test.cpp
| | ---- dir2 -- test.cpp
| | ---- includeFile.h
|
|
|----- CMakeLists.txt
I want to have a library containing all the code from src directory and an executable to run unit tests. After some research on stackOverFlow and Cmake examples, I arrived to these CMake files. There is one makefile per src subdirectories, one for grouping all the library and one global.
dir1 CMakeLists
add_library(dir1 INTERFACE)
target_sources(dir1 INTERFACE dir1.h)
target_include_directories(dir1 INTERFACE
"${PROJECT_SOURCE_DIR}/src/dir1"
)
dir2 CMakeLists
set(dir2_src
dir2.cpp dir2.h
)
add_library(dir2 ${dir2_src})
src CMakeLists
add_subdirectory(dir1)
add_subdirectory(dir2)
add_library(TheProject INTERFACE)
target_sources(TheProject INTERFACE file.h)
target_include_directories(TheProject INTERFACE
"${PROJECT_SOURCE_DIR}/src/"
)
target_link_libraries(TheProject INTERFACE dir1
dir2
${Boost_LIBRARIES})
main CMakeLists.txt
project(TheProject)
# gtest
# boost
# compilation flags ...
####### include paths
include_directories("./src/")
include_directories(${Boost_INCLUDE_DIRS})
####### library to compile
add_subdirectory(src)
####### executable
file(GLOB SRCS utest/*/*.cpp)
add_executable(utest ${SRCS} test/includeFile.h)
target_link_libraries(utest gtest_main TheProject)
I almost used the same organization on a smaller project without header only libraries and INTERFACE and it worked. Here, I have an error with the different interface libraries:
CMake Error at CMakeLists.txt:88 (add_executable):
Cannot find source file:
file.h
Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp
.hxx .in .txx
I think I have not well understood the use of INTERFACE. I have done some research but nothing solve my problem.
And I have also a few questions:
Upvotes: 5
Views: 25944
Reputation: 65936
Before CMake 3.13 relative paths, passed to target_sources
, are interpreted relative to further invocations of add_executable
(or add_library
).
Because you call add_executable()
from the top directory, CMake searches test.h
relative to the top directory, not relative to the src/
one.
Use absolute paths for target_sources
calls:
target_sources(TheProject INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/file.h)
Since CMake 3.13 relative paths passed to target_sources
are resolved immediately, relative to the current source directory. See @markhc's answer.
Upvotes: 11
Reputation: 679
As an addon to Tsyvarev answer to anyone that comes across this from google, the behavior for target_sources
was changed on CMake 3.13.
You can now use relative paths in target_sources
calls.
https://cmake.org/cmake/help/v3.13/command/target_sources.html
Relative source file paths are interpreted as being relative to the current source directory
Upvotes: 6