靜態庫(.a)將多個目標文件(.o)打包,鏈接時將代碼**直接複製**進可執行文件。本文演示從編寫源碼、編寫 Makefile、打包歸檔、編寫頭文件、編譯鏈接主程序、驗證符號表的完整流程。
project/ ├── add.c sub.c mul.c div.c # 四則運算實現 ├── ku.h # 統一頭文件 ├── Makefile # 自動化構建 ├── kumain.c # 主程序測試 └── libstatic.a # 生成的靜態庫
// add.c
float add(int a, int b) { return a + b; }
// sub.c
float sub(int a, int b) { return a - b; }
// mul.c
float mul(int a, int b) { return a * b; }
// div.c
float div(int a, int b) { return (float)a / b; }
ku.h#ifndef KU_H
#define KU_H
float add(int a, int b);
float sub(int a, int b);
float mul(int a, int b);
float div(int a, int b);
#endif
OBJS = add.o sub.o mul.o div.o
LIB = libstatic.a
$(LIB): $(OBJS)
ar -rc $(LIB) $(OBJS)
%.o: %.c
gcc -c $< -o $@
clean:
rm -f $(LIB) $(OBJS)
執行 make 即可生成 libstatic.a。
kumain.c#include <stdio.h>
#include "ku.h"
int main() {
int a = 10, b = 3;
printf("a=%d, b=%d\n", a, b);
printf("add=%.2f, sub=%.2f, mul=%.2f, div=%.2f\n",
add(a,b), sub(a,b), mul(a,b), div(a,b));
return 0;
}
gcc kumain.c -o kumain -L. -lstatic
# -L. 指定庫搜索路徑為當前目錄
# -lstatic 鏈接 libstatic.a (去掉 lib 前綴和 .a 後綴)
運行 ./kumain 輸出:
a=10, b=3 add=13.00, sub=7.00, mul=30.00, div=3.33
$ nm libstatic.a
add.o:
00000000 T add
sub.o:
00000000 T sub
mul.o:
00000000 T mul
div.o:
00000000 T div
$ nm kumain
0000000000001149 T add
0000000000001167 T sub
0000000000001185 T mul
00000000000011a3 T div
00000000000011c9 T main
U printf@@GLIBC_2.2.5
...
可見 add/sub/mul/div 的代碼(T 類型)已**複製進可執行文件**,實現了靜態鏈接。
| 選項 | 作用 |
|---|---|
-A | 顯示文件名 |
-C | 解碼 C++ 修飾名 |
-D | 顯示動態符號 |
-u | 僅顯示未定義符號 |
-n | 按地址排序 |
| 特性 | 靜態庫 (.a/.lib) | 動態庫 (.so/.dll) |
|---|---|---|
| 鏈接時機 | 編譯鏈接階段 | 運行時加載 |
| 代碼副本 | 每個程序一份 | 內存中共享一份 |
| 可執行文件大小 | 較大 | 較小 |
| 更新部署 | 需重新編譯鏈接 | 替換 .so 即可 |
| 符號解析速度 | 快 (無運行時開銷) | 略慢 (首次加載解析) |
gcc -fvisibility=hidden -c ...,僅導出頭文件聲明的函數;ar -rc libfoo.v1.a ...,主程序鏈接 -lfoo.v1;ar -x lib1.a; ar -x lib2.a; ar -rc libmerged.a *.o;nm -u libstatic.a 應為空。掌握靜態庫製作流程,是 Linux C/C++ 開發者構建可復用組件、管理項目依賴的核心技能。