2014/11/12

[Linux] Static Library和 Dynamic Library編譯

在Linux下編譯靜態連結函式庫(Static Library)和動態連結函式庫(Dynamic Library),兩者的差別是靜態函式庫是把整個Library包進去執行檔,因此可以保證到不同機器環境下執行,也不會因為少了這個函式庫導致無法執行檔案,但其缺點是檔案會比較大,假如大部分檔案都需要用到相同的函式庫,但全部都使用靜態連結的方式,那這樣非常的佔空間資源;而動態連結函式庫的好處,就是可以讓多個執行檔案,同時連結使用,可以減少佔空間,但是卻容易發生如果Library的版本不同,會導致連結執行錯誤。

兩者各有優缺點,要端看環境軟體和設定需求,來選擇編譯的方式。譬如檔案共用的多而且函式庫常見,那就要採用動態;少數檔案使用,或者函式庫較稀有,那就採用靜態設計。




底下以簡單好用的XML Parsing C Library這篇為例子,把ezXML分別編譯成動態和靜態函式庫,再比較兩者有何不同。

靜態函式庫(Static Library)編譯
首先編譯成Object檔案
gcc -Wall -O2 -c -o ezxml.o ezxml.c


再來使用ar指令,就可以把Object檔案編譯成靜態函式庫檔案(*.a)
ar rcs libezxml.a ezxml.o

然後在編譯使用到ezxml函式庫的程式時,要把靜態函式庫包進來,把ezxml_mycode.c檔案編譯成ezxml_mycode_static檔。
gcc ezxml_mycode.c libezxml.a -o ezxml_mycode_static -I.
要注意的是要告訴gcc,libezxml.a檔案在哪個路徑之下,因為放在同個資料夾下,所以-I帶此資料夾路徑。


執行結果


動態函式庫(Dynamic Library)編譯
一樣先把.c檔編譯成Object檔案
gcc -Wall -O2 -c -o ezxml.o ezxml.c

然後使用gcc把Object檔案編譯成動態函式庫(*.so)
gcc -s -shared -o libezxml.so ezxml.o


再來編譯使用到ezxml函式庫的程式ezxml_mycode.c,使用動態函式庫
gcc -o ezxml_mycode_dynamic ezxml_mycode.c -L. -lezxml
同樣要注意的是-l的參數會告訴gcc要去找名稱為libezxml.so的動態函式庫檔案,-L代表這個libezxml.so檔案目前是放在哪個位置,編譯成ezxml_mycode_dynamic

而在執行ezxml_dynamic檔案時,要記得先把libezxml.so檔案放到/lib的資料夾下,否則Linux在執行此檔案時,會找不到函式庫
cp libezxml.so /lib/


執行結果


兩個執行檔比較,可以看到ezxml_mycode_static的大小比ezxml_mycode_dynamic還要佔空間。

最後ezxml_mycode.c檔案內容參考
#include <stdio.h>
#include <stdlib.h>
#include "ezxml.h"


int main()
{
    ezxml_t f1 = ezxml_parse_file("test.xml"), team, driver;
const char *teamname;

    for (team = ezxml_child(f1, "team"); team; team = team->next) {
        teamname = ezxml_attr(team, "name");
        for (driver = ezxml_child(team, "driver"); driver; driver = driver->next) {
            printf("%s, %s: %s\n", ezxml_child(driver, "name")->txt, teamname,
            ezxml_child(driver, "points")->txt);
        }
    }
    ezxml_free(f1);
    return 0;
}


要編譯成動態還是靜態函式庫,沒有哪個比較好,要看需求來設計,才能夠符合空間及使用效率。

沒有留言:

張貼留言