Answer the question
In order to leave comments, you need to log in
How to include all dependencies from other static libraries in a CMake project into a static library?
It is required to build a static library using CMake in a platform-independent way, in which all dependencies from other static libraries are already included.
A simplified example of what CMakeLists.txt looks like now:
cmake_minimum_required(VERSION 3.5)
find_package(Boost COMPONENTS system filesystem thread REQUIRED)
add_library (mylib mysource.cpp)
The project creates a static mylib library, but it does not include the required boost implementation, i.e. when linking applications with mylib need to be explicitly told to link boost.
I would like to avoid this, that is, it is necessary that all dependencies on boost be already included in mylib.
I would like to do this using CMake (without additional scripts, only expanding CMakeLists.txt) and cross-platform.
Answer the question
In order to leave comments, you need to log in
Although I would certainly advise using find_package/add_subdirectory to include this lib in the program, but if you still need to get a static lib, then you can try something like this (based on this answer https://stackoverflow.com/a/37941544 /9953527):
CMakeLists.txt:
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
project(mylib_combined VERSION 0.1 LANGUAGES CXX)
# Нам нужны статические либы
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost COMPONENTS system filesystem REQUIRED)
# Наша собственная либа.
# К сожалению мы не может использовать add_library OBJECT либу, т.к.
# CMake не умеет работать с IMPORTED OBJECT либами, т.е. он не умеет
# экстрактить (ar -x) существующею static либу, чтобы собрать её потом
# в одну большую (ar -qcs).
add_library(mylib mylib.cpp)
add_custom_command(
TARGET mylib
POST_BUILD
# Экстрактим нашу свежесобранную либу. Не самое красивое решение, но
# что поделать ¯\_(ツ)_/¯
COMMAND ar -x $<TARGET_FILE:mylib>
# Теперь наши буст либы
COMMAND ar -x ${Boost_SYSTEM_LIBRARY}
COMMAND ar -x ${Boost_FILESYSTEM_LIBRARY}
# А теперь собираем всё обратно
COMMAND ar -qcs lib${PROJECT_NAME}.a *.o
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
project(mylib_combined VERSION 0.1 LANGUAGES CXX)
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost COMPONENTS system filesystem REQUIRED)
add_library(mylib mylib.cpp)
add_custom_target(mylib_packer
COMMAND ar -x $<TARGET_FILE:mylib>
COMMAND ar -x ${Boost_SYSTEM_LIBRARY}
COMMAND ar -x ${Boost_FILESYSTEM_LIBRARY}
COMMAND ar -qcs lib${PROJECT_NAME}.a *.o
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
DEPENDS mylib
)
add_library(mylib_combined STATIC IMPORTED GLOBAL)
add_dependencies(mylib_combined mylib_packer)
set_target_properties(mylib_combined
PROPERTIES
IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/lib${PROJECT_NAME}.a
)
Lord, what did they advise for crutches))
As jcmvbkbc rightly pointed out , usually one stat. the library does not drag in itself another. Moreover, such an opportunity is to enable one stat. library into another one - it exists in few places, I know about support for such a feature only in Visual Studio. Well, i.e. this is something out of the ordinary, and not the usual workflow. Normally, you should specify when linking stat. library, all its dependencies. Therefore, the question is how to transfer and use this information about the transitive dependencies of a static library when linking with it.
pkg-config is generally quite a normal solution, but it is no longer quite "within CMake".
Within CMake, everything is done using target_link_libraries and exporting the simak config paired with the simak targets file. For example, here is a simple script:
cmake_minimum_required(VERSION 3.5)
find_package(Boost COMPONENTS system filesystem thread REQUIRED)
add_library (mylib mysource.cpp)
target_link_libraries(mylib
PRIVATE
Boost::system
Boost::filesystem
Boost::thread
)
install(TARGETS mylib EXPORT mylib_export)
export(EXPORT mylib_export FILE cmake/mylib-targets.cmake)
mylib-targets.cmake
, among other things, the following interesting information:# Create imported target mylib
add_library(mylib STATIC IMPORTED)
set_target_properties(mylib PROPERTIES
INTERFACE_LINK_LIBRARIES "\$<LINK_ONLY:Boost::system>;\$<LINK_ONLY:Boost::filesystem>;\$<LINK_ONLY:Boost::thread>"
)
# Create imported target mylib
add_library(mylib STATIC IMPORTED)
set_target_properties(mylib PROPERTIES
INTERFACE_LINK_LIBRARIES "Boost::system;Boost::filesystem;Boost::thread"
)
mylib-targets.cmake
) and do it in consumers find_package(mylib)
. All this is cross-platform and is standard practice, do not do unnecessary perversions with the merging of static libraries.
The project creates a static mylib library, but it does not include the required boost implementation, that is, when linking an application with mylib, you must explicitly indicate that you need to link boost.
pkg-config --libs <имя библиотеки>
and receives a list of keys to link.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question