$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名字的檔案,而不是庫的檔案名稱,換句話說,soname是庫的區分標誌。
這樣做的目的主要是允許系統中多個版本的庫檔案共存,習慣上在命名庫檔案的時候通常與soname相同
libxxxx.so.major.minor
其中,xxxx是庫的名字,major是主要版本號,minor 是次版本號碼
至於標頭檔的使用 只要.c檔案和.h檔案在同一目錄下就可以直接用#include "your.h" 如果在.c檔案的上層目錄 那隻要做如下修改#include "../your.h" 就能夠讓你的編譯器找到了!
這個也不錯:http://colintrace.blogdriver.com/colintrace/1049722.html
這個也相當詳細:http://blog.csdn.net/lijing3933/archive/2008/01/28/2070381.aspx
一、建立共用庫
1 單獨編譯SList.cpp,編譯時間需要傳入-fPIC選項,告訴編譯器產生位置無關代碼.
位置無關代碼可以被載入到地址空間的任意位置而不需要修改.
[root@LEE src]# ls
main.cpp SList.cpp SList.h
[root@LEE src]# g++ -fPIC -g -c SList.cpp
2 當連結到庫時,為連結器傳入-shared選項,把目標檔案SList.o連結為共用對象
libSList.so.1.0.1
每個共用庫都有一個特定的搜尋名(soname).搜尋名約定如下:
lib+庫名+.so+.版本號碼
在檔案系統中,搜尋名是一個指向實名的符號串連.每個共用庫也有一個特定的實名,約定如下:
搜尋名+.子版本號碼+.發布號
你可以使用一個特殊的編譯器選項-Wl,option,將option傳給ld,用逗號分隔多個option,
為了在所有的系統上得到最好結果,連結libSList到標準C++庫上
[root@LEE src]# g++ -g -shared -Wl,-soname,libSList.so.1 -o libSList.so.1.0.1 SList.o -lstdc++
[root@LEE src]# ls
libSList.so.1.0.1 main.cpp SList.cpp SList.h SList.o
libSList.so.1是搜尋名,libSList.so.1.0.1是實名,SList.o是目標檔案(也可以是多個目標檔案的列表)
,-lstdc++是庫需要訪問的庫(也可以是庫的列表-llibrary,關於此選項參考附錄.)
3 建立一個從soname連結到庫
[root@LEE src]# ln -fs libSList.so.1.0.1 libSList.so.1
[root@LEE src]# ln -fs libSList.so.1 libSList.so
4 使用-L使連結器在目前的目錄中尋找庫,並且使用-lSList告訴它要連結哪個庫
[root@LEE src]# g++ -g -c main.cpp -o main.o
[root@LEE src]# g++ -g -o main main.o -L. -lSList
[root@LEE src]# ls
libSList.so libSList.so.1.0.1 main.cpp SList.cpp SList.o
libSList.so.1 main main.o SList.h
5 運行命令
[root@LEE src]# LD_LIBRARY_PATH=$(pwd) ./main
4->17->19->10->23->21->11->20
LD_LIBRARY_PATH
提供用來搜尋庫的目錄路徑,以冒號作為間隔.正常情況下它不應該被設定,因為系統檔案
/ect/ld.so.conf提供了預設的路徑.
二、使用連結庫
當運行一個程式時,動態裝載器通常在/ect/ld.so.conf.d目錄尋找程式所需要的庫.但是,如果
LD_LIBRARY_PATH 環境變數被設定,它首先掃描在LD_LIBRARY_PATH 中列出的目錄.對於上一節5,如果直接運行
命令 ./main,會出現找不到庫的現象.如:
[root@LEE src]# ./main
./main: error while loading shared libraries: libSList.so.1: cannot open shared object file: No such file or directory
上述問題的解決方案有兩種(我能想到的):
1 如果LD_LIBRARY_PATH 沒設定:
拷貝libSList.so到目錄 /usr/local/lib (同理也可以拷到/usr/lib下)
[root@LEE src]# cp libSList.so /usr/local/lib
[root@LEE src]# ldconfig /usr/local/lib
[root@LEE src]# ./main
4->17->19->10->23->21->11->20
2 如果LD_LIBRARY_PATH 設定:
編輯.bash_profile檔案
添加LD_LIBRARY_PATH:=$LD_LIBRARY_PATH:/path/to/libSList.so(不包括 libSList.so)
執行.bash_profile 檔案.
[root@LEE src]# . /root/.bash_profile
[root@LEE src]# ./main
4->17->19->10->23->21->11->20