ar(archiver)是 GNU Binutils 核心工具,用於創建、修改、提取靜態庫(.a 文件)。靜態庫本質是目標文件(.o)的歸檔集合,鏈接器從中提取所需符號。本文完整覆蓋參數表、常用操作模式、配合 GCC 鏈接實戰、符號表管理。

ar [-dmpqrtx] [cfosSuvV] [a|b|i member] archive [member...]
| 碼 | 功能 | 典型用法 |
|---|---|---|
d | 刪除成員 | ar d libfoo.a obsolete.o |
m | 移動成員順序 | ar m libfoo.a first.o (移至開頭) |
p | 輸出成員內容到 stdout | ar p libfoo.a bar.o > bar.o |
q | 快速追加(不檢查替換、不更新符號表) | ar q libfoo.a new.o |
r | 插入/替換成員(最常用,自動更新符號表) | ar r libfoo.a *.o |
t | 列出成員清單 | ar t libfoo.a |
x | 提取成員到當前目錄 | ar x libfoo.a |
| 修飾符 | 功能 |
|---|---|
a member | 在指定成員 之後 插入 |
b member | 在指定成員 之前 插入 |
i member | 同 b,GNU 兼容 |
c | 創建庫時不提示「creating」 |
f | 截斷過長文件名(兼容舊格式) |
o | 保留成員原始時間戳 |
s | 創建/更新符號表(等同 ranlib) |
S | 不生成符號表(節省空間,鏈接時需手動 ranlib) |
u | 僅插入比庫中舊的新文件(基於修改時間) |
v | 詳細輸出 |
V | 顯示版本號 |
# 編譯源文件為目標文件
gcc -c math_add.c math_sub.c -o math_add.o -o math_sub.o # 錯誤示例,正確如下
gcc -c math_add.c -o math_add.o
gcc -c math_sub.c -o math_sub.o
# 創建/更新庫 (r=插入/替換, c=不提示創建, s=生成符號表, v=詳細)
ar rcs libmath.a math_add.o math_sub.o
# 查看成員
ar t libmath.a
# math_add.o
# math_sub.o
# main.c 調用 add(), sub()
gcc main.c -L. -lmath -o main
# -L. 指定庫搜索路徑, -lmath 鏈接 libmath.a
# 或顯式指定庫文件
gcc main.c libmath.a -o main
# 替換 math_add.o (重新編譯後)
gcc -c math_add_v2.c -o math_add.o
ar r libmath.a math_add.o # r 自動更新符號表
# 刪除 math_sub.o
ar d libmath.a math_sub.o
# 提取所有成員到當前目錄
ar x libmath.a
ls *.o
# math_add.o
# 提取單個成員
ar p libmath.a math_add.o > math_add_extracted.o
# 手動生成/更新符號表 (等同 ar s)
ranlib libmath.a
# 查看符號表
nm -s libmath.a
# Archive index:
# add in math_add.o
# sub in math_sub.o
# ...
注意:ar q 快速追加不更新符號表,後續必須執行 ranlib 或 ar s,否則鏈接器找不到符號。
| 場景 | 推薦工具 | 理由 |
|---|---|---|
| C/C++ 靜態庫構建 | ar (GNU Binutils) | 標準、穩定、鏈接器原生支持 |
| Rust 靜態庫 | cargo build --lib (生成 .rlib/.a) | 語言原生,處理元數據、依賴圖 |
| Go 靜態鏈接 | go build (默認靜態) | 無需 .a,直接生成可執行文件 |
| 跨平台庫打包 | CMake add_library(STATIC) | 構建系統抽象 ar 差異 |
| 大型項目增量構建 | Ninja + ar | 並行構建、精確依賴 |
| 現象 | 原因 | 解決 |
|---|---|---|
ar: libfoo.a: File format not recognized | 文件損壞、非 ar 格式、32/64 位不匹配 | file libfoo.a 驗證,重新構建 |
鏈接報 undefined reference | 符號表缺失、成員順序導致循環依賴未解決 | ar s libfoo.a 或 ranlib;調整 .o 順序或用 --whole-archive |
| 庫過大 | 包含調試符號、未剝離 | strip --strip-debug libfoo.a 或編譯時 -g0 |
| 跨編譯器兼容 | GCC/MSVC/Clang COFF/ELF 格式差異 | 同平台用同工具鏈;Windows 用 lib.exe (MSVC) |
# 創建薄歸檔 (只存儲成員文件路徑,不複製數據)
ar rcsT libthin.a /path/to/obj1.o /path/to/obj2.o
# 特點:極小、依賴外部 .o 文件存在、構建系統中間產物適用
# 鏈接時需確保 .o 路徑可訪問
掌握 ar 能讓您深入理解靜態鏈接機制、排查符號解析疑難雜癥、優化構建產物體積,是 C/C++ 系統級開發的核心基本功。