将存档链接到存档

时间:2017-06-13 07:42:55

标签: c linux gcc linker static-libraries

在Linux上使用GCC,是否可以将.a链接到另一个.a然后只将结果.a链接到我的应用程序?或者我的应用程序必须知道一个存档与另一个存档之间的依赖关系并将它们链接起来吗?

我的理解是,我必须知道依赖关系,并在最后链接所有档案,而不是中间步骤,这似乎有点难看。

这与How to merge two "ar" static libraries into one略有不同,因为我清楚地描述了这只能通过解决问题并且以天真的方式将两个档案链接在一起是不正确的并且不会起作用。原因就是为什么。

2 个答案:

答案 0 :(得分:1)

libx.aliby.a成为您想要合并的模块。你可以试试: -

mkdir tmp                 # create temporary directory for extracting 
cd tmp
ar x ../libx.a            # extract libx.a
cp ../liby.a ../libxy.a
ar -q ../libxy.a *        # add extracted files to libxy.a
cd ..
rm -rf tmp
这样创建的

libxy.a包含.o个文件中的.a个文件

答案 1 :(得分:1)

是的,您的应用程序必须知道不同静态库之间的依赖关系。

  • 假设您有两个静态库ab
  • a的功能为void print_a()b的功能void print_b()正在呼叫print_a()。因此,b取决于a
  • 他们的二进制文件看起来像liba.alibb.a

假设库b引用了库a中定义的函数 - void print_b(void)。 在编译库b时,只在二进制代码部分中定义其符号,而其他符号仍未定义:

host$ nm libb.a | grep print
                 U _print_a          <--- Undefined
0000000000000000 T _print_b          <--- Defined, in code section
0000000000000068 S _print_b.eh
                 U _printf

因此,在编译想要使用这两个库的应用程序时,仅链接到libb.a是不够的。您必须将应用程序链接到两个库。每个库将在代码部分提供自己的符号地址,然后您的应用程序将能够链接到两者。

类似的东西:

gcc -o main main.c libb.a liba.a

BTW:在编译使用b的库a时,您可以但不必链接到a。结果将是一样的。

为什么这是行为

在编译+链接使用静态库的应用程序时,必须在某处定义应用程序源文件中的符号(动态链接除外,但这只能使用动态库/共享对象完成。这里我们处理静态的)。

现在,请记住,静态库只是对象的归档。当它被创建时,没有链接阶段。只是:

  1. 将源代码(*.c)编译为对象(*.o
  2. 将它们存档在libXXXX.a文件中。
  3. 这意味着如果此库(我的示例中的库b)使用在另一个库(void print_a(void))中定义的某个函数(a),则此符号将不会已解决(不是编译错误,而是正常行为)。在创建库之后,它将被设置为 Undefined 符号(正如我们在nm命令的输出中看到的那样),它将等待稍后链接到其定义。它没关系,因为静态库不可执行。

    现在返回应用程序 - 应用程序的链接阶段需要找到所有符号的所有定义。如果您只是将libb.a作为参数,它将无法找到print_a()的定义,因为它不存在,它仍然是未定义。它仅存在于liba.a

    因此,您必须提供两个库。