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
Meaining of the error
Since you use
PUBLICkeyword when link your library (A) withspdlog_header_only, CMake expects that this linking is also needed for users of your library. So, when you create config file for your library (withinstall(EXPORT)), CMake adds linking withspdlog_header_onlytarget into the config file too. LikeLinking with a target implies existence of this target, but you do not install
spdlog_header_onlytarget. Because of that, created config file for your library won't work. This is what CMake tells you in the error message.Simple fix
The simplest fix would be using
PRIVATElinking withspdlog_header_onlytarget, 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 forspdlog. (But a user could obtain these headers by other means.)Hard fix
But if you want a user of your library to have access to
spdlogheaders (or, worse, the public headers of your library use#includefor headers fromspdlog), then you cannot dropPUBLIClinking. In that case you need to installspdlog_header_onlytarget too. E.g. by enablingSPDLOG_INSTALLoptionbefore
(Note, that aside from enabling
SPDLOG_INSTALLoption, several other adjustments needs to be done for make the config file for your library to work.)