1. 程式人生 > >靜態連結庫的編譯與使用 linux下的動態連結庫和靜態連結庫到底是個什麼鬼?(一)靜態連結庫的編譯與使用

靜態連結庫的編譯與使用 linux下的動態連結庫和靜態連結庫到底是個什麼鬼?(一)靜態連結庫的編譯與使用

linux下的動態連結庫和靜態連結庫到底是個什麼鬼?(一)靜態連結庫的編譯與使用

 

    知識不等於技術,這句話真的是越工作的時間長越深有體會,學習到的知識只有不斷的實踐,才成真正在自已的心裡紮下根,成為自身的一部分,所以無論如何,我希望我的部落格可以一直寫下去,慢慢的沉澱,終會有回報,無聊的時候想想,的確,寫程式碼也是一種自娛自樂!

    前幾天在做專案時出了一個問題,大體就是:makefile裡在編譯可執行檔案testappd的時候在有用-l去引用一個libtest.so,能編譯通過,但是在載入執行的時候系統提示找不到這個lib而導致程序啟動失敗。後來知道在產品版本編譯打包的時候這個lib並未被打包進去,這個問題後來解決了。但是出於好奇,我想搞清楚動態庫和靜態庫的概念,以及之前做過另一個專案時以dlopen方式去引用動態庫和makefile 去引用動態庫這幾種方式的不同。查找了網上的一些資料,看明白了,還需手動驗證一下才放心。

    首先說說靜態連結庫,說實話,有時候真心感覺計算機這些相關的各種高大上的詞彙都是紙老虎,看上去高深的不行,其實當你捅開那層紙,就那麼回事兒。

     所謂靜態連結庫,說白了就是在你把寫好的程式碼編譯的時候,就把你引用的庫一起給編進去了,從此後你編出來的執行程式跟外面都不再有任何關係,即使這個庫更新了,你也搭不上邊兒,其次,如果系統中許多類似的程式都需要用到這個庫,那麼各自在編譯的時候都需要把這個庫給編進去,浪費儲存空間(載入到記憶體裡應該也是浪費記憶體空間的)。linux系統中靜態庫的名字一般叫

xxx.a, 所以如果你看到一個以 .a結束的檔案那麼它多半就是一個靜態連結庫檔案。

    廢話少說,我們直接上乾貨,看看靜態庫是如何被編譯出來以及如何被使用的

    首先我們寫了一個sum.c,如下,很簡單,裡面只有一個Sum函式,把兩個數相加的和返回

1 int Sum(int Number1, int Number2)
2 {
3     return Number1 + Number2;
4 }

當然還要寫一個宣告它的sum.h

int Sum(int Number1, int Number2);

最後來一個呼叫這個sum函式的主函式, 列印返回的結果

複製程式碼
 1 #include<stdio.h>
 2 #include<sum.h>
 3 
 4 void main()
 5 {
 6     int Num1 = 1;
 7     int Num2 = 2;
 8     int iRet = 0;
 9 
10     iRet = Sum(Num1, Num2);
11     printf("Num1 + Num2 = %d.", iRet);
12     return;
13 }
複製程式碼

接下來我們編譯靜態庫,我的筆記本是mac os環境,開啟終端後用vim寫程式碼, gcc等相關工具直接就能用,版本沒注意,反正能用就行

複製程式碼
 1 192:zch kane$ ls
 2 main.c    sum.c    sum.h
 3 192:zch kane$ gcc -c sum.c
 4 192:zch kane$ ls
 5 main.c    sum.c    sum.h    sum.o
 6 192:zch kane$ 
 7 192:zch kane$ 
 8 192:zch kane$ ar cr libsum.a sum.o
 9 192:zch kane$ ls
10 libsum.a    main.c        sum.c        sum.h        sum.o
11 192:zch kane$ 
複製程式碼

如上,我們用ar這個工具來編譯靜態庫,cr標誌告訴ar將object檔案封裝

然後我們編譯主程式並執行:

複製程式碼
192:zch kane$ gcc -o sumappd main.c -L . -lsum
192:zch kane$ ls
libsum.a    main.o        sum.h        sumappd
main.c        sum.c        sum.o
192:zch kane$ ./sumappd 
Num1 + Num2 = 3
複製程式碼

“-L .”指明瞭當前lib所在的路徑是在本目錄,-l表示連結libsum.a這個lib庫,很好理解。

    知識不等於技術,這句話真的是越工作的時間長越深有體會,學習到的知識只有不斷的實踐,才成真正在自已的心裡紮下根,成為自身的一部分,所以無論如何,我希望我的部落格可以一直寫下去,慢慢的沉澱,終會有回報,無聊的時候想想,的確,寫程式碼也是一種自娛自樂!

    前幾天在做專案時出了一個問題,大體就是:makefile裡在編譯可執行檔案testappd的時候在有用-l去引用一個libtest.so,能編譯通過,但是在載入執行的時候系統提示找不到這個lib而導致程序啟動失敗。後來知道在產品版本編譯打包的時候這個lib並未被打包進去,這個問題後來解決了。但是出於好奇,我想搞清楚動態庫和靜態庫的概念,以及之前做過另一個專案時以dlopen方式去引用動態庫和makefile 去引用動態庫這幾種方式的不同。查找了網上的一些資料,看明白了,還需手動驗證一下才放心。

    首先說說靜態連結庫,說實話,有時候真心感覺計算機這些相關的各種高大上的詞彙都是紙老虎,看上去高深的不行,其實當你捅開那層紙,就那麼回事兒。

     所謂靜態連結庫,說白了就是在你把寫好的程式碼編譯的時候,就把你引用的庫一起給編進去了,從此後你編出來的執行程式跟外面都不再有任何關係,即使這個庫更新了,你也搭不上邊兒,其次,如果系統中許多類似的程式都需要用到這個庫,那麼各自在編譯的時候都需要把這個庫給編進去,浪費儲存空間(載入到記憶體裡應該也是浪費記憶體空間的)。linux系統中靜態庫的名字一般叫

xxx.a, 所以如果你看到一個以 .a結束的檔案那麼它多半就是一個靜態連結庫檔案。

    廢話少說,我們直接上乾貨,看看靜態庫是如何被編譯出來以及如何被使用的

    首先我們寫了一個sum.c,如下,很簡單,裡面只有一個Sum函式,把兩個數相加的和返回

1 int Sum(int Number1, int Number2)
2 {
3     return Number1 + Number2;
4 }

當然還要寫一個宣告它的sum.h

int Sum(int Number1, int Number2);

最後來一個呼叫這個sum函式的主函式, 列印返回的結果

複製程式碼
 1 #include<stdio.h>
 2 #include<sum.h>
 3 
 4 void main()
 5 {
 6     int Num1 = 1;
 7     int Num2 = 2;
 8     int iRet = 0;
 9 
10     iRet = Sum(Num1, Num2);
11     printf("Num1 + Num2 = %d.", iRet);
12     return;
13 }
複製程式碼

接下來我們編譯靜態庫,我的筆記本是mac os環境,開啟終端後用vim寫程式碼, gcc等相關工具直接就能用,版本沒注意,反正能用就行

複製程式碼
 1 192:zch kane$ ls
 2 main.c    sum.c    sum.h
 3 192:zch kane$ gcc -c sum.c
 4 192:zch kane$ ls
 5 main.c    sum.c    sum.h    sum.o
 6 192:zch kane$ 
 7 192:zch kane$ 
 8 192:zch kane$ ar cr libsum.a sum.o
 9 192:zch kane$ ls
10 libsum.a    main.c        sum.c        sum.h        sum.o
11 192:zch kane$ 
複製程式碼

如上,我們用ar這個工具來編譯靜態庫,cr標誌告訴ar將object檔案封裝

然後我們編譯主程式並執行:

複製程式碼
192:zch kane$ gcc -o sumappd main.c -L . -lsum
192:zch kane$ ls
libsum.a    main.o        sum.h        sumappd
main.c        sum.c        sum.o
192:zch kane$ ./sumappd 
Num1 + Num2 = 3
複製程式碼

“-L .”指明瞭當前lib所在的路徑是在本目錄,-l表示連結libsum.a這個lib庫,很好理解。