Posted on 2008-11-09 12:18
小蘇 閱讀(11033)
評論(3) 編輯 收藏 引用
使用gcc生成可執行文件時,大部分時候我們需要連接我們自己打包(AR)好的一些庫文件,對于中大型(50萬代碼行以上)項目上,你將面對數個項目組,最好的情況是每個項目組發布自己的打包.ar文件,這些.ar文件之間沒有任何依賴關系, 然后由持續集成(ci)小組對這些包進行連接,不幸的是,這幾乎是不可能的, 我們在連接時還是遇到了liba.ar和libb.ar相互依賴的情況。
因為gcc的庫是個有點怪怪的特性,在看-l幫助時可以看到:
-l library
Search the library named library when linking. (The second alter-
native with the library as a separate argument is only for POSIX
compliance and is not recommended.)
It makes a difference where in the command you write this option;
the linker searches and processes libraries and object files in the
order they are specified. Thus, foo.o -lz bar.o searches library z
after file foo.o but before bar.o. If bar.o refers to functions in
z, those functions may not be loaded.
出于知識產權保護的考慮,每一個項目組可能只允許看到自己的代碼和別的項目組的頭文件,這給CI小組帶來了很頭痛的事情,很多時候你不得不把庫順序來回調整。我也遇到了這樣讓人崩潰的情形,問題是對于liba.ar和libb.ar相互以來的情形,你可能最終采取丑陋的做法,將其中一個庫在前后放兩次:
gcc -o out.bin liba.ar libb.ar liba.ar -lrt
否則,您將不得不面對 "xx not referenced"之類的錯誤。
看看gcc的幫助,有下面的選項
-Xlinker option
Pass option as an option to the linker. You can use this to supply
system-specific linker options which GCC does not know how to rec-
ognize.
If you want to pass an option that takes an argument, you must use
-Xlinker twice, once for the option and once for the argument. For
example, to pass -assert definitions, you must write -Xlinker
-assert -Xlinker definitions. It does not work to write -Xlinker
"-assert definitions", because this passes the entire string as a
single argument, which is not what the linker expects.
也就是說,-Xlinker是將連接選項傳給連接器的,趕快看看ld的幫助有沒有解決庫順序的選項吧:
-( archives -)
--start-group archives --end-group
The archives should be a list of archive files. They may be either
explicit file names, or -l options.
The specified archives are searched repeatedly until no new unde-
fined references are created. Normally, an archive is searched
only once in the order that it is specified on the command line.
If a symbol in that archive is needed to resolve an undefined sym-
bol referred to by an object in an archive that appears later on
the command line, the linker would not be able to resolve that ref-
erence. By grouping the archives, they all be searched repeatedly
until all possible references are resolved.
Using this option has a significant performance cost. It is best
to use it only when there are unavoidable circular references
between two or more archives.
不錯,我們有個有點怪異的選項,-(和-),它能夠強制"The specified archives are searched repeatedly"
god,這就是我們要找的啦。
最終的做法:
gcc -o output.bin -Xlinker "-(" liba.ar libb.ar -Xlinker "-)" -lrt
這樣可以解決庫順序的問題了!問題是,如果你的庫相互間的依賴如果錯綜復雜的話,可能會增加連接的時間,不過,做架構設計的都應該能考慮到這些問題吧。