I have a project A that depends on spdlog. Here is the structure:
|--- dir A
...|---src
......|---CMakeLists.txt
...|---include
...|---CMakeLists.txt
|---external/3rd_party/spdlog
I am trying to access spdlog in project A by adding a subdirectory. Here is how my A/CMakeLists.txt
looks like:
cmake_minimum_required(VERSION 3.9.3 FATAL_ERROR)
project(GLOBAL CXX)
add_subdirectory(../external/3rd_party/spdlog ${CMAKE_BINARY_DIR}/spdlog EXCLUDE_FROM_ALL)
add_subdirectory(src)
Here is how my A/src/CMakeLists.txt
looks like:
cmake_minimum_required(VERSION 3.9.3 FATAL_ERROR)
project(Alib CXX)
if(NOT TARGET spdlog)
# Stand-alone build
find_package(spdlog_header_only REQUIRED)
endif()
add_librray(A A.cpp)
target_link_libraries(A PUBLIC spdlog_header_only)
install(TARGETS A
EXPORT ATargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(EXPORT ATargets
NAMESPACE A::
FILE ATargets.cmake
DESTINATION ${INSTALL_CONFIGDIR})
install(FILES AConfig.cmake DESTINATION ${INSTALL_CONFIGDIR})
When I try to build this, I get the following error:
CMake Error: install(EXPORT "ATargets" ...) includes target "A" which requires target "spdlog_header_only" that is not in the export set.
Please can you suggest me how to fix it?
For some reason I need to maintain the same directory structure I have shown above. Here is a related question but does not have an answer : here
Since you use PUBLIC
keyword when link your library (A
) with spdlog_header_only
, CMake expects that this linking is also needed for users of your library. So, when you create config file for your library (with install(EXPORT)
), CMake adds linking with spdlog_header_only
target into the config file too. Like
# [ATargets.cmake]
target_link_libraries(A::A PUBLIC spdlog_header_only)
Linking with a target implies existence of this target, but you do not install spdlog_header_only
target. Because of that, created config file for your library won't work. This is what CMake tells you in the error message.
The simplest fix would be using PRIVATE
linking with spdlog_header_only
target, so that linking won't be part of the config file. Beware, in that case a user of your (installed) library won't get access to the header files for spdlog
.
(But a user could obtain these headers by other means.)
But if you want a user of your library to have access to spdlog
headers (or, worse, the public headers of your library use #include
for headers from spdlog
), then you cannot drop PUBLIC
linking. In that case you need to install spdlog_header_only
target too. E.g. by enabling SPDLOG_INSTALL
option
set(SPDLOG_INSTALL ON)
before
add_subdirectory(../external/3rd_party/spdlog ${CMAKE_BINARY_DIR}/spdlog EXCLUDE_FROM_ALL)
(Note, that aside from enabling SPDLOG_INSTALL
option, several other adjustments needs to be done for make the config file for your library to work.)