linux靜態鏈接庫


庫是寫好的現有的,成熟的,可以復用的代碼。現實中每個程序都要依賴很多基礎的底層庫,不可能每個人的代碼都從零開始,因此庫的存在意義非同尋常

本質上來說庫是一種可執行代碼的二進制形式,可以被操作系統載入內存執行。庫有兩種:靜態庫(.a、.lib)和動態庫(.so、.dll)

靜態庫

之所以稱為“靜態庫”,是因為在鏈接階段,會將匯編生成的目標文件.o與引用到的庫一起鏈接打包到可執行文件中。因此對應的鏈接方式稱為靜態鏈接。

靜態庫與匯編生成的目標文件一起鏈接為可執行文件,那么靜態庫必定跟.o文件格式相似。其實一個靜態庫可以簡單看成是一組目標文件(.o/.obj文件)的集合,即很多目標文件經過壓縮打包后形成的一個文件。

特點

  • 可以實現共享代碼
  • 不能再包含其他靜態鏈接庫
  • 本身包含了代碼,地址符號表等,靜態鏈接庫的使用中,連接器從靜態鏈接庫獲取所有被引用的函數,並將庫同代碼一起放到可執行文件中
  • 代碼裝載速度快,執行速度略比動態鏈接庫快
  • 只需保證在開發者的計算機中有正確的 .a 文件,在以二進制形式發布程序時不需考慮在用戶的計算機上 .a 文件是否存在及版本問題
  • 使用靜態鏈接生成的可執行文件體積較大,包含相同的公共代碼,造成浪費;

創建

  1. 編寫源文件,通過 gcc -c xxx.c 生成目標文件
  2. 使用 ar 命令歸檔目標文件,生成靜態庫
  3. 配合靜態庫,寫一個使用靜態庫中的函數的頭文件
  4. 鏈接靜態庫,生成可執行文件

例子

源文件

add.c 文件:

int add(int a, int b) { return a + b; }

subtract.c 文件:

int subtract(int a, int b) { return a - b; }

編譯兩個文件,生成目標文件 add.o subtract.o

gcc -c add.c subtract.c

歸檔目標文件,生成靜態鏈接庫 libmath.a

使用 ar 命令將目標文件壓縮到一起,並且對其進行編號和索引,以便於查找和檢索

ar rcv libmath.a add.o subtract.o

有關 ar 命令的使用,makepage 有詳細的說明,常用的選項是:

c -- 如果庫文件不存在,生成新的庫文件,並不打印警告 r -- 代替庫中已有的文件或者插入新的文件 v -- 輸出詳細信息
d -- 刪除庫中的某個目標文件
t -- 列出歸檔文件中包含的目標文件

我們生成的庫文件名字必須形如 libxxx.a,這樣我們在鏈接庫的時候,就可以使用 -lxxx。

當我們鏈接時,指定 -lxxx,鏈接器就會在指定的目錄查找 libxxx.a 或 libxxx.so 文件

編寫頭文件 mymath.h

#ifndef _MYMATH_H_ #define _MYMATH_H_

int add(int, int); int subtract(int, int); #endif

使用靜態庫

編寫文件 main.c

#include <stdio.h> #include "mymath.h"


int main() { printf("%d, %d\n", add(2, 3), subtract(9, 8)); return 0; }

編譯鏈接

gcc main.c -L. -lmath

這里,-L 指定搜索鏈接庫的包含當前目錄

使用Makefile

.PHONY: all all: build target build: libmath.a libmath.a: add.o subtract.o ar rc $@ add.o subtract.o add.o: add.c gcc -c $< subtract.o: subtract.c gcc -c $< target: a.out a.out: main.c gcc main.c -L. -lmath .PHONY: clean clean: rm *.o libmath.a a.out

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM