當前位置:首頁 » 編程軟體 » 跨編譯器的靜態庫生成和使用

跨編譯器的靜態庫生成和使用

發布時間: 2022-06-10 13:38:31

㈠ 關於動態庫 靜態庫 區別與使用 路徑查找等

一、引言

我們通常把一些公用函數製作成函數庫,供其它程序使用。
函數庫分為靜態庫和動態庫兩種。

通常情況下,對函數庫的鏈接是放在編譯時期(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大小,運行的速度等綜合考慮。

㈡ 如何生成靜態庫和動態庫

靜態庫

靜態庫的後綴是.a,它的產生分兩步

Step 1.由源文件編譯生成一堆.o,每個.o里都包含這個編譯單元的符號表
Step 2.ar命令將很多.o轉換成.a,成為靜態庫
動態庫的後綴是.so,它由gcc加特定參數編譯產生。具體方法參見後文實例。123123

在 GNU/linux 系統中靜態鏈接文件實際上就是多個 .o 文件的壓縮包。假設我們有 cool.h cool.c 和 some.c 文件,要得到靜態鏈接庫 libcool.a。首先使用如下指令得到相應的 object 文件 cool.o 和 some.o:

gcc -c cool.c
gcc -c some.c1212

用這種方法生成的 object 文件稱為 PDC 即位置相關代碼(position-dependence code)。再使用如下指令可以得到靜態鏈接文件 libcool.a:

ar -r libcool.a cool.o some.o
ranlib libcool.a1212

靜態鏈接庫 libcool.a 遵從 GNU/Linux 規定的靜態鏈接庫命名規范,必須是」libyour_library_name.a」

動態庫

在 GNU/Linux 中動態鏈接文件,必需通過鏈接器 ld 生成。假設我們有 hot.c other.c 等文件要生成動態鏈接庫 libhot.so 。首先使用如下指令得到相應的 object 文件 hot.o 和 some.o

gcc -fPIC -c hot.c
gcc -fPIC -c other.c1212

參數 -fPIC 指定生成的 object 文件為位置無關代碼(position-independence code),只有 PIC 可以被用作生成動態鏈接庫。然後使用如下指令得到動態庫:

ld -Bshared -o libhot.so hot.o other.o11

或者可以使用編譯器的ld wrapper:

gcc -shared -o libhot.so hot.o other.o11

也可以使用編譯器直接生成動態庫:

gcc -fPIC -shared -o libhot.so hot.c other.c11

這里選項 -shared 指示目標文件的類型是動態鏈接庫,動態庫的命名規范是」libyour_library_name.so」

㈢ 靜態庫的調用使用//漏下什麼了

C語言中有一些函數不需要進行編譯,有一些函數也可以在多個文件中使用。一般來說,這些函數都會執行一些標准任務,如資料庫輸入/輸出操作或屏幕控制等。可以事先對這些函數進行編譯,然後將它們放置在一些特殊的目標代碼文件中,這些目標代碼文件就稱為庫。庫文件中的函數可以通過連接程序與應用程序進行連接。這樣就不必在每次開發程序時都對這些通用的函數進行編譯了。不同類型的應用程序將會使用不同的函數庫。例如:libdbm庫中組包含了對資料庫文件進行訪問的dbm函數,需要對資料庫進行操作的程序就會與該庫進行連接。數學應用程序將使用數學庫libm,X-Windows應用程序將使用Xlib庫,libX11。另外,所有的程序都將使用標準的C函數庫。libc,該庫中包含了諸好內存管理或輸入輸出操作的基本函數,這些庫都存放在/usr/lib這些系統公用的目錄中,系統中的任何用戶都可以利用這些庫。當然用戶也可以建立自己專用的庫函數,供自己或其它指定的人員使用。庫可以有三種使用的形式:靜態、共享和動態。靜態庫的代碼在編譯時就已連接到開發人員開發的應用程序中,而共享庫只是在程序開始運行時才載入,在編譯時,只是簡單地指定需要使用的庫函數。動態庫則是共享庫的另一種變化形式。動態庫也是在程序運行時載入,但與共享庫不同的是,使用的庫函數不是在程序運行開始,而是在程序中的語句需要使用該函數時才載入。動態庫可以在程序運行期間釋放動態庫所佔用的內存,騰出空間供其它程序使用。由於共享庫和動態庫並沒有在程序中包括庫函數的內容,只是包含了對庫函數的引用,因此代碼的規模比較小。已經開發的大多數庫都採取共享庫的方式。ELF格式的可執行文件使得共享庫能夠比較容易地實現,當然使用舊的a.out模式也可以實現庫的共享。Linux系統中目前可執行文件的標准格式為ELF格式。GNU庫的使用必須遵守LibraryGNUPublicLicense(LGPL許可協議)。該協議與GNU許可協議略有不同,開發人員可以免費使用GNU庫進行軟體開發,但必須保證向用戶提供所用的庫函數的源代碼。系統中可用的庫都存放在/usr/lib和/lib目錄中。庫文件名由前綴lib和庫名以及後綴組成。根據庫的類型不同,後綴名也不一樣。共享庫的後綴名由.so和版本號組成,靜態庫的後綴名為.a。採用舊的a.out格式的共享庫的後綴名為.sa。libname.so.major.minorlibname.a這里的name可以是任何字元串,用來唯一標識某個庫。該字元串可以是一個單字、幾個字元、甚至一個字母。數學共享庫的庫名為libm.so.5,這里的標識字元為m,版本號為5。libm.a則是靜態數學庫。X-Windows庫名為libX11.so.6,這里使用X11作為庫的標識,版本號為6。使用gcc編譯器就可以將庫與自己開發的程序連接起來,例如:libc.so.5中包含了標準的輸入輸出函數,當連接程序進行目標代碼連接時會自動搜索該程序並將其連接到生成的可執行文件中。標準的輸入輸出庫中包含了許多基本的輸入輸出函數,如printf函數等。也可以連接其它的一些系統函數庫,如數學庫等,但與libc.so.5不同,大部分其它的系統庫需要在命令行中顯式指定所用的庫名。在/usr/lib和/lib目錄中可以找到絕大多數的共享庫。連接時將首先搜索這兩個目錄。有一些庫也可能存放在特定的目錄中,在/etc/ld.conf配置文件中給出了這些目錄的列表。連接程序也會對列出的這些目錄進行搜索。在默認情況下,Linux將首先搜索指定庫的共享版本,如果找不到,才會去搜索靜態版本。在對共享庫進行更新或安裝新庫後,必須運行ldconfig命令更新/etc/ld.conf文件中相應的項(如果使用RPM進行安裝,一般會自動進行更新,不過也不能保證這一點)。在gcc編譯器中引用可搜索到的目錄中的庫文件時,需要使用-l選項和庫名。在gcc命令行上輸入-lm可以在程序中連接標准算術庫,-l將首先使用libname.so進行搜索,這里是libm.so。下面的例子將使用算術庫創建bookrecs程序,請注意這里的-lm選項。$gccmain.cio.c-obookrecs-lm系統中還有一些其它可用的庫,常用的是libncurses.a庫,包含了一些簡單的滑鼠移動常式。在命令行中使用-lncurses選項引用libncurses.so庫。下面的例子同時調用了數學和游標庫。$gccmian.cio.c-obookrecs-lm-lncurses在引用其它目錄中的庫時,需要使用-ldir選項指定該目錄。該選項指定了搜索庫函數時其它路徑。在下面的例子中,用戶在連接時使用了mydir目錄中的myio.so庫文件。$gccmain.c-obookrecs-lmydir-lmyio.a的是為了支持較老的a.out格式的可執行文件的.so的是支持elf格式的可執行文件的庫。靜態庫是指編譯連接時,把庫文件的代碼全部加入到可執行文件中,所以生成的文件較大,但運行時,就不再需要庫文件了。動態庫正好相反,在編譯連接時,沒有把庫文件的代碼加入到可執行文件中,所以生成的文件較小,但運行時,仍需要載入庫文件.a是靜態庫文件,可以用ar命令生成。.so是動態庫文件,編譯時加上指定的選項即可生成,具體選項看相應的系統文檔了。。。。IBMAIX下如下:$(CC)$(SHOPT)$(SHLIBS)a.ob.o-olib$@$(DBBUILDTAIL)假設你有test1.ctest2.ctest3.c,編寫成動態鏈接庫1.先編譯成test1.otest2.otest3.o2.gcc-shared-W1,-soname,libvTest.so.1-olibvTest.so.1.0*.o

㈣ 如何使用GCC生成動態庫和靜態庫

下面以工程libtest為例說明gcc創建和使用靜態庫、動態庫的過程,libtest目錄結構和內容如圖1所示,其中三個文件hello.h,hello.c和main.c的內容如下。

libtest/include/hello.h

#ifdef _HELLO_H_
#define _HELLO_H_
void hello();
#endif
libtest/lib/hello.c
#include "hello.h"
#include <stdio.h>
void hello()
{
printf("hello world!\n");
}
libtest/src/main.c
#include "hello.h"
int main()
{
hello();
}

靜態庫過程如下:
(1) 進入libtest/lib目錄,執行命令:
gcc -c -I../include hello.c
該命令生成目標文件hello.o,注意:參數-I添加頭文件搜索目錄,這里因為hello.c中有#include 「hello.h」,hello.h在libtest/include目錄中,這里需要指定該目錄通知gcc,否則出現錯誤提示「找不到頭文件hello.h」。
這一步將在libtest/lib目錄中生成一個hello.o文件。
(2) 在libtest/lib目錄,執行命令:
ar rc libhello.ahello.o
該命令將hello.o添加到靜態庫文件libhello.a,ar命令就是用來創建、修改庫的,也可以從庫中提出單個模塊,參數r表示在庫中插入或者替換模塊,c表示創建一個庫
這一步將在libtest/lib目錄中生成一個libhello.a文件。
(3) 進入libtest/src目錄,執行命令:
gcc main.c-I../include -L../lib -lhello -o main
該命令將編譯main.c並鏈接靜態庫文件libhello.a生成可執行文件main,注意:參數-L添加庫文件搜索目錄,因為libhello.a在libtest/lib目錄中,這里需要指定該目錄通知gcc,參數-l指定鏈接的庫文件名稱,名稱不用寫全名libhello.a,只用寫hello即可。
這一步將在libtest/src目錄中生成可執行文件main。

動態庫過程如下:
(1) 進入libtest/lib目錄,執行命令:
gcc hello.c-I../include -fPIC -shared -o libhello.so
這一步將在當前目錄生成動態庫文件libhello.so,參數-fPIC -shared固定格式,不用糾結他們什麼意思。
(2) 進入libtest/src目錄,執行命令:
gcc main.c-I../include -L../lib -lhello -o main
此時在當前目錄中已經生成了可執行文件main,執行./main時卻提示錯誤:
./main: error while loading shared libraries: libhello.so: cannotopen shared object file: No such file or directory
也就是找不到動態庫文件libhello.so,在網上找了答案說如果遇到這樣的問題需要設置環境變數LD_LIBRARY_PATH,如下:
export LD_LIBRARY_PATH=」../lib」
gcc main.c -I../include -L../lib -lhello -o main
然後再執行./main就沒有錯誤了。
【補充】
環境變數LD_LIBRARY_PATH指示動態連接器可以裝載動態庫的路徑,在鏈接動態庫文件前設置該變數為庫文件所在路徑,注意:用export LD_LIBRARY_PATH=」…」方式只是臨時生效的,如果要永久有效可以寫入~/.bashrc文件中,跟修改PATH類似,exportLD_LIBRARY_PATH=$LD_LIBRARY_PATH:」…」。
當然如果有root許可權的話,也可以修改/etc/ld.so.conf文件,將要添加的動態庫搜索路徑寫入該文件中,然後調用/sbin/ldconfig來達到同樣的目的。

㈤ 在Linux下如何使用GCC編譯程序、簡單生成 靜態庫及動態庫

一個程序調用了一個動態庫,但是兩者之間有函數重名,導致運行時動態庫中的Linux下動態庫文件的擴展名為這樣,線程函數庫被稱作libthread.so。靜態庫的

㈥ 如何編譯生成和調用靜態庫

如何編譯動態庫
gcc test1.c test2.c -shared -fPIC -o libtest.so
使用動態庫
gcc main.c -L. -ltest -o a.out
(
-L : 表示需要庫的路徑
-l:表示需要庫的名稱,如libtest.so,名稱則為test
)
(ps:執行a.out時有可能提示找不到libtest.so文件,這時需要把庫文件放入到/lib等目錄下,或者添加環境變數LD_LIBRARY_PATH,包含有庫文件的路徑即可)

如何編譯靜態庫
gcc -c test1.c test2.c
ar -r libtest.a test1.o test2.o
使用靜態庫
gcc main.c -static -L. -ltest -o a.out

-static:可強制編譯時使用靜態庫,如果不使用這個參數,而靜態庫與動態庫同名的話,會優先使用動態庫

㈦ 如何使用cmake生成基於靜態庫的動態鏈接庫

在工程搭建時,可能會有將靜態庫鏈接成動態庫的需求,如出於代碼保護的角度,某些模塊會發布.a擴展名的靜態庫,我們要將多個這樣的靜態庫鏈接成一個動態庫。但與直接link目標文件不同的是,ld以默認參數執行時,並把靜態庫中沒有用到的函數過濾掉,導致生成的so並未包含所要的函數,因此要加上--whole-archive參數,以保證所有的函數都包含在生成的so中。在使用cmake時,CMakeLists.txt的寫法如下:add_library(${MODULE_NAME}SHARED${CMAKE_SOURCE_DIR}/builttime.c#要生成一個so,至少要包含一個源文件,實在沒有可以把庫的編譯時間戳打到這兒。)target_link_libraries(${MODULE_NAME}${${MODULE_NAME}_EXTRA_LDFLAGS}"-Wl,--whole-archive"#告訴編譯器,從這里開始,所有的庫的內容都包含到so中${LOCAL_MODULES}#可以是以源代碼生成的靜態庫${PREBUILT_MODULES}#可以是預先生成的靜態庫"-Wl,--no-whole-archive"#告訴編譯器,從這里開始,以後的庫的內容不用都包含到so中)

㈧ 如何使用預編譯的靜態庫平台

tbb 2.2中提供了統一的頭文件:tbb.h,只要包含這個文件就可以使用所有tbb的庫了。為了使用起來方便,以及可以使用靜態庫,可以使用以下這些命令自己創建:

# 1. 先下載 tbb22_20090908oss_src.tgz, 去 http://www.threadingbuildingblocks.org

# 2. 解壓
tar -zxvf tbb22_20090908oss_src.tgz
cd tbb22_20090908oss

# 3. 編譯,沒必要直接make,很多東東其實不需要
make tbb && make tbbmalloc

# 4.編譯好的東東在build目錄下,不同的編譯器和操作系統,文件夾的名字不一樣
cd build/linux_ia32_gcc_cc4.1.0_libc2.4_kernel2.6.16.46_release

# 5.自己寫個命令把o文件打包成靜態庫
ar cqs libtbb.a *.o
cp libtbb.a ../../../
#再去預編譯頭文件
cd ../../include/tbb
g++ -o tbb.h.gch -x c++-header -c tbb.h -g -Wall -Werror -O2 -DNDEBUG
cp tbb.h.gch tbb.h ../../../
cd ../../../

熱點內容
內置存儲卡可以拆嗎 發布:2025-05-18 04:16:35 瀏覽:336
編譯原理課時設置 發布:2025-05-18 04:13:28 瀏覽:378
linux中進入ip地址伺服器 發布:2025-05-18 04:11:21 瀏覽:612
java用什麼軟體寫 發布:2025-05-18 03:56:19 瀏覽:32
linux配置vim編譯c 發布:2025-05-18 03:55:07 瀏覽:107
砸百鬼腳本 發布:2025-05-18 03:53:34 瀏覽:944
安卓手機如何拍視頻和蘋果一樣 發布:2025-05-18 03:40:47 瀏覽:741
為什麼安卓手機連不上蘋果7熱點 發布:2025-05-18 03:40:13 瀏覽:803
網卡訪問 發布:2025-05-18 03:35:04 瀏覽:511
接收和發送伺服器地址 發布:2025-05-18 03:33:48 瀏覽:372