什么是ranlib?

Yin*_*ing 18 linux macos

我已经使用 MacOSX 系统一段时间了,但直到最近才开始深入研究。我找到了一个指南,告诉我运行 'sudo ranlib /usr/local/lib/libjpeg.a'(安装 libjpeg)。我已经阅读了 ranlib 手册,并尝试在网上查找。我简直不明白。我需要查找哪些资源才能了解更多信息,或者有人可以对其使用进行简要说明?提前致谢!

小智 20

这个描述看起来很清楚:http : //sourceware.org/binutils/docs/binutils/ranlib.html

因此,如果您归档一组目标文件,请说:

$ ar r fruits.a apple.o orange.o pineapple.o
Run Code Online (Sandbox Code Playgroud)

然后运行

$ ranlib fruits.a
Run Code Online (Sandbox Code Playgroud)

创建fruits.a 内容的索引并将该索引存储在fruits.a 中。这对于链接和对象相互调用很有用。


Ign*_*ams 10

ranlib添加或更新目标文件静态库。链接器可以在链接时使用静态库,以提供代码运行所需的符号(而不是加载器在运行可执行文件时在动态库中查找它们)。

  • 但是`ar` 不也这样做吗?有什么不同? (5认同)

小智 10

ranlib 生成存档内容的索引并将其存储在存档中。该索引列出了由作为可重定位目标文件的归档成员定义的每个符号。具有此类索引的档案可加快与库的链接,并允许库中的例程相互调用,而无需考虑它们在档案中的位置。

来源:ranlib 手册页


Roy*_*oyi 5

ar

在 Linux 中,ar是 GNU 通用归档器。(ar在其他类 Unix 操作系统中有 的非 GNU 变体)。随着选项c

ar c... archive-name file...
Run Code Online (Sandbox Code Playgroud)

它创建一个包含file.... 该archive-name传统,但不一定具有扩展.a(用于存档)。每个都file...可以是任何类型的文件,不一定是目标文件。

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

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

一个显着的区别是静态库不是由链接器生成的,而是由ar. 所以没有链接发生,没有符号解析发生。归档的目标文件没有改变:它们只是放在一个包里。

当存档是在东西联动输入通过链接器生成-如程序或DSO -链接程序会在袋子,看看是否有任何目标文件,对于已计提未解决的符号引用提供的定义在联动中较早。如果找到,它会从包中提取这些目标文件并将它们链接到输出文件中,就好像它们在链接器命令行中单独命名并且根本没有提及存档一样。因此,归档在链接中的整个作用是作为目标文件的袋子,链接器可以从中选择它需要进行链接的文件。

默认情况下,GNUar将其输出档案准备用作链接器输入。它向存档中添加了一个虚假的“文件”,并带有一个神奇的虚假文件名,并且在这个虚假文件中写入了链接器能够从存档中的任何目标文件定义的全局符号中作为查找表读取的内容到存档中这些目标文件的名称和位置。这个查找表使链接器能够查看存档并识别定义了它手头的任何未解析符号引用的任何目标文件。

您可以使用q( = quick ) 选项禁止创建或更新此查找表- 实际上您已在您自己的ar示例中使用过该选项- 以及 (capital) S( = no symbol table ) 选项。如果您ar出于任何原因调用创建或更新没有(最新的)符号表的存档,那么您可以使用s选项为其提供一个。

运行库

ranlib根本不创建库。在 Linux 中,ranlib是一个遗留程序,ar如果它没有一个(最新的)符号表,它会添加到档案中。它的效果与ar s, 与 GNU完全相同ar。从历史上看,在ar配备自己生成符号表之前,ranlib是将神奇的虚假文件注入存档以使链接器能够从中挑选目标文件的混合器。在非 GNU 类 Unix 操作系统中,ranlib可能仍需要用于此目的。你的例子:

ar qc libgraphics.a *.o
ranlib libgraphics.a
Run Code Online (Sandbox Code Playgroud)

说:

  • libgraphics.a通过将*.o当前目录中的所有文件附加到存档中来创建,没有符号表。
  • 然后添加一个符号表到 libgraphics.a

在 linux 中,这具有与以下相同的净效果:

ar cr libgraphics.a *.o
Run Code Online (Sandbox Code Playgroud)

, 本身ar qc libgraphics.a *.o会创建链接器无法使用的存档,因为它没有符号表。

ld

你的例子:

ld -r -o libgraphics.a *.o
Run Code Online (Sandbox Code Playgroud)

其实是很不正统的。这说明相当罕见使用的连接器ld以产生合并通过连接多个输入文件到一个输出目标文件,其中符号解析已经完成目标文件,只要是可能给定的输入文件。所述-r(=重定位选项指示所述接头通过链接输入尽可能而不是如果未定义的符号引用保持在输出文件中失败的linkaqe以产生一个对象文件目标(而不是节目,或DSO)。这种用法称为部分链接

的输出文件ld -r ... 是一个目标文件,而不是一个 ar 档案,并且指定一个看起来ar档案的输出文件名并不能使它成为一个。所以你的例子说明了一种欺骗。这个:

ld -r -o graphics.o *.o
Run Code Online (Sandbox Code Playgroud)

会是真实的。我不清楚这种欺骗的目的是什么,因为即使调用了一个 ELF 目标文件libgraphics.a,并且通过该名称或通过-lgraphics将其输入到链接中,链接器也会正确地将其识别为 ELF 目标文件, 不是ar档案,并将像在命令行中使用任何目标文件一样使用它:它无条件地将它链接到输出文件中,而输入真正档案的要点是仅在引用档案成员的情况下才链接档案成员。也许你只是在这里有一个不明智的链接的例子。

包起来...

我们实际上只看到了一种生成传统上称为库的东西的方法,那就是生成所谓的静态库,通过归档一些目标文件并将符号表放入归档中。

我们完全没有看到如何生成另一种最重要的东西,通常称为,即动态共享对象/共享库/动态库。

与程序一样,DSO 由链接器生成。程序和 DSO 是 ELF 二进制文件的变体,OS 加载程序可以理解它们并可以使用它们来组装正在运行的进程。通常我们通过一个GCC前端的一个(调用链接gccg++gfortran,等):

链接程序:

gcc -o prog file.o ... -Ldir ... -lfoo ...
Run Code Online (Sandbox Code Playgroud)

链接 DSO:

gcc -shared -o libbar.so file.o ... -Ldir ... -lfoo ...
Run Code Online (Sandbox Code Playgroud)

-lfoo当您链接其他程序或 DSO 时,共享库和静态库都可以通过统一协议提供给链接器。该选项指示链接器扫描其指定或默认搜索目录以查找 libfoo.solibfoo.a。默认情况下,一旦找到其中之一,它就会将该文件输入到链接中,如果在同一搜索目录中找到这两个文件,它会更喜欢libfoo.so. 如果libfoo.so, 被选中,则链接器将该 DSO 添加到您正在制作的任何程序或 DSO 的运行时依赖项列表中。如果libfoo.a被选中,则链接器使用存档作为目标文件的选择以链接到输出文件,如果需要,就在那里。没有运行时依赖 libfoo.a本身是可能的;它不能映射到进程中;它对操作系统加载程序没有任何意义。

复制自/sf/answers/3354740511/