gcc用法以及靜態(tài)/動態(tài)鏈接

安裝

yum install gcc gcc-c++

選項

-E:只進行預(yù)處理,不編譯
-S:只編譯,不匯編
-c:只編譯、匯編,不鏈接
-g:編譯器在編譯的時候產(chǎn)生調(diào)試信息。
-I:指定include包含文件的搜索目錄
-o:輸出成指定文件名,如果缺省則輸出位a.out
-L:搜索庫的路徑
-l:指定程序要鏈接的庫
-w:忽略所有警告
-shared:指定生成動態(tài)鏈接庫。
-static:指定生成靜態(tài)鏈接庫。
-fPIC:表示編譯為位置獨立的代碼,用于編譯共享庫。目標(biāo)文件需要創(chuàng)建成位置無關(guān)碼,概念上就是在可執(zhí)行程序裝載它們的時候,它們可以放在可執(zhí)行程序的內(nèi)存里的任何地方。

-l參數(shù)和-L參數(shù)

  • -l參數(shù)就是用來指定程序要鏈接的庫,-l參數(shù)緊接著就是庫名。那么庫名跟真正的庫文件名有什么關(guān)系呢?
    就拿數(shù)學(xué)庫來說,他的庫名是m,他的庫文件名是libm.so,很容易看出,把庫文件名的頭lib和尾.so去掉就是庫名了。好了現(xiàn)在我們知道怎么得到庫名,當(dāng)我們自已要用到一個第三方提供的庫名字libtest.so,那么我們只要把libtest.so拷貝到/usr/lib里,編譯時加上-ltest參數(shù),我們就能用上libtest.so庫了(當(dāng)然要用libtest.so庫里的函數(shù),我們還需要與libtest.so配套的頭文件)。
    放在/lib/usr/lib/usr/local/lib里的庫直接用-l參數(shù)就能鏈接了,但如果庫文件沒放在這三個目錄里,而是放在其他目錄里,這時我們只用-l參數(shù)的話,鏈接還是會出錯,出錯信息大概是:“/usr/bin/ld: cannot find -lxxx”,也就是鏈接程序ld在那3個目錄里找不到libxxx.so,這時另外一個參數(shù)-L就派上用場了。

  • -L 比如常用的X11的庫,它在/usr/X11R6/lib目錄下,我們編譯時就要用-L/usr/X11R6/lib -lX11參數(shù),-L參數(shù)跟著的是庫文件所在的目錄名。再比如我們把libtest.so放在/aaa/bbb/ccc目錄下,那鏈接參數(shù)就是-L/aaa/bbb/ccc -ltest。 gcc默認(rèn)會在程序當(dāng)前目錄、/lib、/usr/lib/usr/local/lib下找對應(yīng)的庫

-I參數(shù)

  • -include和-I參數(shù)

    在你是用#include '***.h'的時候,gcc/g++會先在當(dāng)前目錄查找你所制定的頭文件,如果沒有找到,他回到缺省的頭文件目錄找,如果使用-I制定了目錄,他回先在你所制定的目錄查找,然后再按常規(guī)的順序去找.對于#include,gcc/g++會到-I制定的目錄查找,查未找到,然后將到系統(tǒng)的缺省的頭文件目錄查找。
    #include有兩種方式

  • 使用<>包含的頭文件一般會先搜索-I選項后的路徑(即用gcc編譯時的-I選項),之后就是標(biāo)準(zhǔn)的系統(tǒng)頭文件路徑。

  • 而用""號包含的頭文件會首先搜索當(dāng)前的工作目錄,之后的搜索路徑才是和<>號包含的頭文件所搜索的路徑一樣的路徑。

Linux下的標(biāo)準(zhǔn)頭文件路徑為/usr/include/usr/local/include

2.png
1.png

.a 和.so

靜態(tài)函數(shù)庫

靜態(tài)函數(shù)庫,這類庫的名字一般是libxxx.a
利用靜態(tài)函數(shù)庫編譯成的文件比較大,因為整個函數(shù)庫的所有數(shù)據(jù)都會被整合進目標(biāo)代碼中。
優(yōu)點就顯而易見了,即編譯后的執(zhí)行程序不需要外部的函數(shù)庫支持,因為所有使用的函數(shù)都已經(jīng)被編譯進去了。當(dāng)然這也會成為缺點如果靜態(tài)函數(shù)庫改變了,那么你的程序必須重新編譯。

共享函數(shù)庫

這類庫的名字一般是libxxx.so
相對于靜態(tài)函數(shù)庫,共享函數(shù)庫在編譯的時候 并沒有被編譯進目標(biāo)代碼中。當(dāng)程序執(zhí)行到相關(guān)函數(shù)時才調(diào)用共享函數(shù)庫里相應(yīng)的函數(shù),因此共享函數(shù)庫所產(chǎn)生的可執(zhí)行文件比較小。
由于共享函數(shù)庫沒有被整合進你的程序,而是在程序運行時動態(tài)地申請并調(diào)用,所以程序的運行環(huán)境中必須提供相應(yīng)的庫.
共享函數(shù)庫的改變并不影響你的程序,所以共享函數(shù)庫的升級比較方便.

示例

先上頭文件hello.h

#ifndef HELLO_H
#define  HELLO_H
void show();
#endif

分別做兩個實現(xiàn),hello_static.cpp和hello_dynamic.cpp。代碼很簡單就是打印一句話做一個區(qū)分,方便我們后面測試鏈接的哪個庫。
hello_static.cpp

#include "hello.h"
#include <iostream>
using namespace std;
void show(){
  cout<<"hello static"<<endl;
}

hello_dynamic.cpp

#include "hello.h"
#include <iostream>
using namespace std;
void show(){
  cout<<"hello dynamic"<<endl;
}

測試主程序main.cpp

#include "hello.h"
int main(){
  show();
  return 0;
}

下面我們寫Makefile然后進行編譯:

all : hello_static.o libhello.a libhello.so  main_s main_d

hello_static.o : hello_static.cpp
    g++ -c hello_static.cpp
    
libhello.a : hello_static.o
    ar crs libhello.a hello_static.o

libhello.so : hello_dynamic.cpp
    g++ -o $@ $+  -fPIC -shared

main_s : main.cpp
    g++  -static -o $@ $+ -I. -lhello -L.

main_d : main.cpp
    g++ -o $@ $+ -I. -lhello -L.

.PHONY : clean
clean :
    -rm hello_static.o libhello.a libhello.so main_s main_d

在鏈接hello時,會以共享庫文件優(yōu)先. 如果同時存在靜態(tài)庫和共享庫,可以使用-static強制使用靜態(tài)庫。當(dāng)然也可以直接指定libhello.a。如:

g++ -o $@ $+ -I.  -L.  libhello.a

完成Makefile后,就可以進行編譯,執(zhí)行make命令,生成hello_static.olibhello.a、 libhello.so、main_smain_d等文件。而main_s是我們靜態(tài)鏈接生成的,main_d是動態(tài)鏈接。我們分別運行后:

[root@localhost gcc]# ./main_d 
hello dynamic
[root@localhost gcc]# ./main_s
hello static

與我們預(yù)期一致。

問題

靜態(tài)鏈接使用-static出現(xiàn)錯誤:
/usr/bin/ld: cannot find -lm
collect2: ld 返回 1
make: *** [main_s] 錯誤 1

安裝glibc-devel即可

找不到動態(tài)庫
./main_d: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory

這里是需要設(shè)置環(huán)境變量,可參考Linux環(huán)境變量介紹和區(qū)別。也就是我們需要將so文件設(shè)置到環(huán)境變量中。直接編輯.bashrc文件

vim ~/.bashrc

添加:

export LD_LIBRARY_PATH=/code/gcc

保存退出后,使其生效。

source ~/.bashrc
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容