Linux下gcc經驗總結

1.gcc的常用參數

-I(大寫i)參數:添加頭文件目錄到索引目錄;例如:-I /usr/local/include/

-L參數:添加鏈接庫目錄到索引目錄;例如:-L /usr/local/lib/

-l(小寫L)參數:表示編譯時添加鏈接庫文件;例如:-ltest(參數與內容中間沒空格)代表着連接(庫名爲test)鏈接庫文件,庫名和實際文件名是不同的,庫名是文件名去掉開頭的lib和結尾的.a或.so後的名字,比如文件名爲libmy.a的鏈接庫的庫名是my

-static參數:GCC在默認情況下鏈接的是動態庫,-static選項,它會強制程序連接靜態庫。在支持動態鏈接的系統上,可以用來阻止連接動態庫。該選項在其它系統上無效。

-Wl,[option](小寫L)參數:告知gcc把-Wl,後面的參數傳遞給鏈接器ld去處理,其中option是要傳遞的參數表,option中多個參數由“,”分割,例如-Wl,-ldl,-lm

2.gcc的機制

參數解析順序:
對於C/C++編譯而言,讀取編譯選項是按照從左到右的順序執行的。那麼當編譯器遇到源文件的時候,就開始對源文件中用到的函數進行解析,找到相對應的 函數的函數體或者說是實現(Definition of Function)。這個過程是按照先遇到不能解析的函數(unresolved function),然後在源文件選項後面的一些選項中尋找可能的函數體的信息,是這樣的一個順序進行的。那麼對於包含函數體或者函數定義信息的編譯選項出現在源文件之前,那麼當編譯器在源文件中遇到不能解析的函數時,在源文件之後的選項中尋找相關的信息,那麼就出現了編譯錯誤,也就是無法找到相關的函數定義。
gcc鏈接庫目錄:
gcc把/usr/lib和/usr/lib64作爲默認的庫索引目錄,這是可以控制的,操作方式是這樣的
1.編輯/etc/ld.so.conf文件,加入庫文件所在目錄的路徑 
2.運行ldconfig,該命令會重建/etc/ld.so.cache文件

3.靜態庫問題

生成靜態庫:
靜態庫只是一堆object對象的集合,使用ar命令可以將.o文件打包成.a靜態庫。
假設gcc已經生成了a.o, b.o, c.o,使用下面的命令即可生成libmylib.a
#ar rcs libmylib.a a.o b.o c.o

4.動態庫問題

生成動態庫:
動態庫的生成由gcc直接生成。
假設a.c, b.c兩個文件,通過下面的命令可生成libmylib.so
#gcc -shared -fpic -o libmylib.so a.c b.c
“pic”命令行標記告訴GCC產生的代碼不要包含對函數和變量具體內存位置的引用,這是因爲現在還無法知道使用該消息代碼的應用程序會將它連接到哪一段內存地址空間。這樣編譯出的hello.o可以被用於建立共享鏈接庫。建立共享鏈接庫只需要用GCC的”-shared”標記即可。

5.鏈接庫問題

混合使用鏈接庫:
程序鏈接時候如果既需要鏈接靜態庫,又需要鏈接動態庫,可以使用Wl,[option]參數解決,此參數的option參數可以用來指定鏈接方式,-dn(-Bstatic)爲靜態鏈接,-dy(-Bdynamic)爲指定動態鏈接;例子如下:gcc -o test test.c -Wl,-dn -lmylib -Wl,-dy -lm 此處的mylib爲libmylib.a

6.使用問題

-static選項時候提示cannot find -lc:
原因分析:
gcc編譯時候調用了libc.so的鏈接庫文件,如果加入了-static參數,這時候gcc尋找的就是libc.a文件了,如果目錄中沒有,則出現cannot find -lc;正常情況下用yum安裝gcc是不安裝靜態庫的,所以有此錯誤。
解決方案:
安裝gcc對應的靜態庫,即:yum install glibc-static

在-static選項下使用-lm也就是math庫時候報錯:undefined reference to `sqrt`:
原因分析:
因爲編譯選項中有-static, 所以 -lm 指的是libm.a

這就涉及到符號空穴的實現問題。
Sam猜測:因爲編譯器從左向右讀取文件, 當讀到-lm時,因爲是靜態的,但此時還不知道該把哪個符號抽出來。所以只好往後繼續處理,等在main.o中發現
*UND* 00000000 sqrt, 也就是這個符號需要填入時,後面的文件卻沒有這個符號的實現。所以就報錯了。

但如果去掉 -static. 則編譯器編譯出的test中此符號還是未定義。但會在運行時從libm.so中將符號找到。
解決方案:
既然編譯器只會向後找符號,那很簡單,把-lm放後面就行了。
gcc -o test -static test.o -lm
編譯成功。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章