【问题标题】:How to merge two "ar" static libraries into one?如何将两个“ar”静态库合并为一个?
【发布时间】:2010-09-29 13:13:33
【问题描述】:

我有 2 个静态 Linux 库,由 ar crlibabc.alibxyz.a 创建。
我想将它们合并到一个静态库中libaz.a
我该怎么做。

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

【问题讨论】:

  • 另见:libtool-based solution:libtool -static -o new.a old1.a old2.a
  • 它工作得很好,只是有点怀疑这些库是否有共同的 file.o(但在功能方面它们是不同的)它还能工作吗?
  • libtool -static -o new.a old1.a old2.a 在 linux(centos 7) 上不起作用

标签: linux static-libraries unix-ar


【解决方案1】:

至少有三种方式原生。第一种也是最便携的方法是使用 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

或者您可以使用 thin 存档(选项-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

【讨论】:

  • 对于那些想要普通存档(不是精简)的人,可以做的一件简单的事情是创建精简存档,然后将其转换为普通存档。类似:ar cqT libaz.a libabc.a libxyz.a &amp;&amp; echo -e 'create libaz.a\naddlib libaz.a\nsave\nend' | ar -M。这会创建一个临时精简版libaz.a,然后将精简存档转换为普通存档(以便您可以移动/分发它)。当您的库名称包含特殊字符(空格、加号或逗号)(即ar cqT libbundle.a libfoo++.a 'libbar baz.a')时,这也可以很好地处理。但是我要 +1!
  • 给出的第一个 MRI 脚本示例有什么缺点?
  • 不错的答案!很高兴看到一些不需要您提取和重新获得的选项。我也认为@Cornstalks 的想法很好。也许应该添加到答案中?
  • 嘿,当我尝试使用libtool 的命令时,我得到了这些错误:libtool: link: unable to infer tagged configuration libtool: error: specify a tag with '--tag' 任何想法如何解决这个问题?
  • @Guillem @Cornstalks 很好的答案。如果在多个 lib*.a 的原始链接命令中需要 --Wl,-whole-archive 选项,我需要将所有 lib*.a 合并到 one.a 中怎么办?再次链接时,--Wl,-whole-archive 将无法与 one.a 一起使用。你的建议是什么? stackoverflow.com/questions/56323197/…
【解决方案2】:

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

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

【讨论】:

  • 危险,威尔罗宾逊!这在 libabc.a 和 libxyz.a 中的成员名称不重叠时有效。否则你会覆盖一个,它会丢失。
  • 此外,libabc.a 可能包含具有相同名称的对象(源自不同的目录)- 重新组装将不起作用!
  • ar -c 对我不起作用(Ubuntu 14.04)。我得到了ar: no operation specified。我改为使用ar -qc,效果很好。
  • ar t lib.a 可用于查看库中的文件,而无需实际提取文件。
  • 如何在 automake 中做到这一点?
【解决方案3】:

如果你只是这样做:

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

如果在 a.a 和 b.a 中都有同名的成员,您将丢失一些目标文件 因此,您需要将不同档案的成员提取到不同的文件夹中:

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 

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

【讨论】:

  • 塞缪尔,谢谢。但是在合并到共享库中时,所有对象都应该用-fPIC编译。
【解决方案4】:

更好的是,您对每个库执行部分链接,然后它们会生成两个生成的目标文件的存档。这样它就可以像共享库一样运行

您使用

进行部分链接
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

【讨论】:

  • 这并没有真正回答所提出的问题——因为他要求图书馆。很多时候,您甚至没有给定库的源代码,或者出于其他原因想要保留它们的预构建。
  • 它确实回答了这个问题,您也可以使用库,但对于静态库,您需要 -Wl,--whole-archive。
【解决方案5】:

你总是可以做部分链接:

gcc -r -o libnew.o -Wl,--whole-archive libabc.a libxyz.a
ar cr libnew.a libnew.o

【讨论】:

    【解决方案6】:
    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”

    【讨论】:

      【解决方案7】:
      ar crsT libaz.a libabc.a libxyz.a
      

      在这里,您创建档案档案,然后使用 T 标志“展平”(细化)结果。 不确定它如何处理可能包含在其中的同名 .o 文件。

      【讨论】:

        【解决方案8】:

        这个问题是针对 Linux 的。如果您正在寻找如何在 macOS 上执行此操作,答案是 libtoolas explained here

        libtool -static -o new.a old1.a old2.a
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-11-09
          • 1970-01-01
          • 1970-01-01
          • 2012-06-22
          • 2021-11-08
          • 2022-11-25
          相关资源
          最近更新 更多