Issue
Take for example this project structure
project
CMakeLists.txt
main.cpp
libA
src.cpp
CMakeLists.txt
libB
foo.h
foo.cpp
CMakeLists.txt
src.cpp and main.cpp:
#include "foo.h"
.
.
.
I need both src.cpp and main.cpp to have libB in their include path, what I've tried to do is:
libB/CMakeLists.txt:
add_library(libB SHARED
src.cpp)
libA/CMakeLists.txt:
add_library(libA SHARED
foo.cpp)
target_link_libraries(libA libB)
project/CMakeLists.txt:
add_subdirectory(libA)
add_subdirectory(libB)
add_executable(App main.cpp)
target_include_directories(App PUBLIC libB)
target_link_libraries(App libA libB)
And yet I get an error that src.cpp: fatal error: foo.h: No such file or directory
Solution
In the top-level:
cmake_minimum_required(VERSION 3.21)
project(project)
option(BUILD_SHARED_LIBS "Build shared libs instead of static" ON)
add_subdirectory(libA)
add_subdirectory(libB)
add_executable(App main.cpp)
target_link_libraries(App PRIVATE libA libB)
In libA:
add_library(libA src.cpp)
# Use PUBLIC below if libA exposes libB's types in its API.
target_link_libraries(libA PRIVATE libB)
In libB:
add_library(libB foo.cpp)
target_include_directories(
libB PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
)
PUBLIC
and INTERFACE
properties on targets propagate to their linkees. Thus, when we set up the include directories on libB
, any target linking to it will get its source directory added it its include path.
We guard the include directory with $<BUILD_INTERFACE:...>
so that if you ever install()
the library somewhere it might be re-used in another CMake build, it won't remember details of your specific file system.
Answered By - Alex Reinking