Merge multiple static libraries into one using CMake

I have a very similar problem to the one described on the cmake mailing list, where we have a project that depends on many static libraries (all built from the source in separate submodules, each with its own CMakeLists.txt, which describes the build process for each library), which I I would like to combine into one static library for release for consumers. The dependencies of my library are subject to change, and I do not want to burden developers further down the chain with these changes. The best solution would be to combine all the libraries into one lib unit.

Interestingly, the target_link_libraries command target_link_libraries not combine all statistics when setting up the target on mylib and uses it like this.,

 target_link_libraries(mylib abcd) 

However, as if it were unusual, if I make the mylib project a submodule of the executable project and only attach to mylib in the top-level CMAkeLists.txt executable, the library seems to be merging. That is, mylib is 27 MB, instead of 3 MB, when I set the target for mylib build only.

There are solutions that describe unpacking libs into object files and recombining ( here and here ), but it seems surprisingly awkward when CMake seems quite capable of automatically merging libraries, as described in the example above. Is it the magic team I'm missing out there, or the recommended elegant way to create a release library?

+6
source share
1 answer

Given the simplest working example, I can think of: 2 classes, a and b , where a depends on b ..

hijras

 #ifndef A_H #define A_H class aclass { public: int method(int x, int y); }; #endif 

a.cpp

 #include "ah" #include "bh" int aclass::method(int x, int y) { bclass b; return x * b.method(x,y); } 

bh

 #ifndef B_H #define B_H class bclass { public: int method(int x, int y); }; #endif 

b.cpp

 #include "bh" int bclass::method(int x, int y) { return x+y; } 

main.cpp

 #include "ah" #include <iostream> int main() { aclass a; std::cout << a.method(3,4) << std::endl; return 0; } 

You can compile them into separate static libraries, and then combine the static libraries with a custom target.

 cmake_minimum_required(VERSION 2.8.7) add_library(b b.cpp bh) add_library(a a.cpp ah) add_executable(main main.cpp) set(C_LIB ${CMAKE_BINARY_DIR}/libcombi.a) add_custom_target(combined COMMAND ar -x $<TARGET_FILE:a> COMMAND ar -x $<TARGET_FILE:b> COMMAND ar -qcs ${C_LIB} *.o WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS ab ) add_library(c STATIC IMPORTED GLOBAL) add_dependencies(c combined) set_target_properties(c PROPERTIES IMPORTED_LOCATION ${C_LIB} ) target_link_libraries(main c) 

It also works great using the libtool version for the custom Apple libtool target.,.

 add_custom_target(combined COMMAND libtool -static -o ${C_LIB} $<TARGET_FILE:a> $<TARGET_FILE:b> WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS ab ) 

Still seams, as if there should be a tidier way ..

+4
source

All Articles