Linux gcc/g++链接编译顺序详解
gcc/g++鏈接時對庫的順序要求
-LdirAdd directory dir to the list of directories to be searched for -l. -llibrary -l librarySearch the library named library when linking. (The secondalternative with the library as a separate argument is only for POSIXcompliance 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 inthe order they are specified. Thus, `foo.o -lz bar.o' searcheslibrary `z' after file foo.o but before bar.o. If bar.o refers tofunctions in `z', those functions may not be loaded.The linker searches a standard list of directories for thelibrary, which is actually a file named liblibrary.a. The linkerthen uses this file as if it had been specified precisely by name.The directories searched include several standard systemdirectories plus any that you specify with -L.Normally the files found this way are library files—archive fileswhose members are object files. The linker handles an archive fileby scanning through it for members which define symbols that haveso far been referenced but not defined. But if the file that isfound is an ordinary object file, it is linked in the usualfashion. The only difference between using an -l option andspecifying a file name is that -l surrounds library with `lib' and`.a' and searches several directories. 以上來源于gcc手冊對于library的查找
查找需要連接的符號名是從前向后找,根據-L指定的路徑順序查找;不同 目錄下的同名的庫,只取第一個(從左向右),后面同名庫被忽略;
對于符號的查找
從左向右查找,如果是主程序塊和靜態庫,不能定位地址就報錯: ‘undefined reference to: xxx’如果是鏈接成動態庫,則假設該符號在load 的
時候地址重定位。如果找不到對應的動態庫,則會在load的時候報:“undefined symbol: xxx“這樣的錯誤。
–as-needed對鏈接動態庫的影響
gcc-4.6默認開啟ld的–as-needed選項。
--as-needed --no-as-neededThis option affects ELF DT_NEEDED tags for dynamic libraries mentioned on the command line after the --as-neededoption. Normally the linker will add a DT_NEEDED tag for each dynamic library mentioned on the command line,regardless of whether the library is actually needed or not. --as-needed causes a DT_NEEDED tag to only be emitted fora library that satisfies an undefined symbol reference from a regular object file or, if the library is not found inthe DT_NEEDED lists of other libraries linked up to that point, an undefined symbol reference from another dynamiclibrary. --no-as-needed restores the default behaviour.--add-needed --no-add-neededThese two options have been deprecated because of the similarity of their names to the --as-needed and --no-as-neededoptions. They have been replaced by --copy-dt-needed-entries and --no-copy-dt-needed-entries.--copy-dt-needed-entries --no-copy-dt-needed-entriesThis option affects the treatment of dynamic libraries referred to by DT_NEEDED tags inside ELF dynamic librariesmentioned on the command line. Normally the linker won't add a DT_NEEDED tag to the output binary for each librarymentioned in a DT_NEEDED tag in an input dynamic library. With --copy-dt-needed-entries specified on the command linehowever any dynamic libraries that follow it will have their DT_NEEDED entries added. The default behaviour can berestored with --no-copy-dt-needed-entries.This option also has an effect on the resolution of symbols in dynamic libraries. With --copy-dt-needed-entriesdynamic libraries mentioned on the command line will be recursively searched, following their DT_NEEDED tags to otherlibraries, in order to resolve symbols required by the output binary. With the default setting however the searchingof dynamic libraries that follow it will stop with the dynamic library itself. No DT_NEEDED links will be traversed toresolve symbols.--以上來源于man手冊 --add-needed Set DT_NEEDED tags for DT_NEEDED entries in following dynamic libs --no-add-needed Do not set DT_NEEDED tags for DT_NEEDED entries in following dynamic libs --as-needed Only set DT_NEEDED for following dynamic libs if used --no-as-needed Always set DT_NEEDED for following dynamic libs
as-needed,意思大概是:只給用到的動態庫設置DT_NEEDED。
例如:
當鏈接生成libtest2.so的時候,如果libtest2.so里面用到了libtest1.so,但是沒有用到libxxx.so。
當開啟–as-needed選項的時候,就不會鏈接libxxx.so文件
–as-needed就是忽略鏈接時沒有用到的動態庫,只將用到的動態庫set NEEDED。
?
常見錯誤
1.鏈接主程序模塊或者是靜態庫的時的‘undefined reference to: xxx’
g++ -Wl,--as-needed -ltest1 -lc -lm -ldl -lpthread -L/home/ocaml/lib/ -lrt -o app main.o假設main.o依賴libtest1.so中的東西。因為gcc對庫的順序要求(gcc編譯時,由左向右)和–as-needed選項的開啟(因為libtest1.so在main.o的左邊,
所以gcc認為沒有使用到它,–as-needed將其忽略),ld忽略libtest1.so,定位main.o的符號的時候當然會找不到符號的定義。
所以會出現‘undefined reference to’這個錯誤!
正確寫法是:是:
g++ -Wl,--as-needed main.o -ltest1 -lc -lm -ldl -lpthread -L/home/ocaml/lib/ -lrt -o app?
2.編譯動態庫(shared library)的時候會導致一個比較隱晦的錯誤
編譯出來的動態庫的時候沒有問題,但是加載的時候有“undefined symbol: xxx”這樣的錯誤。假如像這也鏈接PyGalaxy.so
g++ -shared -Wl,--as-needed -lGalaxyParser -lc -lm -ldl -lpthread -L/home/ocaml/lib/ -lrt -o PyGalaxy.so PyGalaxy.oload PyGalaxy.so的時候會有上面的運行時錯誤!
簡單分析原因:因為libGalaxyParser.so在mutex.o的左邊,所以gcc認為沒 有用到它,–as-needed將其忽略。但是前面說的動態庫符號解析的特點導 致ld認為某些符號是加載的時候才去地址重定位的。但是 libGalaxyParser.so已經被忽略了。所以就算你寫上了依賴的庫,load的時 候也會找不到符號。但是為什么沒有-Wl–as-needed的時候是正確的呢?沒 有的話,ld會set NEEDED libGalaxyParser.so(用前面提到的查看動態庫 依賴關系的辦法可以驗證)。load的時候還是可以找到符號的,所以正確。
正確的鏈接方式是:
g++ -shared -Wl,--as-needed PyGalaxy.o -lGalaxyParser -lc -lm -ldl -lpthread -L/home/ocaml/lib/ -lrt -o PyGalaxy.so?
解決方案
在項目開發過層中盡量讓lib是垂直關系,避免循環依賴;越是底層的庫,越是往后面寫!
例如:
g++ ... obj($?) -l(上層邏輯lib) -l(中間封裝lib) -l(基礎lib) -l(系統lib) -o $@
這樣寫可以避免很多問題,這個是在搭建項目的構建環境的過程中需要考慮清楚地,在編譯和鏈接上浪費太多的生命不值得!
?
轉載于:https://www.cnblogs.com/zhanggaofeng/p/9255668.html
總結
以上是生活随笔為你收集整理的Linux gcc/g++链接编译顺序详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: eclipse对maven项目进行打wa
- 下一篇: 发票二维码扫描增强_03_图像预处理_0