Hello,
I have a simple library project, which consumes an other library, provided as a CMake installation configuration (throught a ZIP and a call to FetchContent).
The question is at the end.
Here is the files structure :
└── DepTest
├── CMakeLists.txt
├── include
│ └── DepTest
│ └── a.h
├── src
│ ├── CMakeLists.txt
│ ├── a.cpp
└── test
├── CMakeLists.txt
└── test.cpp
Root CMakeLists.txt :
cmake_minimum_required(VERSION 3.17.2)
project(DepTest VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_subdirectory(src)
add_subdirectory(test)
test CMakeLists.txt :
add_executable(DepTestTest test.cpp)
target_link_libraries(DepTestTest PRIVATE DepTest)
and the big part, the src CMakeLists.txt :
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
find_package(Qt5 REQUIRED
COMPONENTS Core)
if(POLICY CMP0135)
cmake_policy(SET CMP0135 NEW)
endif()
include(FetchContent)
FetchContent_Declare(OtherLib
URL <path_to_otherLib>
HTTP_USERNAME $ENV{NEXUS_USERNAME}
HTTP_PASSWORD $ENV{NEXUS_PASSWORD})
FetchContent_MakeAvailable(OtherLib)
set(OtherLib_SOURCE_DIR)
FetchContent_GetProperties(OtherLib
SOURCE_DIR OtherLib_SOURCE_DIR)
add_library(DepTest STATIC)
target_include_directories(${PROJECT_NAME}
PRIVATE
${OtherLib_SOURCE_DIR}/include)
# Problem !!!
target_link_directories(${PROJECT_NAME}
PUBLIC
${OtherLib_SOURCE_DIR}/lib)
target_link_libraries(DepTest
PRIVATE
Qt5::Core
OtherLib$<$<CONFIG:Debug>:d>)
set(PUBLIC_SOURCE_LIST
${PROJECT_SOURCE_DIR}/include/DepTest/a.h)
set(PRIVATE_SOURCE_LIST
a.cpp)
target_sources(DepTest
PRIVATE
${PUBLIC_SOURCE_LIST}
${PRIVATE_SOURCE_LIST})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX Sources FILES ${PRIVATE_SOURCE_LIST})
source_group(TREE ${PROJECT_SOURCE_DIR}/include/DepTest PREFIX Interface FILES ${PUBLIC_SOURCE_LIST})
# CMake will install by default the files in C:/Program Files/DepTest
# (see in CMake documentation CMAKE_INSTALL_PREFIX), but we don't want
# to pollute C:/Program Files, so we'll put the files somewhere in the
# project folders.
# All installation files will be rooted in CMAKE_INSTALL_PREFIX.
if(DEFINED CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
message(
STATUS
"CMAKE_INSTALL_PREFIX is not set\n"
" Default value: ${CMAKE_INSTALL_PREFIX}\n"
" Will set it to ${CMAKE_SOURCE_DIR}/install"
)
set(CMAKE_INSTALL_PREFIX
"${CMAKE_SOURCE_DIR}/install"
CACHE PATH "Where the library will be installed to" FORCE
)
else()
message(
STATUS
"CMAKE_INSTALL_PREFIX was already set\n"
" Current value: ${CMAKE_INSTALL_PREFIX}"
)
endif()
# This module sets several installation directories compliant with GNU standard.
# They can also be used for Windows.
include(GNUInstallDirs)
set(CMAKE_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include")
target_include_directories(DepTest
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE
${CMAKE_CURRENT_LIST_DIR})
# To install the public header files, we cannot just set the PUBLIC_HEADER property on these
# files,and expect that the install() command will do correctly the job by using the parameter
# PUBLIC_HEADER DESTINATION: the file structure will not be respected.
# So instead we iterate through public headers and install them "manually".
# Note : May be obsolete since the introduction of File sets (see target_sources())
foreach(header ${PUBLIC_SOURCE_LIST})
file(RELATIVE_PATH header_file_path "${PROJECT_SOURCE_DIR}" "${header}")
get_filename_component(header_directory_path "${header_file_path}" DIRECTORY)
install(FILES ${header}
DESTINATION "${CMAKE_INSTALL_PREFIX}/${header_directory_path}")
endforeach()
# We need to keep the original name, before postfix appending, in order to manage the PDB file later.
set(ORIGINAL_PROJECT_NAME ${PROJECT_NAME})
# Add a suffix on ibrary binary for debug version
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "d")
install(TARGETS ${PROJECT_NAME}
EXPORT "${PROJECT_NAME}Targets"
# These get default values from GNUInstallDirs, no need to set them
# RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # bin
# LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # lib
# ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # lib
# except for public headers, as we want them to be inside a library folder
# PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # include/DepTest
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # include/DepTest
)
# For some build configurations, we have also to copy "by hand" the PDB files, because it is not done by CMake.
# CMake provides the expression generator $<TARGET_PDB_FILE:tgt>, but it concerns the PDB built by linker.
# As static libraries don't link, we need the PDB geenrated during the build. But CMake doesn't provide
# expression generator for this file (an issue has been opened : https://gitlab.kitware.com/cmake/cmake/-/issues/16932).
# We have so to "manually" localize the PDB file, and copy it during the installation for the relevant builds.
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.19.0")
message(WARNING ">>>> Use <CONFIG:Debug,RelWithDebInfo> instead boolean test in if() test inside install command")
endif()
install(CODE "
if ($<CONFIG:Debug> OR $<CONFIG:RelWithDebInfo>)
file(INSTALL \"${CMAKE_CURRENT_BINARY_DIR}/${ORIGINAL_PROJECT_NAME}.dir/$<CONFIG>/${ORIGINAL_PROJECT_NAME}.pdb\"
DESTINATION \"\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}\")
endif()
")
# Problem !!!
install(EXPORT "${PROJECT_NAME}Targets"
FILE "${PROJECT_NAME}Targets.cmake"
NAMESPACE ${namespace}:: # This namespace will have to be used by the client when it will search the package
DESTINATION cmake)
include(CMakePackageConfigHelpers)
# Generate the version file for the config file
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
COMPATIBILITY AnyNewerVersion
)
# Create config file
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION cmake
)
# Install config files
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION cmake
)
In the big CMakeLists.txt, please search for the 2 occurrences of “# Problem !!!”.
These two instructions causes some troubles. Here what I get when I run CMake -G
:
CMake Error in src/CMakeLists.txt:
Target "DepTest" INTERFACE_LINK_DIRECTORIES property contains path:
"E:/CMake_sandbox/DepTest/build/_deps/OtherLib-src/lib"
which is prefixed in the build directory.
CMake Error in src/CMakeLists.txt:
Target "DepTest" INTERFACE_LINK_DIRECTORIES property contains path:
"E:/CMake_sandbox/DepTest/build/_deps/OtherLib-src/lib"
which is prefixed in the build directory.Target "DepTest"
INTERFACE_LINK_DIRECTORIES property contains path:
"E:/CMake_sandbox/DepTest/build/_deps/OtherLib-src/lib"
which is prefixed in the source directory.
I found this related post :
But I don’t really understand what’s happening, and what I should do.