Linux C/C++ 鏈接選項之靜態庫--whole-archive,--no-whole-archive和--start-group, --end-group


參照這兩篇博客:

http://stackoverflow.com/questions/805555/ld-linker-question-the-whole-archive-option

http://codemacro.com/2014/09/15/inside-static-library/

這四個都是鏈接器的選項,所以在編譯的時候要用-Wl,[options]來傳遞給鏈接器,不然編譯器會不認得這個選項。

--whole-archive選項解決的是編譯中常遇到的問題。在代碼中定義的符號(如函數名)還未使用到之前,鏈接器並不會把它加入到連接表中。如下面這個例子:

a.cpp:

void func(){printf("I am in a.cpp.\n");}

main.cpp:

extern void func();

int main(){func(); printf("I am in main.cpp"); return 0;}

首先編譯g++ -c a.cpp,再打包ar -r liba.a a.o。

如果這么鏈接g++ -L. -la main.cpp -o main,則鏈接器會報錯,稱func()未定義。其實改一下順序既可以解決g++  main.cpp -L. -la -o main。

或者使用g++ -Wl,--whole-archive -L. -la -Wl,--no-whole-archive main.cpp -o main,將liba.a中的所有.o中的符號都鏈接進來。

對於C++中使用的Register機制,即動態對象創建會遇到這樣的問題。在使用Caffe庫的時候也遇到了這樣的問題。

 

對於--start-group和--end-group, gcc liner man中如下描述:

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 undefined 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 symbol referred to by an object in an archive that appears later on the command line, the linker would not be able to resolve that reference. 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

這里有一個鏈接順序的問題,在command line上前面的庫會依賴之后的庫,如果碰到循環鏈接,-lliba -llibb -lliba,這樣就需要使用--start-group和--end-group反復在.a中進行搜索直到所有的未定義字符都被找到為止,而不是默認的只搜索一次。MKL庫有這樣的問題。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM