ranlib 的作用 | C & C++

本文转载自《ar、ranlib、nm命令详解》,原文有删改。

前边提到过,静态库文件需要使用 ar 来创建和维护。当给静态库增建一个成员时(加入一个 .o 文件到静态库中),ar 可直接将需要增加的 .o 文件简单的追加到静态库的末尾。之后当我们使用这个库进行链接生成可执行文件时,链接器 ld 却提示错误,这可能是:主程序使用了之前加入到库中的 .o 文件中定义的一个函数或者全局变量,但链接器无法找到这个函数或者变量。

这个问题的原因是:之前我们将编译完成的 .o 文件直接加入到了库的末尾,却并没有更新库的有效符号表。链接器进行连接时,在静态库的符号索引表中无法定位刚才加入的 .o 文件中定义的函数或者变量。这就需要在完成库成员追加以后让加入的所有 .o 文件中定义的函数(变量)有效,完成这个工作需要使用另外一个工具 ranlib 来对静态库的符号索引表进行更新。

我们所使用到的静态库中,存在这样一个特殊的成员 __.SYMDEF。它包含了静态库中所有成员所定义的有效符号(函数名、 变量名)。因此,当为库增加了一个成员时,相应的就需要更新成员 __.SYMDEF,否则所增加的成员中定义的所有的符号将无法被链接器定位。更新的命令是:ranlib xxx.a

其实 ar 程序已经提供了在更新库的同时更新符号索引表的功能,但是同时还保留了 ranlib 程序,ranlib 其实相当于 ar -s,为什么会这样呢?

这是由于最早在 Unix 系统上 ar 程序是单纯用来打包多个 .o 到 .a,而不处理 .o 里的符号表。链接器则需要 .a 文件提供一个完整的符号表,所以当时就提供单独的 ranlib 程序用来产生链接器所需要的符号信息。也就是说,产生一个对链接器合格的的 .a 文件需要做 ar 和 ranlib 两步 。很快,Unix 厂商就发现 ranlib 做得事情完全可以合并到 ar 里面去,于是 ar 程序的升级版本就包括了 ranlib 的功能,但早期的很多项目编译脚本是按照两步式的方法生成 .a,所以为了保证这些早期文件的兼容性,ranlib 被保留下来了。

作者

zhongtian

发布于

2023-03-05

更新于

2023-12-16

许可协议

评论