編譯一個動態庫可以依賴靜態庫嗎
『壹』 動態庫能不能使用靜態庫
我們通常把一些公用函數製作成函數庫,供其它程序使用。
函數庫分為靜態庫和動態庫兩種。
靜態庫在程序編譯時會被連接到目標代碼中,程序運行時將不再需要該靜態庫。
動態庫在程序編譯時並不會被連接到目標代碼中,而是在程序運行是才被載入,因此在程序運行時還需要動態庫存在。
『貳』 c++靜態庫和動態庫
1、編譯出的靜態庫可以使用。視代碼不同有時你可能需要指定鏈接到哪個*.lib,有時不需要(頭文件里#pragma指定過了)。你需要在項目屬性里設置include和lib目錄,不想這樣做的話,就把它們丟到C庫一起。
2、動態庫一起的*.lib只起符號鏈接作用,和靜態庫一樣只需要*.lib即可編譯鏈接成功,但運行需要*.dll,它可以放在系統目錄或程序同目錄。頭文件沒#pragma的話自己#pragma或在鏈接選項里指定*.lib文件,這種方法可以像使用靜態庫一樣使用動態庫。
還有可以不依賴*.lib的符號鏈接直接使用*.dll的方法,譬如用WinAPI編程的話,使用LoadLibrary-GetProcAddress-FreeLibrary來載入*.dll中的一個函數。
3、沒看懂你的意思。
最後那段話:靜態庫需要*.lib即可編譯鏈接運行。動態庫需要*.dll才能運行,視使用方法的不同可能需要*.lib才能編譯鏈接可能不需要。
以上只對VS而言。MinGW不需要符號鏈接也可以像使用靜態庫那樣使用動態庫。
『叄』 linux編譯一個動態庫,將所依賴的其他庫的頭文件包含了進來,但沒指定其他靜態庫的路徑和名稱
編譯能過。因為頭文件的聲明,表示在某個地方這些變數被定義了。既然被定義了,當然編譯能過。但是如果沒有那些庫,鏈接是不能過的。
『肆』 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
『伍』 我編譯A靜態庫的時候依賴了B靜態庫,我編譯的程序依賴A靜態庫和B靜態庫,這樣B靜態庫是不是會有重復的部分
靜態庫在程序的鏈接階段被復制到了程序中。
你用依賴這個詞。
程序編譯一般需經預處理、編譯、匯編和鏈接幾個步驟。
在鏈接步驟中,靜態庫才會被復制。
因為靜態庫在程序的鏈接階段被復制到了程序中,和程序運行的時候沒有關系。
存在幾個鏈接?
那麼就幾分拷貝。
『陸』 什麼叫靜態庫和動態庫
兩者區別:
一,靜態庫的使用需要:
1
包含一個對應的頭文件告知編譯器lib文件裡面的具體內容
2
設置lib文件允許編譯器去查找已經編譯好的二進制代碼
二,動態庫的使用:
程序運行時需要載入動態庫,對動態庫有依賴性,需要手動加入動態庫
三,依賴性:
靜態鏈接表示靜態性,在編譯鏈接之後,
lib庫中需要的資源已經在可執行程序中了,
也就是靜態存在,沒有依賴性了
動態,就是實時性,在運行的時候載入需要的資源,那麼必須在運行的時候提供
需要的
動態庫,有依賴性,
運行時候沒有找到庫就不能運行了
四,區別:
簡單講,靜態庫就是直接將需要的代碼連接進可執行程序;動態庫就是在需要調用其中的函數時,根據函數映射表找到該函數然後調入堆棧執行。
做成靜態庫可執行文件本身比較大,但不必附帶動態庫
做成動態庫可執行文件本身比較小,但需要附帶動態庫
五:
首先糾正所謂「靜態連接就是把需要的庫函數放進你的exe之中」的說法。在真實世界中,有三個概念:use
static
libary,
static
linked
dll,
dynamic
linked
dll.
多數人混淆了static
libary
和
static
linked
dll的概念,當然他們有似是而非的「相似之處」,比如都用到.lib,下面具體說明。
使用靜態庫(use
static
libary)是把.lib和其他.obj一起build在目標文件中,目標文件可以是.exe,也可以是.dll或.oxc等。一般情況下,可以根本就沒有「對應的」.dll
文件,如c
run
time(crt)庫。一個例子就是,寫一個main(){},build出來並不是只有幾個位元組,當然有人會說那還有exe文件頭呢?是,即使加上文件頭的尺寸,build出的執行文件仍然「莫名的大」。實際上那多出來的部分就是crt靜態庫。姑且可以把靜態庫.lib理解成外部程序的obj文件比較合理,它包含了函數的實現。
『柒』 關於動態庫 靜態庫 區別與使用 路徑查找等
一、引言
我們通常把一些公用函數製作成函數庫,供其它程序使用。
函數庫分為靜態庫和動態庫兩種。
通常情況下,對函數庫的鏈接是放在編譯時期(compile time)完成的。所有相關的對象文件(object file)與牽涉到的函數庫(library)被鏈接合成一個可執行文件(executable file)。程序在運行時,與函數庫再無瓜葛,因為所有需要的函數已拷貝到相應目錄下下。所以這些函數庫被成為靜態庫(static libaray),通常文件名為「libxxx.a」的形式。
其實,我們也可以把對一些庫函數的鏈接載入推遲到程序運行的時期(runtime)。這就是動態鏈接庫(dynamic link library)技術。
二、兩者區別:
a,靜態庫的使用需要:
1 包含一個對應的頭文件告知編譯器lib文件裡面的具體內容
2 設置lib文件允許編譯器去查找已經編譯好的二進制代碼
b,動態庫的使用:
程序運行時需要載入動態庫,對動態庫有依賴性,需要手動加入動態庫
c,依賴性:
靜態鏈接表示靜態性,在編譯鏈接之後, lib庫中需要的資源已經在可執行程序中了, 也就是靜態存在,沒有依賴性了
動態,就是實時性,在運行的時候載入需要的資源,那麼必須在運行的時候提供 需要的 動態庫,有依賴性, 運行時候沒有找到庫就不能運行了
d,區別:
簡單講,靜態庫就是直接將需要的代碼連接進可執行程序;動態庫就是在需要調用其中的函數時,根據函數映射表找到該函數然後調入堆棧執行。
做成靜態庫可執行文件本身比較大,但不必附帶動態庫
做成動態庫可執行文件本身比較小,但需要附帶動態庫
鏈接靜態庫,編譯的可執行文件比較大,當然可以用strip命令精簡一下(如:strip libtest.a),但還是要比鏈接動態庫的可執行文件大。程序運行時間速度稍微快一點。
靜態庫是程序運行的時候已經調入內存,不管有沒有調用,都會在內存里頭。靜態庫在程序編譯時會被連接到目標代碼中,程序運行時將不再需要該靜態庫。
其在編譯程序時若鏈接,程序運行時會在系統指定的路徑下搜索,然後導入內存,程序一般執行時間稍微長一點,但編譯的可執行文件比較小;動態庫是程序運行的時候需要調用的時候才裝入內存,不需要的時候是不會裝入內存的。
動態庫在程序編譯時並不會被連接到目標代碼中,而是在程序運行是才被載入,因此在程序運行時還需要動態庫存在。
三、動態鏈接庫的特點與優勢
首先讓我們來看一下,把庫函數推遲到程序運行時期載入的好處:
1. 可以實現進程之間的資源共享。
什麼概念呢?就是說,某個程序的在運行中要調用某個動態鏈接庫函數的時候,操作系統首先會查看所有正在運行的程序,看在內存里是否已有此庫函數的拷貝了。如果有,則讓其共享那一個拷貝;只有沒有才鏈接載入。這樣的模式雖然會帶來一些「動態鏈接」額外的開銷,卻大大的節省了系統的內存資源。C的標准庫就是動態鏈接庫,也就是說系統中所有運行的程序共享著同一個C標准庫的代碼段。
2. 將一些程序升級變得簡單。用戶只需要升級動態鏈接庫,而無需重新編譯鏈接其他原有的代碼就可以完成整個程序的升級。Windows 就是一個很好的例子。
3. 甚至可以真正坐到鏈接載入完全由程序員在程序代碼中控制。
程序員在編寫程序的時候,可以明確的指明什麼時候或者什麼情況下,鏈接載入哪個動態鏈接庫函數。你可以有一個相當大的軟體,但每次運行的時候,由於不同的操作需求,只有一小部分程序被載入內存。所有的函數本著「有需求才調入」的原則,於是大大節省了系統資源。比如現在的軟體通常都能打開若干種不同類型的文件,這些讀寫操作通常都用動態鏈接庫來實現。在一次運行當中,一般只有一種類型的文件將會被打開。所以直到程序知道文件的類型以後再載入相應的讀寫函數,而不是一開始就將所有的讀寫函數都載入,然後才發覺在整個程序中根本沒有用到它們。
靜態庫:在編譯的時候載入生成目標文件,在運行時不用載入庫,在運行時對庫沒有依賴性。
動態庫:在目標文件運行時載入,手動載入,且對庫有依賴性。
具體在開發中用到哪種庫,我覺得還是根據實際的內存大小,ROM大小,運行的速度等綜合考慮。
『捌』 求助,依賴的動態庫包含靜態庫,編譯報錯說找
動態鏈接庫和靜態鏈接庫一般是編譯集成一系列的介面(函數)
在程序源代碼編譯完成後通過編譯器編譯並通過鏈接器與這些庫進行鏈接
動態鏈接庫與靜態鏈接庫的區別在於鏈接器在進行鏈接時靜態庫會被直接編譯進程序里
而動態鏈接庫並不會,我們這里將這些鏈接庫稱作依賴(動態庫和靜態庫)
程序的運行需要這些依賴,程序在靜態鏈接後該程序本身便已包含該依賴
而動態鏈接後的程序本身本不包含該依賴,這些依賴需要執行者自行安裝進操作系統(動態庫、運行時庫)
程序運行時會動態地載入這些庫
linux上動態庫一般的後綴後為.so
靜態庫一般的後綴為.a
由於靜態鏈接會直接將庫編譯進程序里所以靜態編譯後的程序相較於動態鏈接所要大
這就是因為靜態鏈接會將鏈接庫編譯進程序里的原因,所以佔用就要大了
出於這種原因,靜態庫不易於維護與更新,如果鏈接庫中有實現有bug等需要更新則需要更新整個程序,因為靜態庫被編譯進程序中了
但動態庫就沒有這種情況了,因為動態庫是程序運行時動態載入的,所以我們只需要更新動態庫而不需要更新所有依賴該庫的程序(軟體)
另一方面,很多程序的開發都會使用到相同的鏈接庫,也就是很多程序(軟體)會有相同的依賴
如果將這些依賴全部靜態編譯的話將會造成存儲資源佔用過多而造成資源浪費
而使用動態庫的方式這些程序(軟體)則可以共享一個鏈接庫,而不需要每個程序都帶一個鏈接庫,這樣就大大地減少了存儲資源佔用空間
『玖』 linux動態庫編譯
Linux動態庫的編譯與使用 轉載
http://hi..com/linuxlife/blog/item/0d3e302ae2384d3a5343c1b1.html
Linux下的動態庫以.so為後綴,我也是初次在Linux下使用動態庫,寫一點入門步驟,以便以後能方便使用。
第一步:編寫Linux程序庫
文件1.動態庫介面文件
//動態庫介面文件getmaxlen.h
#ifndef _GETMAXLEN_H_
#define _GETMAXLEN_H_
int getMaxLen(int *sel,int N);
#endif
文件2.動態庫程序實現文件
//動態庫程序實現文件getmaxlen.c
#include "getmaxlen.h"
int getMaxLen(int *sel,int N)
{
int n1=1,n2=1;
for(int i=1;i<N;i++)
{
if(sel[i]>sel[i-1])
{
n2 ++;
if(n2 > n1)
{
n1 = n2;
}
}
else
{
n2 = 1;
}
}
return n1;
}
第二步:編譯生成動態庫
gcc getmaxlen.c –fPIC –shared –o libtest.so
由以上命令生成動態庫libtest.so,為了不需要動態載入動態庫,在命令時需以lib開頭以.so為後綴。
–fPIC:表示編譯為位置獨立的代碼,不用此選項的話編譯後的代碼是位置相關的所以動態載入時是通過代碼拷貝的方式來滿足不同進程的需要,而不能達到真正代碼段共享的目的。
–shared:指明編譯成動態庫。
第三步:使用動態庫
1. 編譯時使用動態庫
文件1.動態庫使用文件test.c
//使用動態庫libtest.so,該文件名為test.c
#include "getmaxlen.h"
int main()
{
int Sel[] = {2,3,6,5,3,2,1,2,3,4,5,6,7,6,5};
int m;
m = getMaxLen(Sel,15);
printf("%d",m);
return 0;
}
編譯命令:
gcc test.c –L . –l test –o test
–L:指明動態庫所在的目錄
-l:指明動態庫的名稱,該名稱是處在頭lib和後綴.so中的名稱,如上動態庫libtest.so的l參數為-l test。
測試:
ldd test
ldd 測試可執行文件所使用的動態庫
2. 動態載入方式使用動態庫
文件內容:
//動態庫的動態載入使用
int main()
{
void *handle = NULL;
int (*getMaxLen)(int *sel,int N);
int sel[] = {1,2,5,4,5,8,6,5,9,5,4,5,4,1};
handle = dlopen("./libtest.so",RTLD_LAZY);
if(handle == NULL)
{
printf("dll loading error.\n");
return 0;
}
getMaxLen = (int(*)(int *,int))dlsym(handle,"getMaxLen");
if(dlerror()!=NULL)
{
printf("fun load error.\n");
return 0;
}
printf("%d\n",getMaxLen(sel,15));
}
編譯命令:
gcc –ldl test1.c –o test
gcc -o test test.c ./libmytools.so