博客專欄

EEPW首頁 > 博客 > ranlib的作用

ranlib的作用

發(fā)布人:電子禪石 時(shí)間:2021-05-27 來源:工程師 發(fā)布文章

更新靜態(tài)庫的符號(hào)索引表 

本小節(jié)的內(nèi)容相對(duì)簡單。前邊提到過,靜態(tài)庫文件需要使用“ar”來創(chuàng)建和維護(hù)。當(dāng)給靜態(tài)庫增建一個(gè)成員時(shí)(加入一個(gè).o文件到靜態(tài)庫中),“ar”可直接 將需要增加的.o文件簡單的追加到靜態(tài)庫的末尾。之后當(dāng)我們使用這個(gè)庫進(jìn)行連接生成可執(zhí)行文件時(shí),鏈接程序“l(fā)d”卻提示錯(cuò)誤,這可能是:主程序使用了之 前加入到庫中的.o文件中定義的一個(gè)函數(shù)或者全局變量,但連接程序無法找到這個(gè)函數(shù)或者變量。 

這個(gè)問題的原因是:之前我們將編譯完成的.o文件直接加入到了庫的末尾,卻并沒有更新庫的有效符號(hào)表。連接程序進(jìn)行連接時(shí),在靜態(tài)庫的符號(hào)索引表中無法定 位剛才加入的.o文件中定義的函數(shù)或者變量。這就需要在完成庫成員追加以后讓加入的所有.o文件中定義的函數(shù)(變量)有效,完成這個(gè)工作需要使用另外一個(gè) 工具“ranlib”來對(duì)靜態(tài)庫的符號(hào)索引表進(jìn)行更新。 

我們所使用到的靜態(tài)庫(文檔文件)中,存在這樣一個(gè)特殊的成員,它的名字是“__.SYMDEF”。它包含了靜態(tài)庫中所有成員所定義的有效符號(hào)(函數(shù)名、 變量名)。因此,當(dāng)為庫增加了一個(gè)成員時(shí),相應(yīng)的就需要更新成員“__.SYMDEF”,否則所增加的成員中定義的所有的符號(hào)將無法被連接程序定位。完成 更新的命令是: 
ranlib ARCHIVEFILE 
通常在Makefile中我們可以這樣來實(shí)現(xiàn): 
libfoo.a: libfoo.a(x.o) libfoo.a(y.o) ... 
ranlib libfoo.a 

它所實(shí)現(xiàn)的是在更新靜態(tài)庫成員“x.o”和“y.o”之后,對(duì)靜態(tài)庫的成員“__.SYMDEF”進(jìn)行更新(更新庫的符號(hào)索引表)。 

如果我們使用GNU ar工具來維護(hù)、管理靜態(tài)庫,我們就不需要考慮這一步。GNU ar本身已經(jīng)提供了在更新庫的同時(shí)更新符號(hào)索引表的功能(這是默認(rèn)行為,也可以通過命令行選項(xiàng)控制ar的具體行為??蓞⒖?GNU ar工具的man手冊(cè))。

 

GNU工具中ar是用來制作庫文件.a的,但同時(shí)還提供了一個(gè)ranlib,從手冊(cè)上看ranlib相當(dāng)于ar -s,為什么這樣呢?

這是由于最早在Unix系統(tǒng)上ar程序是單純用來打包多個(gè).o到.a(類似于tar做的事情),而不處理.o里的符號(hào)表。Linker程序則需 要.a文件提供一個(gè)完整的符號(hào)表,所以當(dāng)時(shí)就寫了單獨(dú)的ranlib程序用來產(chǎn)生linker所需要的符號(hào)信息。也就是說,產(chǎn)生一個(gè)對(duì)linker合 格的的.a文件需要做ar和ranlib兩步 。

很快,Unix廠商就發(fā)現(xiàn)ranlib做得事情完全可以合并到ar里面去,于是ar程序的升級(jí)版本就包括了ranlib的功能,但早期的很多項(xiàng)目的Makefile都已經(jīng)是按照兩步式的方法生成.a,所以為了保證這些早期文件的兼容性,ranlib被保留下來了。

如今,GNU/Linux系統(tǒng)上,ranlib依然存在,當(dāng)然大部分項(xiàng)目已經(jīng)不使用它了,因?yàn)閍r -s就做了ranlib的工作。
歷史通常是進(jìn)步和妥協(xié)的混合!


*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。



關(guān)鍵詞: ranlib

技術(shù)專區(qū)

關(guān)閉