如何将两个“ ar”静态库合并为一个?


90

我有2个静态的Linux库,通过创建ar crlibabc.alibxyz.a
我想将它们合并到一个静态库中libaz.a
我怎样才能做到这一点。

我想创建一个合并的静态库,而不是将这两个库都提供给应用程序的最终链接。


7
另请参见:libtool基于解决方案的解决方案libtool -static -o new.a old1.a old2.a
osgx 2014年

2
它运行完美,只是有点怀疑那些库是否具有通用文件。o(但是功能上它们是不同的)它仍然可以工作吗?
bindingofisaac 2015年

libtool -static -o new.a old1.a old2.a在linux(centos 7)上
不起作用

Answers:


59

您可以从两个.a文件中提取对象,然后.a使用提取的.os创建文件:

ar -x libabc.a
ar -x libxyz.a
ar -c libaz.a  *.o

63
危险,威尔·鲁滨逊!这工作如果libabc.a成员和libxyz.a的名称不重叠。否则,您将覆盖其中一个,它将丢失。
大卫·吉夫

6
而且,libabc.a可能包含具有相同名称的对象(起源于不同目录)-那么重新组装将无法进行!
伊戈尔·R。

15
ar -c不适用于我(Ubuntu 14.04)。我知道了ar: no operation specified。我做了ar -qc,那做得很好。
2014年

ar t lib.a可用于查看库中的文件,而无需实际提取文件。
raj_gt1 2015年

我该如何在automake中做到这一点?
舒瓦'16

119

本地至少有三种方法可以执行此操作。第一种也是最可移植的方法是使用libtool。在也使用libtool构建了其他库之后,可以通过将.la库添加到automake libaz_la_LIBADD变量中或直接从Makefile中添加以下内容来将它们组合:

libtool --mode=link cc -static -o libaz.la libabc.la libxyz.la

其他两个至少在使用GNU ar时可用。您可以使用MRI脚本(例如,libaz.mri),例如:

create libaz.a
addlib libabc.a
addlib libxyz.a
save
end

然后将ar执行为:

ar -M <libaz.mri

或者,您可以使用一个精简的归档文件(选项-T),该归档文件将允许添加其他归档文件而不将其嵌套在内部,尽管不利之处在于,如果您要分发静态库,将缺少分离的对象:

ar -rcT libaz.a libabc.a libxyz.a

以上所有方法都可以正常处理原始档案中的重叠成员名称。

否则,您将必须解压缩到其他目录中并再次重新打包,以避免替换重叠的成员名称:

mkdir abc; cd abc; ar -x ../libabc.a
mkdir xyz; cd xyz; ar -x ../libxyz.a
ar -qc libaz.a abc xyz

19
对于需要普通存档(不是精简版)的用户,可以做的一件简单的事情是创建精简存档,然后将其转换为普通存档。类似于:ar cqT libaz.a libabc.a libxyz.a && echo -e 'create libaz.a\naddlib libaz.a\nsave\nend' | ar -M。这将创建一个临时的Thin文件libaz.a,然后将其转换为普通文件(因此您可以移动/分发它)。当您的库名称具有特殊字符(空格,加号或逗号)(即ar cqT libbundle.a libfoo++.a 'libbar baz.a')时,这也可以正常处理。但是我+1。
2014年

给出的第一个MRI脚本示例的不利之处是什么?
2014年

好答案!很高兴看到一些不需要您提取和重新实现的选项。我也认为@Cornstalks的想法很好。也许应该添加到答案中?
Lightbulb1 2015年

嘿,当我尝试使用该命令时,出现libtool以下错误:有libtool: link: unable to infer tagged configuration libtool: error: specify a tag with '--tag' 任何解决方法吗?
拉尔斯·尼尔森

@Guillem @Cornstalks好答案。如果--Wl,-whole-archive多个lib * .a的原始链接命令中需要该选项怎么办,而我需要将所有lib * .a合并为one.a。再次链接时,--Wl,-whole-archive将无法使用one.a。你有什么建议?stackoverflow.com/questions/56323197/…–
thinkdeep

10

如果您只是这样做:

ar x a.a
ar x b.a
ar c c.a  *.o 

如果aa和ba中都有相同名称的成员,则会丢失一些目标文件,因此,您需要将不同档案的成员提取到不同的文件夹中:

ar x a.a && mv *.o a_objs
ar x b.a && mv *.o b_objs
ar c c.a a_objs/*.o b_objs/*.o

此外,有可能在一个档案中有多个同名成员(例如在aa中),如果运行ar x aa,则对于那些同名成员只会得到一个。

提取一个档案中所有同名成员的唯一方法是通过选项“ N”指定成员编号:

ar xN 1 a.a  xxx.c.o && mv xxx.c.o xxx.c.1.o
ar xN 2 b.a  xxx.c.o && mv xxx.c.o xxx.c.2.o
...

这将是一件繁琐的工作,因此您必须编写一个更复杂的脚本才能完成该工作。

一种可选的解决方案是,您可以将多个归档合并到一个共享库中:

g++ -shared -o c.so -Wl,--whole-archive a.a b.a 

这样,链接器将为您处理所有事情!


1
塞缪尔,谢谢。但是在合并到共享库中时,所有对象都应使用进行编译-fPIC
2014年

0

更好的是,您对每个库执行部分链接,它们将两个结果对象文件存档。这样,它就像共享库一样运行

您可以进行部分链接

gcc -r --nostdlib

因此,要么制作中间存档,要么重新提取中间存档,然后运行

gcc -r --nostdlib $CFLAGS $OBJECTS_A -o $LIBNAME_A.o
gcc -r --nostdlib $CFLAGS $OBJECTS_B -o $LIBNAME_B.o

然后

ar -cr $LIBNAME_JOINED.a $LIBNAME_A.o $LIBNAME_B.o

这并不是真正回答的问题-因为他要图书馆。很多时候,您甚至没有提供库的源,或者出于其他原因希望保留它们的预构建。
pholat,

0
ar -x libx264.a
mkdir sub && cd sub
ar -m ../libx264.a `ar -t ../libx264.a |sort|uniq|grep "\.o"`
ar -x ../libx264.a

现在您有两个版本的“ macroblock-10.o”


0
ar crsT libaz.a libabc.a libxyz.a

在这里,您可以创建归档文件的归档文件,然后使用T标志对结果进行“扁平化”(稀化)。不知道它将如何与可能包含在其中的同名.o文件一起使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.