{
//http://www.360doc.com/content/14/0413/16/15099545_368549362.shtml
}
GCC/Clang生成和鏈接靜態庫/動態庫
{
1
2
3
4
5
|
//add.cpp
int
add(
int
a,
int
b)
{
return
a + b;
}
|
1
2
3
4
5
6
7
8
9
10
11
|
//main.cpp
#include <iostream>
int
add(
int
a,
int
b);
int
main(
int
argc,
const
char
*argv[])
{
std::cout << add(1, 2) << std::endl;
return
0;
}
|
筆者的開發平台: Mac OS X 10.9.2 / Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
生成靜態庫
靜態庫文件的命名規則是:lib****.a(將****替換成自定義名字),將 add.cpp 編譯成一個目標文件,然后打包成為一個靜態庫,具體操作如下:
1.先將 add.cpp 編譯成目標文件 add.o
clang++ -c add.cpp
2.然后使用 ar 命令將目標文件 add.o 打包成為靜態庫文件 libadd.a
ar -r libadd.a add.o
從上面這些操作中可以看出,生成靜態庫文件其實就是使用 ar 命令將目標文件打包一下,ar 是 archive 的縮寫,意思是歸檔,有關 ar 的部分參數解釋如下:
-r :添加或替換指定的文件到歸檔中;
ar -r libtest.a test.o
-v :顯示冗余的信息;
ar -rv libtest.a test.o
-t :按順序顯示歸檔中的文件名;
ar -t libtest.a
-d :從歸檔里刪除指定的文件;
ar -d libtest.a test.o
從 ar 命令的參數中可以得知,可以將多個目標文件打包到一個靜態庫中,並可以隨時的添加和刪除。
鏈接靜態庫
生成完靜態庫了,然后該如何使用這個生成的靜態庫文件呢?看下面的具體操作:
1.將 main.cpp 模塊編譯成為目標文件 main.o
clang++ -c main.cpp
2.將目標文件 main.o 和靜態庫文件 libadd.a 鏈接成為可執行文件 main
clang++ main.o -L. -ladd -o main
3.運行可執行文件 main
./main
運行結果:
3
鏈接靜態庫時,在 clang++ 鏈接命令后添加了兩個參數,下面具體解釋一下:
L. :將當前目錄添加至編譯器庫搜索目錄中,如果動態庫和靜態庫同時存在,會優先選擇動態庫;
-ladd :表示查找靜態庫名是:libadd.a 或 動態庫名是:libadd.so 的庫文件進行鏈接,優先選擇動態庫;
將這兩個參數泛化來講解:
Ldir :將 dir 添加編譯器的庫查找路徑中,編譯器默認僅僅搜索 /usr/lib 和 /usr/local/lib 這兩個文件夾;
-lname :查找靜態庫名是:libname.a 或 動態庫名是:libname.so 的庫文件進行鏈接,優先選擇動態庫;
生成動態庫
相比靜態庫,使用動態庫生成的可執行文件更小,看下面如何生成一個動態庫:
clang++ test.o -shared -fPIC -o libtest.so
執行完上面的操作后,會生成一個動態庫文件:libtest.so,動態庫文件的命名規則和靜態庫一樣,只是擴展名變成了 .so,下面具體解釋一下生成動態庫使用的參數的意義:
-shared :表明生成的文件是動態庫文件;
-fPIC :表明生成的動態庫是位置獨立的代碼(Position-independent Code),這個參數筆者也解釋不太清楚,可以自己 man 一下或者 Google 一下。
-o :指定生成的文件名;
鏈接動態庫
clang++ main.o -L. -ltest -o main
動態庫的鏈接和靜態庫一樣,見上文。
靜態庫和動態庫的區別:
1.使用靜態庫生成的可執行文件比動態庫大;
2.使用靜態庫生成的可執行文件執行時可以脫離靜態庫執行,而使用動態庫生成的可執行文件在執行時需要動態庫文件(所以它比較大)。
3.動態庫可以同時被多個程序共享,節省內存和外存。
.
.
思考:
有沒有想過靜態庫和動態庫有什么用?其實看看 /usr/lib 和 /usr/local/lib 中的文件就能明白些許。
}