Hi,
I have a header-only library mylib consisting of the header mylib.h . Inside the header I have a template function. Given a preprocessor macro USE_FAST_LIB the implementation of that function redirects to a third party library “fastlib”. When writing my CMakeLists.txt it looks something like
cmake_minimum_required(VERSION 3.26)
project(mylib LANGUAGES CXX)
option(MYLIB_USE_FAST_LIB “Use fast third-party implementation” OFF)
For some reason my e-mail was not formatted correctly here, so I repost my question
Hi,
I have a header-only library mylib consisting of the header mylib.h . Inside the header I have a template function. Given a preprocessor macro USE_FAST_LIB the implementation of that function redirects to a third party library “fastlib”. When writing my CMakeLists.txt it looks something like
My question is: How do I need to write the install rules and package configuration file such that downstream users can use mylib like
# Optionally, before find_package:
set(MYLIB_USE_FAST_LIB ON) # or OFF
find_package(mylib REQUIRED)
target_link_libraries(their_target PRIVATE mylib::mylib)
I.e. they can optionally opt in or out of using the third party library fastlib (because it may not be available on all systems / target-architectues or may not be freely available etc). I know a downstream user can use FetchContent (or CPM) instead of find_package and the above example works. But I have not managed to achieve the same following the cmake tutorial https://cmake.org/cmake/help/latest/guide/importing-exporting/index.html meaning my installed IMPORTED targets have the option “baked-in” depending on what I choose at configuration time of mylib and the option to choose is no longer available to a downstream user. I also dislike the option of providing two targets mylib::mylib_fast and mylib::mylib_regular because it is (i) not scalable with the number of configuration options and (ii) it just pushes the problem off to downstream users who then face the same issue. In my mind there should not be a difference in cmake between importing an interface target with CPMAddPackage / FetchContent or find_package (after all it is the same header file that is being imported and the same configuration options for that header should be exposed to a downstream user).
How do I need to modify the install-rules.cmake and the install-config.cmake such that a downstream user of find_package(mylib) can set an option MYLIB_USE_FAST_LIB as described above?
Thank you for the reply. Just to clarify that I understand this correctly The find_package( OpenSSL QUIET) line will set the OpenSSL_FOUND variable that you use to conditionally add the OpenSSL and Threads targets to the interface of asio::asio_headers?
I have a couple of follow-up questions: Why can’t you use target_link_librarires( asio_headers INTERFACE OpenSSL::SSL) instead of set_target_properties?
Also, I am wondering how this is working when the asio library is installed because in your main CMakeLists.txt you have the line find_package( OpenSSL REQUIRED) and target_link_libraries(asio_header INTERFACE OpenSSL::SSL OpenSSL::Crypto)
So to my understanding the asio library can never be configured without OpenSSL because cmake throws an error if OpenSSL is not available. So when someone installs the asio library the OpenSSL_FOUND variable is always true because it cannot be configured without it? What am I missing?
That is the tricky part of CMake:
I checked the stagedir/lib/cmake/asioTargets-debug.cmake
#----------------------------------------------------------------
# Generated CMake target import file for configuration "Debug".
#----------------------------------------------------------------
# Commands may need to know the format version.
set(CMAKE_IMPORT_FILE_VERSION 1)
# Import target "asio::asio" for configuration "Debug"
set_property(TARGET asio::asio APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(asio::asio PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX"
IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/libasioD.a"
)
list(APPEND _cmake_import_check_targets asio::asio )
list(APPEND _cmake_import_check_files_for_asio::asio "${_IMPORT_PREFIX}/lib/libasioD.a" )
# Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION)
in stagedir/lib/cmake/asioTargets.cmake you will find this: