Having worked with CMake for some time, it is now time to create my first exported library. I followed the guides in the documentation (https://cmake.org/cmake/help/latest/guide/importing-exporting/index.html and others), but I ran into some troubles, which I hope you can help me resolve.
The project contains of several libraries, one of them should be published. The project file structure looks something like this:
myProject
|- CMakeLists.txt
|- myLib
| |- CMakeLists.txt
| |- FindMyLib.cmake
| |- MyLib-config.cmake
| |- include
| | |- ... header files ...
| |- src
| | |- ... source files
|- ... other libs, executables and tests
The CMakeLists.txt of myLib looks like this
include(GenerateExportHeader)
include(CMakePackageConfigHelpers)
# Library definition as used in myProject
add_library(myLib SHARED ${myLib_SOURCES})
target_link_libraries(myLib Qt5::Core Boost::headers)
target_include_directories(myLib
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include;${CMAKE_CURRENT_BINARY_DIR}>
INTERFACE $<INSTALL_INTERFACE:include>
)
generate_export_header(myLib
EXPORT_MACRO_NAME MYLIB_SHARED_EXPORT
EXPORT_FILE_NAME mylib_global.h
)
# For installation of the library
install(TARGETS myLib EXPORT myLibTargets
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
install(DIRECTORY include/ DESTINATION ${MYLIB_INCLUDE_INSTALL_PATH})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mylib_global.h
DESTINATION ${MYLIB_INCLUDE_INSTALL_PATH}/include
)
# Creating CMake package configuration files
set(ConfigPackageLocation ${MYLIB_LIB_INSTALL_PATH}/cmake/myLib)
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/myLib-version.cmake
VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}
COMPATIBILITY SameMajorVersion
)
configure_package_config_file(MyLib-config.cmake.in MyLib-config.cmake
INSTALL_DESTINATION ${MYLIB_LIB_INSTALL_PATH}
)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/MyLib-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/MyLib-version.cmake
DESTINATION ${ConfigPackageLocation}
)
export(TARGETS myLib NAMESPACE MyProject::
FILE ${CMAKE_CURRENT_BINARY_DIR}/MyLibTargets.cmake
)
install(EXPORT MyLibTargets
FILE MyLibTargets.cmake
NAMESPACE MyProject::
DESTINATION ${ConfigPackageLocation}
)
Without the package configuration part, the library builds and installs as expected into the wanted directory and is usable there (please forgive me if I made a typo when posting the reduced version here). I used PUBLIC for the include directories to build the library, because with INTERFACE, the directories were not used for building.
Package-version file and package-config file are generated and installed as expected.
But, my issues start with the last two commands: the generated MyLibTargets.cmake file contains absolute paths to my source/build directory:
CMake Error in myLib/CMakeLists.txt:
Target "myLib" INTERFACE_INCLUDE_DIRECTORIES property contains path:
"C:/path/to/source/directory/myProject/myLib/"
which is prefixed in the source directory.
According to the documentation, the use of $<BUILD_INTERFACE:...>
and $<INSTALL_INTERFACE:...>
should prevent exactly this issue. Looking into the generated MyLibTargets.cmake, I can see absolute paths for include directories as well as the libraries location (IMPORTED_IMPLIB_DEBUG in this case and IMPORTED_LOCATION_DEBUG).
Removing the export(TARGETS...)
call gives a similar result. Still the INTERFACE_INCLUDE_DIRECTORIES
property is set to the value I wanted to use for build, not the one for install. (I cleaned the build directory between when I commented the line; the generated MyLibTargets.cmake files are generated in different locations anyway).
In theory I can take the generated MyLibTargets.cmake file, correct the values and check it in into the repository. But I would like to use CMake’s generation to be compatible with future versions.
(Environment: Win10, CMake 3.21)
Any ideas?