gcc編譯常見問題,gcc編譯
inux C gcc -lm
使用math.h中聲明的庫函數還有一點特殊之處,gcc命令列必須加-lm選項,因為數學函數位於libm.so庫檔案中(這些庫檔案通常位於/lib目錄下),-lm選項告訴編譯器,我們程式中用到的數學函數要到這個庫檔案裡找。本書用到的大部分庫函數(例如printf)位於libc.so庫檔案中,使用libc.so中的庫函數在編譯時間不需要加-lc選項,當然加了也不算錯,因為這個選項是gcc的預設選項。
C標準主要由兩部分組成,一部分描述C的文法,另一部分描述C標準庫。C標準庫定義了一組標準標頭檔,每個標頭檔中包含一些相關的函數、變數、類型 聲明和宏定義。要在一個平台上支援C語言,不僅要實現C編譯器,還要實現C標準庫,這樣的實現才算符合C標準。不符合C標準的實現也是存在的,例如很多單 片機的C語言開發工具中只有C編譯器而沒有完整的C標準庫。
在Linux平台上最廣泛使用的C函數庫是glibc,其中包括C標準庫的實現。幾乎所有C程式都要調用glibc的庫函數,所以glibc是Linux平台C程式啟動並執行基礎。glibc提供一組標頭檔和一組庫檔案,最基本、最常用的C標準庫函數和系統函數在libc.so庫檔案中,幾乎所有C程式的運行都依賴於libc.so,有些做數學計算的C程式依賴於libm.so,以後我們還會看到多線程的C程式依賴於libpthread.so。以後我說libc時專指libc.so這個庫檔案,而說glibc時指的是glibc提供的所有庫檔案。
glibc並不是Linux平台唯一的基礎C函數庫,也有人在開發別的C函數庫,比如適用於嵌入式系統的uClibc
1. 為什麼會出現undefined reference to 'xxxxx'錯誤?首先這是連結錯誤,不是編譯錯誤,也就是說如果只有這個錯誤,說明你的程式源碼本身沒有問題,是你用編譯器編譯時間參數用得不對,你沒有指定連結程式要用到得庫,比如你的程式裡用到了一些數學函數,那麼你就要在編譯參數裡指定程式要連結數學庫,方法是在編譯命令列裡加入-lm。
2. -l參數和-L參數-l參數就是用來指定程式要連結的庫,-l參數緊接著就是庫名,那麼庫名跟真正的庫檔案名稱有什麼關係呢?就拿數學庫來說,他的庫名是m,他的庫檔案名稱是libm.so,很容易看出,把庫檔案名稱的頭lib和尾.so去掉就是庫名了。好了現在我們知道怎麼得到庫名了,比如我們自已要用到一個第三方提供的庫名字叫libtest.so,那麼我們只要把libtest.so拷貝到/usr/lib裡,編譯時間加上-ltest參數,我們就能用上libtest.so庫了(當然要用libtest.so庫裡的函數,我們還需要與libtest.so配套的標頭檔)。放在/lib和/usr/lib和/usr/local/lib裡的庫直接用-l參數就能連結了,但如果庫檔案沒放在這三個目錄裡,而是放在其他目錄裡,這時我們只用-l參數的話,連結還是會出錯,出錯資訊大概是:“/usr/bin/ld: cannot find -lxxx”,也就是連結程式ld在那3個目錄裡找不到libxxx.so,這時另外一個參數-L就派上用場了,比如常用的X11的庫,它放在/usr/X11R6/lib目錄下,我們編譯時間就要用-L/usr/X11R6/lib -lX11參數,-L參數跟著的是庫檔案所在的目錄名。再比如我們把libtest.so放在/aaa/bbb/ccc目錄下,那連結參數就是-L/aaa/bbb/ccc -ltest
3. -include和-I參數-include用來包含標頭檔,但一般情況下包含標頭檔都在源碼裡用#include xxxxxx實現,-include參數很少用。-I參數是用來指定標頭檔目錄,/usr/include目錄一般是不用指定的,gcc知道去那裡找,但是如果標頭檔不在/usr/include裡我們就要用-I參數指定了,比如標頭檔放在/myinclude目錄裡,那編譯命令列就要加上-I/myinclude參數了,如果不加你會得到一個"xxxx.h: No such file or directory"的錯誤。-I參數可以用相對路徑,比如標頭檔在目前的目錄,可以用-I.來指定。上面我們提到的--cflags參數就是用來產生-I參數的。
4. -O參數這是一個程式最佳化參數,一般用-O2就是,用來最佳化程式用的,比如gcc test.c -O2,最佳化得到的程式比沒最佳化的要小,執行速度可能也有所提高(我沒有測試過)。
5. -shared參數編譯動態庫時要用到,比如gcc -shared test.c -o libtest.so
6. 幾個相關的環境變數PKG_CONFIG_PATH:用來指定pkg-config用到的pc檔案的路徑,預設是/usr/lib/pkgconfig,pc檔案是文字檔,副檔名是.pc,裡面定義開發包的安裝路徑,Libs參數和Cflags參數等等。CC:用來指定c編譯器。CXX:用來指定cxx編譯器。LIBS:跟上面的--libs作用差不多。CFLAGS:跟上面的--cflags作用差不多。CC,CXX,LIBS,CFLAGS手動編譯時間一般用不上,在做configure時有時用到,一般情況下不用管。