使用CMake将几个静态库合并为一个

我有一个非常类似于cmake邮件列表中描述的问题,我们有一个依赖于许多静态库的项目(都是从各个子模块中的源代码构建的,每个子库都有自己的CMakeLists.txt描述每个库的构建过程)我想组合成一个静态库,以便向消费者发布。 我的库的依赖性可能会发生变化,我不想让开发人员在这些变化的后面进一步负担。 简洁的解决方案是将所有lib捆绑到一个单独的lib中。

有趣的是,在将目标设置为mylib并使用它时, target_link_libraries命令并未组合所有静态。 。

 target_link_libraries(mylib abcd) 

但是,奇怪的是,如果我将mylib项目作为可执行项目的子模块,并且仅在顶级可执行文件CMAkeLists.txt中链接mylib ,那么该库似乎确实是组合在一起的。 即,当我将目标设置为仅构建mylib时,mylib为27 MB,而不是3 MB。

有一些解决方案描述了将lib解压缩到目标文件并重新组合( 这里和这里 ),但是当CMake看起来完全能够自动合并lib时,这似乎非常笨拙,如上例所述。 它有一个我失踪的神奇命令,或推荐的优雅方式制作发布库?

给出最简单的工作示例,我可以想到:2个类, ab ,其中a取决于b 。 。

 #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  int main() { aclass a; std::cout << a.method(3,4) << std::endl; return 0; } 

可以将它们编译为单独的静态库,然后使用自定义目标组合静态库。

 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 $ COMMAND ar -x $ 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) 

使用Apple的libtool版本的自定义目标也可以正常工作。 。 。

 add_custom_target(combined COMMAND libtool -static -o ${C_LIB} $ $ WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS ab ) 

仍然接缝似乎应该有一个更简洁的方式。 。

如果您尝试合并的库来自第三方,那么(遵循learnvst示例)此代码会处理可能的.o文件替换(例如,如果liba和libb都有文件名zzz.o)

 ## Create static library (by joining the new objects and the dependencies) ADD_LIBRARY("${PROJECT_NAME}-static" STATIC ${SOURCES}) add_custom_command(OUTPUT lib${PROJECT_NAME}.a COMMAND rm ARGS -f *.o COMMAND ar ARGS -x ${CMAKE_BINARY_DIR}/lib${PROJECT_NAME}-static.a COMMAND rename ARGS 's/^/lib${PROJECT_NAME}-static./g' *.o COMMAND rename ARGS 's/\\.o/.otmp/g' *.o COMMAND ar ARGS -x ${CMAKE_SOURCE_DIR}/lib/a/liba.a COMMAND rename ARGS 's/^/liba./g' *.o COMMAND rename ARGS 's/\\.o/.otmp/g' *.o COMMAND ar ARGS -x ${CMAKE_SOURCE_DIR}/lib/b/libb.a COMMAND rename ARGS 's/^/libb./g' *.o COMMAND rename ARGS 's/\\.o/.otmp/g' *.o COMMAND rename ARGS 's/\\.otmp/.o/g' *.otmp COMMAND ar ARGS -r lib${PROJECT_NAME}.a *.o COMMAND rm ARGS -f *.o DEPENDS "${PROJECT_NAME}-static") add_custom_target(${PROJECT_NAME} ALL DEPENDS lib${PROJECT_NAME}.a) 

否则,如果库是你的,你应该使用CMake OBJECT库,这是一个很好的机制来合并它们。