I have a static library built using cmake and I'm trying to integrate it to vcpkg. The library has some wrappers for things like ssl
using openssl
and sqlite
databases but they are optional and not required to used other parts of the library. The source files looks like this:
include:
core.h
ssl.h
sql.h
src:
core.cpp
ssl.cpp
sql.cpp
the source files ssl.cpp
and sql.cpp
include the headers from openssl
and sqlite
to implement their functionality but core.cpp
does not need either of them. I used vcpkg manifest features to enable any feature and I check in the cmake script to enable features on demand:
if (OPENSSL_FEATURE)
find_package(OpenSSL REQUIRED)
target_compile_definitions(thelib PUBLIC HAVE_OPENSSL)
target_link_libraries(thelib PRIVATE OpenSSL::SSL PRIVATE OpenSSL::Crypto)
endif()
Now I have another library which depends on the core part of this previous library and also built with cmake and vcpkg:
find_package(thelib REQUIRED)
target_link_libraries(otherlib PRIVATE thelib)
but cmake is giving an error saying that thelib
depends on OpenSSL::SSL
and other libraries but it was not found. When I added the proper find_package
to find these packages without target_link_libraries
then the build passes but now consumers of otherlib
will try to link to thelib
and will be required to find all the packages required even it is not used by the consumer.
I thought that using PRIVATE
in target_link_libraries
will hide the dependencies from the consumers but it turned out that dependencies of a static library are added to the link targets even if PRIVATE
is used.
The solution I'm thinking of is to split the library into several libraries which depend on each other as required but for a small library and basic things like this it is very annoying and much of work.
Does anyone know how to instruct cmake to link only the used packages ?
EDIT: To clarify more the problem is that in the thelib-target.cmake
generated by installing the target and included in thelib-config.cmake
there exists this cmake code:
set_target_properties(thelib::thelib PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "HAVE_OPENSSL;HAVE_SQLITE"
INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
INTERFACE_LINK_LIBRARIES "\$<LINK_ONLY:OpenSSL::SSL>;\$<LINK_ONLY:OpenSSL::Crypto>;\$<LINK_ONLY:SQLite::SQLite3>"
)
which requires those dependencies to be visible when linking against thelib
but otherlib
does not need to use target_link_libraries
to link any of them but only find_package
to make them visible and also the final executable result will not include the libraries it does not use because adding a library to the linker line only adds it to the linker search set and if it is not referenced by the executable it will not be included.
The problem is that consumers are required to use find_package
to search for unused libraries.
I see that some libraries contain many dependencies like POCO
but it builds many libraries and consumer are free to link against any of them.
I don't want to create many libraries. Can cmake components solve this problem ?
The way I got around this problem is by dividing the library into several libraries and link the required components per application demand. I am not an expert in cmake so I used the template from this repo to get it: https://github.com/ClausKlein/cmake-example-component-lib