I'm currently writing a c++ library, that has several "sub libraries", like for example the boost library.
Let's name the library "TestLib" and the sub libraries "Base" and "Ext", where Base contains come basic stuff, that doesn't depend an any other sub library. Ext however depends on some classes of Base.
Each "sub library" should compile into a separate .a or .so file, but they all should share a namespace (TestLib). Now i'm aiming to write clean cmake scripts in order to achieve this goal.
In the end i want to be able to do something like this in cmake:
find_package(TestLib 0.1 REQUIRED COMPONENTS Base Ext)
or
target_link_libraries(someapplication
PUBLIC
TestLib::Base
)
I have put each "sub library" in a separate git repository and added them as submodules in a new repository that has only a CMakeLists.txt that just calls add_subdirectory on each of the repos.
Most of the cmake stuff i achieved, i got from this awesome tutorial at https://pabloariasal.github.io/
And the Base part works as intended (which is no wonder, since it doesn't depend on anything else).
But my problems come with the Ext part. In order for this to compile, i have to link against the Base library, which shouldn't be to hard, and with some trial and error i am sure that i will get it to work.
But i want to do it the right way.
My approach was to
find_package(TestLib COMPONENTS Base)
in the CMakeLists.txt of TestLib.Ext. But this cant be found since it has no TestLibConfig.cmake.
Which makes sense, but i don't know what to put in this file.
I tried to provide some code that exactly describes my problem, but since this would be too much to post here, i created a github for this purpose:
https://github.com/PowerSupplyTopologies/TestLib
This should contain all the relevant code.
This could be trivial to some of you, but i bet there are more people that could benefit from this approach.
Thank you in advance for any of your thoughts.
EDIT:
The library creation in the CMakeLists.txt of Base is:
set(TARGET_NAME testlibbase)
add_library(${TARGET_NAME}
src/ClassA.cpp
src/ClassB.cpp
)
#Add an alias so that library can be used inside the build tree, e.g. when testing
add_library(TestLib::${TARGET_NAME} ALIAS ${TARGET_NAME})
and
set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/TestLib)
install(TARGETS ${TARGET_NAME}
EXPORT ${TARGET_NAME}-targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
#This is required so that the exported target has the name JSONUtils and not jsonutils
set_target_properties(${TARGET_NAME} PROPERTIES EXPORT_NAME Base)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
#Export the targets to a script
install(EXPORT ${TARGET_NAME}-targets
FILE
TestLibBaseTargets.cmake
NAMESPACE
TestLib::
DESTINATION
${INSTALL_CONFIGDIR}
)
#Create a ConfigVersion.cmake file
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/TestLibBaseConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion
)
configure_package_config_file(${CMAKE_CURRENT_LIST_DIR}/cmake /TestLibBaseConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/TestLibBaseConfig.cmake
INSTALL_DESTINATION ${INSTALL_CONFIGDIR}
)
#Install the config, configversion and custom find modules
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/TestLibBaseConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/TestLibBaseConfigVersion.cmake
DESTINATION ${INSTALL_CONFIGDIR}
)
##############################################
## Exporting from the build tree
export(EXPORT ${TARGET_NAME}-targets FILE ${CMAKE_CURRENT_BINARY_DIR}/TestLibBaseTargets.cmake NAMESPACE TestLib::)
and of Ext:
set(TARGET_NAME testlibext)
add_library(${TARGET_NAME}
src/ClassC.cpp
)
#Add an alias so that library can be used inside the build tree, e.g. when testing
add_library(TestLib::${TARGET_NAME} ALIAS ${TARGET_NAME})
add_library
), which creates.cmake
files and installs them. – Livesay