Linker ranlib、ar和ld在创建库方面有什么区别

Linker ranlib、ar和ld在创建库方面有什么区别,linker,ld,unix-ar,Linker,Ld,Unix Ar,为了从*.o文件生成c++/unix中的库,我注意到在我的项目中有两种不同的方法(遗留代码): 及 这两种方法的区别是什么?使用哪种方法的目的是什么?ar 在Linux中,是GNU通用归档程序。 (在其他类似Unix的操作系统中,存在ar的非GNU变体)。使用选项c ar c... archive-name file... 它创建一个包含文件…副本的存档。存档名称按惯例 但不一定有扩展名.a(用于存档)。每个文件…可能是 任何类型的文件,不一定是对象文件 当归档文件都是目标文件时,通常打算使用

为了从*.o文件生成c++/unix中的库,我注意到在我的项目中有两种不同的方法(遗留代码):

这两种方法的区别是什么?使用哪种方法的目的是什么?

ar

在Linux中,是GNU通用归档程序。 (在其他类似Unix的操作系统中,存在
ar
的非GNU变体)。使用选项
c

ar c... archive-name file...
它创建一个包含
文件…
副本的存档。
存档名称
按惯例 但不一定有扩展名
.a
(用于存档)。每个
文件…
可能是 任何类型的文件,不一定是对象文件

当归档文件都是目标文件时,通常打算使用 用于将选定的目标文件传递到程序链接中的存档 或DSO(动态共享对象)。在这种情况下,
archive name
通常也会被赋予前缀
lib
,例如。
libfoo.a
,以便可以通过链接器选项
-lfoo
将其作为候选链接器输入文件进行查找

用作链接器输入文件,
libfoo.a
通常称为静态库。这 对于不熟练的程序员来说,用法永远是一个困惑的根源,因为它会导致他们困惑 想一想归档文件
libfoo.a
与DSO是同一种东西,
libfoo.so
, 通常称为动态/共享库,并在此基础上建立错误的期望 基础。事实上,“静态库”和“动态库”根本不相似 并且以完全不同的方式在链接中使用

一个明显的区别是静态库不是由链接器生成的, 但是通过
ar
。因此,不会发生链接,也不会发生符号解析。存档的 对象文件是不变的:它们只是放在一个袋子里

当一个归档文件被输入到由 链接器-如程序或DSO-链接器查看包中是否有 其中是否有为未解析符号引用提供定义的任何对象文件 这些都是在早期的联系中积累起来的。如果找到任何对象文件,它将从中提取这些对象文件 该包并将它们链接到输出文件中,就像它们被单独命名一样 在链接器命令行和存档中根本没有提到。那么整个 链接中的归档文件的角色是链接器可以从中访问的对象文件包 选择需要进行联动的部件

默认情况下,GNU
ar
使其输出档案准备好用作链接器输入。它添加了一个虚假的“文件” 到归档文件中,使用一个神奇的假文件名,并在这个假文件中写入 链接器能够从定义的全局符号中读取查找表 将存档中的任何对象文件复制到这些对象的名称和位置 档案中的文件。此查找表使链接器能够查找 存档并标识定义任何未解析符号引用的任何对象文件 它已经控制住了

您可以使用
q
(= 快速)选项-事实上您已经在自己的
ar
示例中使用了该选项,并且 使用(大写)
S
(=无符号表)选项。如果您调用
ar
来创建或更新 由于任何原因没有(最新)符号表的存档,那么您 可以使用
s
选项为其设置一个

ranlib

没有 创建所有的库。在Linux中,
ranlib
是一个传统程序,它添加了一个(最新的) 将符号表添加到
ar
存档(如果没有)。它的效果正是 与
ar s
相同,带有GNU
ar
。历史上,在配备ar生成 一个符号表本身,
ranlib
就是注入这个神奇虚假文件的乱码 进入存档,以使链接器能够从中拾取对象文件。非GNU 与Unix类似的操作系统,
ranlib
可能仍然需要用于此目的。你的例子是:

ar qc libgraphics.a *.o
ranlib libgraphics.a
ld -r -o libgraphics.a *.o
说:

  • 创建
    libgraphics.a
    ,方法是将当前数据库中的所有
    *.o
    文件附加到存档文件中 目录,没有符号表
  • 然后将符号表添加到
    libgraphics.a
在linux中,这具有与以下相同的净效果:

ar cr libgraphics.a *.o
ar qc libgraphics.a*.o本身创建了一个链接器 无法使用,因为它没有符号表

ld

你的例子是:

ar qc libgraphics.a *.o
ranlib libgraphics.a
ld -r -o libgraphics.a *.o
这实际上是非常不正统的。这说明了链接器的使用非常罕见,
ld
,通过将多个输入文件链接到 单个输出对象文件,其中符号解析已尽可能完成, 给定输入文件。选择权 指示链接器通过以下方式生成对象文件目标(而不是程序或DSO) 尽可能地链接输入,如果未定义符号引用,则不要使linkaqe失败 保留在输出文件中。这种用法称为部分链接

ld-r…
的输出文件是一个对象文件,而不是
ar
归档文件,并且 指定一个类似于
ar
归档文件的输出文件名并不能使其成为归档文件。 所以你的例子说明了一个骗局。这:

ld -r -o graphics.o *.o
这是真实的。我不清楚这种欺骗的目的是什么, 因为即使ELF对象文件被称为
libgraphics.a
,并通过该名称输入到链接, 或者通过
-lgraphics
,链接器将正确地将其标识为ELF对象文件,而不是
ar
存档,并将使用 它使用命令行中任何对象文件的方式:无条件链接它 输入到输出文件中,而输入真实存档的点是
gcc -o prog file.o ... -Ldir ... -lfoo ...
gcc -shared -o libbar.so file.o ... -Ldir ... -lfoo ...