靜態庫編譯器
① linux動態庫和靜態庫的區別
動態鏈接庫和靜態鏈接庫是編程中常見的兩種鏈接方式。在程序源代碼編譯完成後,通過編譯器和鏈接器,程序會與這些庫進行鏈接。其中,動態鏈接庫與靜態鏈接庫的主要區別在於鏈接器在進行鏈接時,靜態庫會被直接編譯進程序,而動態鏈接庫則不會。我們通常將這些庫稱為程序的依賴。
程序運行需要這些依賴,而在程序進行靜態鏈接後,程序本身便已包含了這些依賴。然而,在動態鏈接後的程序中,這些依賴則不會包含在程序里,它們需要由執行者自行安裝進操作系統。特別是在Linux系統中,動態庫的後綴通常是.so,而靜態庫的後綴為.a。
靜態鏈接的一個顯著缺點是,靜態鏈接後的程序相較於動態鏈接所要佔用的空間更大。這是因為靜態鏈接會將鏈接庫編譯進程序里,所以靜態編譯後的程序會佔用更多的存儲空間。這種情況下,靜態庫的維護和更新變得相對困難,因為如果鏈接庫中存在bug等需要更新時,可能需要更新整個程序。
相比之下,動態庫在程序運行時會動態地載入這些庫,因此我們只需要更新動態庫而不需要更新所有依賴該庫的程序。此外,很多程序的開發都會使用到相同的鏈接庫,這些程序共享一個鏈接庫,從而大大減少了存儲資源的佔用。
綜上所述,動態鏈接庫和靜態鏈接庫各有優缺點。使用動態鏈接庫可以減少存儲資源的佔用,便於維護和更新。而靜態鏈接庫則適用於對程序大小有嚴格要求的情況,以及需要確保程序在沒有依賴庫的情況下也能運行的場景。
② linux 靜態庫和動態庫編譯的區別
Linux庫有動態與靜態兩種,動態通常用.so為後綴,靜態用.a為後綴。例如:libhello.so libhello.a
為了在同一系統中使用不同版本的庫,可以在庫文件名後加上版本號為後綴,例如: libhello.so.1.0,由於程序連接默認以.so為文件後綴名。所以為了使用這些庫,通常使用建立符號連接的方式。
ln -s libhello.so.1.0 libhello.so.1
ln -s libhello.so.1 libhello.so
動態庫和靜態庫的區別:
當要使用靜態的程序庫時,連接器會找出程序所需的函數,然後將它們拷貝到執行文件,由於這種拷貝是完整的,所以一旦連接成功,靜態程序庫也就不再需要了。然而,對動態庫而言,就不是這樣。動態庫會在執行程序內留下一個標記『指明當程序執行時,首先必須載入這個庫。由於動態庫節省空間,linux下進行連接的預設操作是首先連接動態庫,也就是說,如果同時存在靜態和動態庫,不特別指定的話,將與動態庫相連接。
兩種庫的編譯產生方法:
第一步要把源代碼編繹成目標代碼。以下面的代碼hello.c為例,生成hello庫:
/* hello.c */
#include
void sayhello()
{
printf("hello,world\n");
}
用gcc編繹該文件,在編繹時可以使用任何全法的編繹參數,例如-g加入調試代碼等:
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名字的文件,%B
③ C++通過什麼編譯器編譯成的靜態庫給ios調用
用的是gcc編譯器或者xcode編譯就可以。
在開發過程中,經常會碰到一些在不同工程中經常用到的部分,把這些部分抽取出來做成一個靜態庫往往是一個比較好的做法。xcode里就有製作靜態庫的模板,相關的製作步驟網上也有很多,但在實際的操作中,還是有不少細節方面需要注意。以下是我碰到的一些問題總結。
1.編譯release版本的庫
在「Manage Schemes」中,將「Build Configuration」的選項改為「Release」即可。如圖:
2.靜態庫中包含category
如果你在靜態庫工程中使用了category,那麼你可能會碰到鏈接問題,解決的辦法就是需要同時在生成靜態庫的工程和使用靜態庫的工程中使用「-all_load」編譯選項,即在對應target的"Build Settings"中的「Other Linker Flags」選項添加「-all_load」。注意:使用靜態庫的工程中是一定要加該編譯選項的!!至於生成靜態庫的工程中加不加沒有試過,不過建議還是加上該編譯選項。
3.靜態庫支持的SDK版本
為了使自己的靜態庫盡可能多的支持IOS的系統版本,應該在"IOS Deployment Target"這個選項中選擇自己所需的IOS版本。設置如下圖,這個是我的靜態庫工程中的配置,紅框框起來的是我修改過的選項。
4.自動拷貝頭文件
在工程對應的target的「Build Phases」下添加「Copy Headers」的選項。該選項默認是沒有的,添加方法是點擊下方的「Add Build Phase」按鈕後選擇後即可添加。該選項下有3個子選項,分別是Public,Private,Project。通過點擊下方的加號,可以將工程中的頭文件添加到「Project」中,在其中的對應頭文件點擊右鍵,選擇「Move to Public Group」,當頭文件移到「Pulic」後,編譯工程以後,在工程編譯後.a文件所在的路徑下,會同時出現一個"usr/local/include"的文件夾,其中的頭文件就是public group中的頭文件。這時只需將.a文件和這個路徑下的頭文件拷貝到所需工程文件即可。
轉載