gcc編譯的鏈接動態庫
❶ AIX下gcc編譯器怎麼使用動態連接庫
鏈接靜態庫其實從某種意義上來說也是一種粘貼復制,只不過它操作的對象是目標代碼而不是源碼而已。因為靜態庫被鏈接後庫就直接嵌入可執行文件中了,這樣就帶來了兩個問題。
首先就是系統空間被浪費了。這是顯而易見的,想像一下,如果多個程序鏈接了同一個庫,則每一個生成的可執行文件就都會有一個庫的副本,必然會浪費系統空間。
再者,人非聖賢,即使是精心調試的庫,也難免會有錯。一旦發現了庫中有bug,挽救起來就比較麻煩了。必須一一把鏈接該庫的程序找出來,然後重新編譯。
而動態庫的出現正彌補了靜態庫的以上弊端。因為動態庫是在程序運行時被鏈接的,所以磁碟上只須保留一份副本,因此節約了磁碟空間。如果發現了bug或要升級也很簡單,只要用新的庫把原來的替換掉就行了。
❷ 如何用gcc編譯生成動態鏈接庫*.so文件
生成動態鏈接庫的命令行為:
gcc -fPIC -shared -o libstr.so
當將main.c和動態鏈接庫進行連接生成可執行文件 的命令如下:
gcc main.c -L./ -lstr -o main或者gcc -o main main.c -L./ -lstr
測試是否動態鏈接,如果列出libstr.so, 那麼應該是連接正常了ldd main註:1)-L.:表示連接的庫在當前的目錄中。
❸ linux中編譯時怎麼連接動態庫
Linux系統中靜態庫是.a文件,編譯鏈接.a文件只需要加上.a文件的完整路徑就可以了,比如:
gcc -o hello hello.c /usr/lib/libm.a
Linux系統的動態庫是.so文件,編譯鏈接動態庫需要用-L參數指定動態庫的搜索路徑,還要用-l(這個是小寫的L)指定動態庫的名字,比如:
gcc -o hello hello.c -L/usr/openssl/lib -lcrypto
❹ 關於gcc編譯選項選取動態庫不同版本的問題
不同版本的動態庫是為了升級方便,舊的程序需要與舊的庫鏈接,新的程序與新的.
一般的做法是把libabc.so連接(symbolic link, ln -s libabc.so.N libabc.so)到最新的版本,這樣以後的新程序,在用gcc -labc的時候,都會鏈接到新的版本.舊的已經鏈接好的程序並不會產生不兼容的問題,因為舊程序在過去已經鏈接過了(動態庫鏈接的信息可以用ldd來查看: ldd /bin/ls).
symbolic link, ln是推薦的維護版本的辦法,不建議更改文件名.
如果你要有一個方便的辦法鏈接舊的版本, 建一個舊的版本的symbolic link就可以了,libabc11.so
ln -s libabc.so.11 libabc11.so
gcc -labc11...
❺ GCC中靜態連接和動態連接的區別
gcc中靜態連接和動態鏈接的方法:
1:GCC的靜態連接,直接把靜態庫的名字放在gcc後面
例如:gcc-otesttest.cstaticlib.a
2:GCC的動態連接,使用-l指定庫,-L指定庫的路徑,注意動態庫名必須是lib開頭,後綴名為.so
例如:gcc-otesttest.c-lpthread-L/usr/lib/
3:靜態庫也可以採用動態庫的連接方法,如果目錄中同時存在2種庫,gcc會優先選擇動態庫。如果一條gcc鏈接指令中既要鏈接動態庫又要鏈接靜態庫,可以用-Wl,-dn和-Wl,-dy參數選項來切換。
靜態連接和動態鏈接的主要區別:
1:靜態連接的時候,靜態庫的所有執行代碼被直接編譯到目標程序中。而動態連接的時候,僅僅把動態庫的函數和變數的符號名,地址偏移量等導入到目標程序。只有在目標程序運行的時候才把動態庫的執行代碼載入到內存中。
2:動態鏈接的項目容易管理,把不同模塊封裝成不同的動態庫,如果模塊功能修改,一般只需要重新生成該動態庫,不用重新編譯其他模塊和目標程序。而靜態鏈接的程序修改任何一個地方都必須重新編譯整個程序
3:靜態鏈接生成的目標程序體積比動態鏈接的大,但是載入速度更快,發布更容易,不需要檢查發布機器上是否有該動態庫或者動態庫版本是否符合要求。
4:如果多個程序使用一個動態庫,則該庫的執行代碼只會在內存中載入一次。而靜態庫是多次載入(事實上靜態庫連接完就沒用了,等於目標程序的一部分)。
5:從調試的角度來說,靜態連接的程序調試方法和獨立程序沒有任何區別,而動態庫的調試相對要復雜一些,因為庫裡面的符號地址都是相對地址。
❻ 如何使用GCC生成動態庫和靜態庫
下面以工程libtest為例說明gcc創建和使用靜態庫、動態庫的過程,libtest目錄結構和內容如圖1所示,其中三個文件hello.h,hello.c和main.c的內容如下。
libtest/include/hello.h
#ifdef _HELLO_H_
#define _HELLO_H_
void hello();
#endif
libtest/lib/hello.c
#include "hello.h"
#include <stdio.h>
void hello()
{
printf("hello world!\n");
}
libtest/src/main.c
#include "hello.h"
int main()
{
hello();
}
靜態庫過程如下:
(1) 進入libtest/lib目錄,執行命令:
gcc -c -I../include hello.c
該命令生成目標文件hello.o,注意:參數-I添加頭文件搜索目錄,這里因為hello.c中有#include 「hello.h」,hello.h在libtest/include目錄中,這里需要指定該目錄通知gcc,否則出現錯誤提示「找不到頭文件hello.h」。
這一步將在libtest/lib目錄中生成一個hello.o文件。
(2) 在libtest/lib目錄,執行命令:
ar rc libhello.ahello.o
該命令將hello.o添加到靜態庫文件libhello.a,ar命令就是用來創建、修改庫的,也可以從庫中提出單個模塊,參數r表示在庫中插入或者替換模塊,c表示創建一個庫
這一步將在libtest/lib目錄中生成一個libhello.a文件。
(3) 進入libtest/src目錄,執行命令:
gcc main.c-I../include -L../lib -lhello -o main
該命令將編譯main.c並鏈接靜態庫文件libhello.a生成可執行文件main,注意:參數-L添加庫文件搜索目錄,因為libhello.a在libtest/lib目錄中,這里需要指定該目錄通知gcc,參數-l指定鏈接的庫文件名稱,名稱不用寫全名libhello.a,只用寫hello即可。
這一步將在libtest/src目錄中生成可執行文件main。
動態庫過程如下:
(1) 進入libtest/lib目錄,執行命令:
gcc hello.c-I../include -fPIC -shared -o libhello.so
這一步將在當前目錄生成動態庫文件libhello.so,參數-fPIC -shared固定格式,不用糾結他們什麼意思。
(2) 進入libtest/src目錄,執行命令:
gcc main.c-I../include -L../lib -lhello -o main
此時在當前目錄中已經生成了可執行文件main,執行./main時卻提示錯誤:
./main: error while loading shared libraries: libhello.so: cannotopen shared object file: No such file or directory
也就是找不到動態庫文件libhello.so,在網上找了答案說如果遇到這樣的問題需要設置環境變數LD_LIBRARY_PATH,如下:
export LD_LIBRARY_PATH=」../lib」
gcc main.c -I../include -L../lib -lhello -o main
然後再執行./main就沒有錯誤了。
【補充】
環境變數LD_LIBRARY_PATH指示動態連接器可以裝載動態庫的路徑,在鏈接動態庫文件前設置該變數為庫文件所在路徑,注意:用export LD_LIBRARY_PATH=」…」方式只是臨時生效的,如果要永久有效可以寫入~/.bashrc文件中,跟修改PATH類似,exportLD_LIBRARY_PATH=$LD_LIBRARY_PATH:」…」。
當然如果有root許可權的話,也可以修改/etc/ld.so.conf文件,將要添加的動態庫搜索路徑寫入該文件中,然後調用/sbin/ldconfig來達到同樣的目的。
❼ 如何用gcc編譯動態庫
今天要用到靜態庫和動態庫,於是寫了幾個例子來鞏固一下基礎。
hello1.c ————————————————————
#include <stdio.h>
void print1(int i) { int j; for(j=0;j<i;j++) { printf("%d * %d = %d\n",j,j,j*j); } }
hello2.c _________________________________________________
#include <stdio.h>
void print2(char *arr) { char c; int i=0; while((c=arr[i++])!='\0') { printf("%d****%c\n",i,c); } }
hello.c ____________________________________________________
void print1(int); void print2(char *);
int main(int argc,char **argv) { int i=100; char *arr="THIS IS LAYMU'S HOME!"; print1(i); print2(arr);
return 0; }
可以看到hello.c要用到hello1.c中的print1函數和hello2.c中的print2函數。所以可以把這兩個函數組合為庫,以供更多的程序作為組件來調用。
方法一:將hello1.c和hello2.c編譯成靜態鏈接庫.a
[root@localhost main5]#gcc -c hello1.c hello2.c
//將hello1.c和hello2.c分別編譯為hello1.o和hello2.o,其中-c選項意為只編譯不鏈接。
[root@localhost main5]#ar -r libhello.a hello1.o hello2.o
//將hello1.o和hello2.o組合為libhello.a這個靜態鏈接庫
[root@localhost main5]#cp libhello.a /usr/lib
//將libhello.a拷貝到/usr/lib目錄下,作為一個系統共享的靜態鏈接庫
[root@localhost main5]#gcc -o hello hello.c -lhello
//將hello.c編譯為可執行程序hello,這個過程用到了-lhello選項,這個選項告訴gcc編譯器到/usr/lib目錄下去找libhello.a的靜態鏈接庫
以上的過程類似於windows下的lib靜態鏈接庫的編譯及調用過程。
方法二:將hello1.o和hello2.o組合成動態鏈接庫.so
[root@localhost main5]#gcc -c -fpic hello1.c hello2.c
//將hello1.c和hello2.c編譯成hello1.o和hello2.o,-c意為只編譯不鏈接,-fpic意為位置獨立代碼,指示編譯程序生成的代碼要適合共享庫的內容這樣的代碼能夠根據載入內存的位置計算內部地址。
[root@localhost main5]#gcc -shared hello1.o hello2.o -o hello.so
//將hello1.o和hello2.o組合為shared object,即動態鏈接庫
[root@localhost main5]#cp hello.so /usr/lib
//將hello.so拷貝到/usr/lib目錄下
[root@localhost main5]#gcc -o hello hello.c hello.so
//將hello.c編譯鏈接為hello的可執行程序,這個過程用到了動態鏈接庫hello.so
在這里要廢話幾句,其實一切的二進制信息都有其運作的機制,只要弄清楚了它的機制,並能夠實現之,則任何此時此刻無法想像之事都將成為現實。當然,這兩者之間的巨大鴻溝需要頂級的設計思想和頂級的代碼來跨越。
❽ acc和gcc編譯動態庫的區別
編譯動態庫時,acc使用-b開關,gcc使用-share開關,acc使用-AA開關編譯標准c++代碼,-mt加入多線程鏈接,gcc使用-pthread開關,acc使用+Markered開關編譯出cpp文件所需的頭文件,並以xxx.d文件形式存放,acc和gcc的共同的開關有-I加入頭文件目錄,-l開關加入依賴的動態庫鏈接,-L開關加入動態庫搜尋的路徑,-o開關輸出目標文件,-g開關加入調試信息,-w開關加入警告級別。在64位的機器上,acc使用+DD32開關編譯32位程序,gcc使用-milp32編譯32位程序,此外,在64位機器上,默認是編譯32位的程序。
❾ Linux 如何使用gcc生成靜態庫和動態庫
Linux庫有動態與靜態兩種,動態通常用.so為後綴,靜態用.a為後綴。例如:libhello.so libhello.a 為了在同一系統中使用不同版本的庫,可以在庫文件名後加上版本號為後綴,例如: libhello.so.1.0,由於程序連接默認以.so為文件後綴名。所以為了使用這些庫,通常使用建立符號連接的方式。 ln -s libhello.so.1.0 libhello.so.1 ln -s libhello.so.1 libhello.so 動態庫和靜態庫的區別: 當要使用靜態的程序庫時,連接器會找出程序所需的函數,然後將它們拷貝到執行文件,由於這種拷貝是完整的,所以一旦連接成功,靜態程序庫也就不再需要了。然而,對動態庫而言,就不是這樣。動態庫會在執行程序內留下一個標記『指明當程序執行時,首先必須載入這個庫。由於動態庫節省空間,linux下進行連接的預設操作是首先連接動態庫,也就是說,如果同時存在靜態和動態庫,不特別指定的話,將與動態庫相連接。 兩種庫的編譯產生方法: 第一步要把源代碼編繹成目標代碼。以下面的代碼hello.c為例,生成hello庫: /* hello.c */ #include void sayhello() { printf("hello,world\n"); } 用gcc編繹該文件,在編繹時可以使用任何全法的編繹參數,例如-g加入調試代碼等: gcc -c hello.c -o hello.o 1.連接成靜態庫 連接成靜態庫使用ar命令,其實ar是archive的意思 $ar cqs libhello.a hello.o 2.連接成動態庫 生成動態庫用gcc來完成,由於可能存在多個版本,因此通常指定版本號: $gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 hello.o 另外再建立兩個符號連接: $ln -s libhello.so.1.0 libhello.so.1 $ln -s libhello.so.1 libhello.so 這樣一個libhello的動態連接庫就生成了。最重要的是傳gcc -shared 參數使其生成是動態庫而不是普通執行程序。 -Wl 表示後面的參數也就是-soname,libhello.so.1直接傳給連接器ld進行處理。實際上,每一個庫都有一個soname,當連接器發現它正在查找的程序庫中有這樣一個名稱,連接器便會將soname嵌入連結中的二進制文件內,而不是它正在運行的實際文件名,在程序執行期間,程序會查找擁有 soname名字的文件,%B
❿ LLINUX GCC 編譯C使用自定義動態鏈接庫.so的問題
1. 可以參考如下關於庫文件的文章:http://numanal.com/?p=129
2. 在編譯文件時最好用-L指明自定義庫的存在目錄, 利用如下任一語句(.so文件與.c文件在同一目錄):
gcc test.c -o test2 -L./verify.so
gcc test.c -o test2 -L.
3. 你這里在的問題應該與編譯器的某些兼容性有關, 在實際編寫程序的時候最好按gcc的語法規范走, 避免不必要的錯誤.