问题描述
我有一个与 cmake 上的 描述 非常相似的问题邮件列表,我们有一个依赖于许多静态库的项目(全部从单个子模块中的源代码构建,每个子模块都有自己的 CMakeLists.txt 描述每个库的构建过程),我想将它们组合成一个静态库以供发布给消费者.我的库的依赖项可能会发生变化,我不希望这些变化给链下游的开发人员带来负担.简洁的解决方案是将所有库捆绑到一个库中.
I have a very similar problem to one described on the cmake mailing list where we have a project dependent on many static libraries (all built from source in individual submodules, each with their own CMakeLists.txt describing the build process for each library) that I'd like to combine into a single static library for release to the consumers. The dependencies of my library are subject to change, and I do not want to burden developers further down the chain with those changes. The neat solution would be to bundle all of the libs into one single lib.
有趣的是,在将目标设置为 mylib
并像这样使用它时,target_link_libraries
命令并没有结合所有的静态..
Interestingly, the target_link_libraries
command does not combine all of the statics when setting the target to mylib
and using it like so . .
target_link_libraries(mylib a b c d)
然而,奇怪的是,如果我使 mylib
项目成为可执行项目的子模块,并且只链接到顶级可执行文件 CMAkeLists.txt 中的 mylib
,库似乎是结合在一起的.IE.mylib 是 27 MB,而不是我将目标设置为仅构建 mylib
时的 3MB.
However, bizarrely, if I make the mylib
project a submodule of an executable project, and only link against mylib
in the top level executable CMAkeLists.txt, the library does seem to be combined. I.e. mylib is 27 MB, instead of the 3MB when I set the target to only build mylib
.
有一些解决方案描述了将库解包为目标文件并重新组合(此处 和 此处),但这似乎非常当 CMake 看起来完全有能力自动合并库时,就像上面的例子中描述的那样笨拙.是否有我遗漏的魔法命令,或者推荐的制作发布库的优雅方式?
There are solutions describing unpacking of the libs into object files and recombining (here, and here), but this seems remarkably clumsy when CMake seems perfectly capable of automatically merging the libs as described in the above example. It there a magic command I'm missing, or a recommended elegant way of making a release library?
推荐答案
给出我能想到的最简单的工作示例:2 个类,a
和 b
,其中a
依赖于 b
..
Given the most simple working example I can think of: 2 classes, a
and b
, where a
depends on b
. .
#ifndef A_H
#define A_H
class aclass
{
public:
int method(int x, int y);
};
#endif
a.cpp
#include "a.h"
#include "b.h"
int aclass::method(int x, int y) {
bclass b;
return x * b.method(x,y);
}
b.h
#ifndef B_H
#define B_H
class bclass
{
public:
int method(int x, int y);
};
#endif
b.cpp
#include "b.h"
int bclass::method(int x, int y) {
return x+y;
}
main.cpp
#include "a.h"
#include <iostream>
int main()
{
aclass a;
std::cout << a.method(3,4) << std::endl;
return 0;
}
可以将它们编译成单独的静态库,然后使用自定义目标组合静态库.
It is possible to compile these into separate static libs, and then combine the static libs using a custom target.
cmake_minimum_required(VERSION 2.8.7)
add_library(b b.cpp b.h)
add_library(a a.cpp a.h)
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 a b
)
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
版本的自定义目标也可以正常工作...
It also works just fine using Apple's libtool
version of the custom target . . .
add_custom_target(combined
COMMAND libtool -static -o ${C_LIB} $<TARGET_FILE:a> $<TARGET_FILE:b>
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
DEPENDS a b
)
仍然接缝,好像应该有一个更整洁的方法..
Still seams as though there should be a neater way . .
这篇关于使用 CMake 将多个静态库合二为一的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!