Reputation: 2888
I want to have multi versions of a library installed in one place(e.g. the default system prefix path) using CMake to be used like: find_package(Package 1.0.0 REQUIRED)
.
find_package
job to handle it.The find_package
's version parameter is just an ordinary parameter that will be passed to the package *VersionConfig.cmake
file for version checking and if that file doesn't exists CMake will treat it as an error. So we couldn't install different version in the same place.
file(WRITE Library.H "void Function();")
file(WRITE Library.C "void Function() {}")
add_library(Library SHARED Library.H Library.C)
target_include_directories(Library
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include/Library>
)
set_target_properties(Library PROPERTIES VERSION 1.0.0)
install(TARGETS Library EXPORT LibraryConfig)
install(FILES Library.H DESTINATION include/Library)
install(EXPORT LibraryConfig DESTINATION lib/cmake/Library)
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
${PROJECT_BINARY_DIR}/LibraryConfigVersion.cmake
VERSION 1.0.0
COMPATIBILITY SameMajorVersion
)
install(
FILES ${PROJECT_BINARY_DIR}/LibraryConfigVersion.cmake
DESTINATION lib/cmake/Library
)
I just apply version to the target name in form of ${PROJECT_NAME}-${PROJECT_VERSION}
:
install(TARGETS Library EXPORT Library-1.0.0Config)
install(
EXPORT Library-1.0.0Config
DESTINATION lib/cmake/Library-1.0.0Config
)
INSTALL_INTERFACE
for the include directories:target_include_directories(Library
PUBLIC
$<INSTALL_INTERFACE:include/Library-1.0.0>
)
OUTPUT_NAME
property of the target:set_target_properties(Library
PROPERTIES
OUTPUT_NAME Library-1.0.0
)
The result:
file(WRITE Library.H "void Function();")
file(WRITE Library.C "void Function() {}")
add_library(Library SHARED Library.H Library.C)
target_include_directories(Library
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include/Library-1.0.0>
)
set_target_properties(Library PROPERTIES OUTPUT_NAME Library-1.0.0)
install(TARGETS Library EXPORT Library-1.0.0Config)
install(FILES Library.H DESTINATION include/Library-1.0.0)
install(EXPORT Library-1.0.0Config DESTINATION lib/cmake/Library-1.0.0)
But with this approach, I always have to specify the version: find_package(Target-1.0.0 REQUIRED)
.
Upvotes: 1
Views: 479
Reputation: 378
You are working in Config Mode of find_package
, so the search mode according to the documents is like:
<prefix>/(lib/<arch>|lib*|share)/cmake/<name>*/ (U)
<prefix>/(lib/<arch>|lib*|share)/<name>*/ (U)
<prefix>/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/ (U)
So you need to:
INSTALL_INTERFACE
to point to a directory tagged with the library version(with whatever policy you prefer for version matching).OUTPUT_NAME
property of the target to a name tagged with the version.
VERSION
or SOVERSION
property, the result will be a non-version tagged symlink to the tagged one. It will be overridden by other versions and It could cause problems if anyone used it without using CMake.So your sample with above modifications could be like:
file(WRITE Library.H "void Function();")
file(WRITE Library.C "void Function() {}")
add_library(Library SHARED Library.H Library.C)
target_include_directories(Library
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include/Library-1.0.0>
)
set_target_properties(Library PROPERTIES OUTPUT_NAME 1.0.0)
install(TARGETS Library EXPORT LibraryConfig)
install(FILES Library.H DESTINATION include/Library-1.0.0)
install(EXPORT LibraryConfig DESTINATION lib/cmake/Library-1.0.0)
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
${PROJECT_BINARY_DIR}/LibraryConfigVersion.cmake
VERSION 1.0.0
COMPATIBILITY SameMajorVersion
)
install(
FILES ${PROJECT_BINARY_DIR}/LibraryConfigVersion.cmake
DESTINATION lib/cmake/Library-1.0.0
)
With this approach doesn't matter how many version of the library is installed using the same prefix path, the only important thing is the EXACT version name. And the usage could be requesting for a version find_package(Target 1.0.0)
or the last available version find_package(Target)
(based on the search policy and the version matching policy).
Upvotes: 1