天天看點

linux c/c++ 動态庫和靜态庫的生成與使用

一.寫在前面          本文僅僅是總結了,靜态庫,動态庫的使用及基本編譯方法。至于庫本身的格式,記憶體位址等較底層問題,則等有時間放到作業系統一類的文章中研究。下面開始正題吧。

二.介紹

     從源代碼到可執行程式,通常要經過最重要的兩大步是:編譯,連結。編譯就是将源檔案生成中間檔案的過程,在linux下就是生成   .obj  檔案。連結就是用連結器将,這些個中間檔案有序地”糅合“在一起,構成一個可執行檔案。通常,一個.c檔案或者.cpp源檔案編譯後,就會對應生成一個.obj檔案。           那麼庫檔案是什麼東西呢?其實庫檔案就是将這些中間檔案.obj進行打包生成的檔案。那麼為什麼要将這些obj檔案打包成庫檔案呢?一個很重要的原因是,友善代碼複用。通常,我們都會有自己寫的一些公用的函數,一般是一些工具類的函數。然後再不同的項目中,經常會引用到這些公用的函數。顯而易見的做法是,将公用函數的.h檔案和.cpp檔案分别丢到某個項目的.h檔案目錄或.cpp檔案目錄中,編譯的時候也跟對待其他的源檔案一樣調用g++或者gcc進行編譯。如果是引用的第三方檔案不多還好,要是使用到了一些大型的第三方庫比如zlib,openssl等,那麼編譯這些庫都得花很長的時間。      那麼那些懶的程式員就想到了一個辦法,隻編譯一次,并将這些第三方庫編譯後生成的中間檔案全部保留下來,下次可以直接用了。那麼又來了個問題,加入某個第三方庫有許多源檔案,那豈不是要儲存好多.obj檔案??至少看起來,目錄都是亂糟糟的。是以,就想到了一個辦法将這些個.obj檔案打包起來放在一起,也就産生了所謂的庫檔案。      連結的時候又有問題了,如果這些第三方庫很大或者很多,直接将項目自己的中間檔案跟第三方庫檔案連結成可執行程式,最終這個程式一定非常臃腫,挺占空間。而且關鍵是,執行程式的時候,會将程式丢到記憶體裡去,那麼如果多個程式同時調用了這些第三方庫,那麼在記憶體裡,可能會存在兩份第三方庫的拷貝,貌似挺占記憶體。好的,聰明的程式員又想到好辦法了,生成動态庫,連結的時候不會将第三庫檔案”糅合“進可執行程式中,程式占的硬碟變小了。第二,當程式運作時,會将第三方庫丢進記憶體中,但是如果有多個程式也動态連結了這個第三方庫,記憶體中隻會有一份拷貝,也就是多個程式共享一個第三方庫,哈,記憶體占用解決了。

三.制作庫檔案      1,制作靜态庫檔案           使用linux下的ar指令可以打包中間檔案生成靜态庫檔案。通過man ar檢視ar的具體用法。一般可以使用 ar -crv 來産生靜态庫。比如:           g++ -g -c add.cpp  生成add.o           g++ -g -c sub.cpp  生成sub.o           ar -crv libmymth.a add.o sub.o生成歸檔檔案,也就是我們的靜态庫檔案。      2 ,制作動态庫檔案           g++ -fPIC -g -c add.cpp 生成add.o           g++ -fPIC -g -c sub.cpp 生成sub.o           -fPIC選項是為了生成與位址無關的編譯程式,這樣讓中間檔案能夠在多個程式中共享           g++ -shared -o libmymath.so add.o sub.o 生成相應的動态庫           或者直接合成一步:           g++ -shared -fPIC -o libmymath.so add.cpp sub.cpp

 四.使用庫檔案     動态庫或者靜态庫都可以在連結的時候,使用 -l 進行連結。但是要注意的是,-l 選項隻會在特定的目錄裡去尋找指定的庫檔案。這些特定的目錄指的是 /usr/lib,還有$LD_LIBRARY_PATH指定的路徑,還有ld.so.cache中的緩存内容。其中ld.so.cache是通過ldconfig指令來生成的,改指令會讀取 /etc/ld.so.conf檔案中的目錄清單,并寫入ld.so.cache檔案中。      是以正常的做法是,将生成的庫檔案直接丢到 /usr/lib下,或者放到$LD_LIBRARY_PATH的某一個目錄中,或者再/etc/ld.so.conf中配置庫檔案所在的目錄。這樣連結器就可以找到庫檔案。      特别的,對于動态庫。程式在運作的時候還會尋找動态庫檔案,如果連結的時候存在動态庫而運作的時候不存在動态庫,也會報錯。靜态庫就不一樣,隻要連結的時候存在庫檔案就行了,應為庫檔案和其他中間檔案一起打包進了最終的二進制檔案。      例子:           假設你把生成的庫檔案放到了上述連結器可以找到的地方,那麼你可以這樣連結你的程式:                g++ -o main main.o -lmymath                        另外g++提供了一個 -L選項用來指定庫檔案的目錄,例如假設你的庫檔案放在了 /root/data/lib下,那麼你可以這樣連結你的程式:                g++ -o main main.o -L/root/data/lib -lmymath           這樣連結後生成的程式,如果是連結了靜态庫,就可以直接正常運作。但是如果是連結的動态庫,那麼在運作程式的時候,通常都會報錯顯示找不到動态庫。原因上面已經提過了,連結的時候指定了動态庫的目錄,但是運作的時候沒有指定動态庫的目錄,解決的辦法是,将動态庫丢到連結器搜尋的目錄下。

參考:     http://blog.jobbole.com/86852/

                                                                                                             by mzy

繼續閱讀