linux之動(dòng)態(tài)庫和靜態(tài)庫編譯

Linux 中 動(dòng)態(tài)庫和靜態(tài)庫編譯和使用

為了更好的表述,這里寫了一個(gè)簡單的示例代碼 示例代碼 源代碼鏈接

代碼目錄結(jié)構(gòu)為:

.
├── hello          # 寫的一個(gè)hello示例庫
│   ├── hello.c
│   ├── include
│   │   └── hello.h
│   └── makefile
├── main.c         # 使用main函數(shù)去使用上面的庫
└── makefile

其中 hello.c內(nèi)容:

#include "include/hello.h"
void say_hello(char * name){
    printf("Hello, %s!\n", name);
}

其中 hello.h內(nèi)容:

#include<stdio.h>
void say_hello(char *name);

其中 main.h內(nèi)容:

#include<hello.h>
int main(){
    say_hello("Tom");
}

靜態(tài)庫編譯

切換目的到hello, 執(zhí)行一下命令可生成靜態(tài)庫

gcc -c -o hello.o hello.c -fpic # 編譯源文件hello.c 到目標(biāo)文件hello.o 
ar -rc  libhello.a hello.o  # ar 打包成一個(gè)靜態(tài)庫  

其中g(shù)cc的 -fpic 標(biāo)志含義是:生成使用相對(duì)地址無關(guān)的目標(biāo)代碼

注意: 靜態(tài)庫要以lib開頭,和.a結(jié)束 的方式命名

動(dòng)態(tài)庫的編譯

切換目的到hello, 執(zhí)行一下命令可生成動(dòng)態(tài)庫

gcc -c -o hello.o hello.c -fpic # 編譯源文件hello.c 到目標(biāo)文件hello.o 
gcc -shared -fpic -o libhello.so hello.o   # 生成動(dòng)態(tài)庫  

注意: 動(dòng)態(tài)庫要以lib開頭,和.so結(jié)束 的方式命名

如果你下載我提供的代碼,也可以直接使用make編譯

靜態(tài)庫的使用

切換目錄回到主目錄, 編譯main.c 并使用剛才編譯好的靜態(tài)庫

gcc -c -o main.o main.c -Ihello/include # 這里-Ihello/include 指定頭文件查找目錄為相對(duì)路徑hello/include 
                        # 這一定要指定頭文件查找目錄的,不然找不到main.c中使用的hello.h 
gcc -o main_a  main.o -Lhello -lhello -static 
# 這里 -Lhello 指定庫查找目錄為相對(duì)路徑hello
# -lhello 指定需要鏈接的庫為hello, 優(yōu)先鏈接libhello.so,如何找不到就鏈接libhello.a  
# -static 指定要鏈接靜態(tài)庫, 因?yàn)閔ello目錄中同時(shí)存在靜態(tài)庫和動(dòng)態(tài)庫,所以需要特別指定

最后生成 main_a , 可以直接通過 ./main_a 運(yùn)行

動(dòng)態(tài)庫的使用

切換目錄回到主目錄, 編譯main.c 并使用剛才編譯好的動(dòng)態(tài)庫

gcc -c -o main.o main.c -Ihello/include 
gcc -o main_so main.o  -Lhello -lhello -Wl,-rpath=./hello 

相比使用靜態(tài)庫,使用動(dòng)態(tài)庫需要指定的查找目錄 -Wl,-rpath=./hello
這里指定的目錄,是編譯完成的程序運(yùn)行的時(shí)候,去找依賴的動(dòng)態(tài)庫的路徑,如果你沒有指定,程序會(huì)
到系統(tǒng)默認(rèn)的路徑去找,如果沒有找到會(huì)報(bào)錯(cuò)(如下)

./main_so: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory

最后生成 main_so , 可以直接通過 ./main_so 運(yùn)行

動(dòng)態(tài)庫和靜態(tài)庫的區(qū)別

  1. 鏈接時(shí)不同
    靜態(tài)庫鏈接的時(shí)候,會(huì)把靜態(tài)庫中自己需要的代碼復(fù)制到自己的程序里面去。
    動(dòng)態(tài)庫鏈接的時(shí)候,只會(huì)檢查一下動(dòng)態(tài)庫只是否有自己程序需要的代碼,不會(huì)復(fù)制。
  2. 運(yùn)行時(shí)不同
    靜態(tài)庫因?yàn)殒溄訒r(shí)已經(jīng)把相關(guān)代碼復(fù)制進(jìn)程序了,所以運(yùn)行時(shí)不再依賴靜態(tài)庫。
    相反,使用動(dòng)態(tài)的程序在運(yùn)行時(shí)需要去找依賴的動(dòng)態(tài)庫,如果找不到會(huì)導(dǎo)致無法運(yùn)行。

靜態(tài)庫優(yōu)點(diǎn)

  • 運(yùn)行效率高些,無需依賴,簡單方便。

動(dòng)態(tài)庫的優(yōu)點(diǎn)

  • 節(jié)約內(nèi)存(主要體現(xiàn)在:因?yàn)閯?dòng)態(tài)庫可多個(gè)程序共享一份,當(dāng)多個(gè)程序都在使用這個(gè)動(dòng)態(tài)庫時(shí),內(nèi)存中只加載一份)
  • 節(jié)約時(shí)間(如果庫修改代碼,只需要重新編譯動(dòng)態(tài)庫,然后替換掉原先的庫。相反靜態(tài)庫需要編譯所有使用這個(gè)庫的程序)


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容