静态库制作
静态库(后缀 .a)是多个目标文件(.o)的归档文件,链接时会被完整拷贝到可执行程序中,生成的程序不依赖外部库即可运行。
- 制作静态库相关工具
- GCC:将源文件编译为目标文件(
.o); - ar:GNU 归档工具,用于将多个
.o文件打包为静态库(.a); - ranlib(可选):为静态库生成索引(现代
ar已集成,加-s参数即可)。
- GCC:将源文件编译为目标文件(
- 静态库命名规范
- Linux 下静态库必须以
lib开头,后缀为.a
- Linux 下静态库必须以
2.1、制作步骤
目录结构
.
├── include
│ └── fun.h
└── src
└── fun.c
头文件,声明库中的函数
#ifndef _FUN_H
#define _FUN_H
int add(int a, int b);
#endif
源文件,实现函数
#include "fun.h"
int add(int a, int b)
{
return a + b;
}
- 源文件编译为目标文件
# -I 指定头文件位置
# -Wall 开启警告
gcc@gcc:~/2026/c/static/src$ gcc -c fun.c -o fun.o -I ../include -Wall
gcc@gcc:~/2026/c/static/src$ ls
fun.c fun.o
- 用ar工具将.o文件归档为.a静态库
# ar rcs 静态库名称 目标文件...
gcc@gcc:~/2026/c/static$ ar rcs ./lib/libfun.a ./src/fun.o
gcc@gcc:~/2026/c/static$ ls ./lib/
libfun.a
ar 参数详解:
r:将目标文件插入 / 替换到静态库中(若库已存在);c:创建新的静态库(若不存在);s:为静态库生成索引(等价于ranlib,现代ar必加,否则链接时可能报错)。 验证静态库
# 查看静态库中的目标文件
gcc@gcc:~/2026/c/static/lib$ ar t libfun.a
fun.o
# 查看静态库中的函数(nm 工具) nm libutil.a
gcc@gcc:~/2026/c/static/lib$ nm libfun.a
fun.o:
0000000000000000 T add
2.2、使用静态库
制作完静态库后,需在编译测试程序时链接该库,核心是指定头文件路径、库路径和库名。
#include <stdio.h>
#include "fun.h"
int main(void)
{
int sum = add(10, 20);
printf("sum = %d\n", sum);
return 0;
}
使用静态库编译可执行程序
# -L 指定库位置
gcc@gcc:~/2026/c/static$ gcc main.c -o app -I ./include -L ./lib -lfun -Wall
gcc@gcc:~/2026/c/static$ ls
app include lib main.c src
gcc@gcc:~/2026/c/static$ ./app
sum = 30
2.3、使用注意事项
- 静态库与动态库冲突:若系统中同时存在同名静态库(
.a)和动态库(.so),GCC 默认优先链接动态库,强制链接静态库需加-static参数:
gcc main.c -o app -I ./include -L ./lib -lfun -static -Wall
- 静态库中不能有重复的函数名(多个
.o文件中定义同名函数),否则链接时会报multiple definition of xxx错误。 -
- Linux 下的
.a库无法在 Windows 下使用(需用 MinGW 交叉编译);
- Linux 下的
- 32 位 GCC 编译的静态库不能用于 64 位程序(加
-m32/-m64指定架构); - 若多个静态库存在依赖关系,链接时需按 “依赖逆序” 排列,例如:
libA.a依赖libB.a,则编译命令为:
gcc main.c -o app -LA -LB -lA -lB # 先链接依赖者,再链接被依赖者
动态库制作
GCC 制作动态库(也叫共享库,后缀 .so)是 Linux 开发中实现代码复用、动态更新的核心技能。动态库在程序运行时才被加载,不会被拷贝到可执行程序中,因此生成的程序体积小,且库文件更新后无需重新编译程序。
- 文件命名规范:Linux 下以
lib开头,后缀.so(如libutil.so),通常还会带版本号(如libutil.so.1.0) - 编译参数:必须加
-fPIC(生成位置无关代码)和-shared(生成动态库而非可执行程序) - 运行依赖:程序运行时需能找到动态库(通过
LD_LIBRARY_PATH或系统库路径) - 优势:程序体积小、库更新无需重新编译程序、多个程序可共享同一个库;
- 劣势:部署时需同时发布库文件,运行时依赖库存在且版本兼容;
- 工具:
- GCC:编译源文件为位置无关的目标文件(
.o),并链接为动态库; - ldd:查看可执行程序依赖的动态库(排查 “找不到库” 问题);
- ldconfig:配置系统动态库缓存(永久生效库路径)。
- GCC:编译源文件为位置无关的目标文件(
3.1、制作步骤
代码同静态库代码;
- 编译为位置无关的目标文件
gcc@gcc:~/2026/c/shard/src$ gcc -c fun.c -o fun.o -I ../include -fPIC -Wall
gcc@gcc:~/2026/c/shard/src$ ls
fun.c fun.o
关键参数:
-fPIC:生成位置无关代码(动态库必需,否则链接时会报relocation R_X86_64_PC32 against symbol xxx can not be used when making a shared object错误);-c:仅编译生成目标文件,不链接;-Wall:开启警告,确保库代码无语法问题。
链接生成动态库
gcc@gcc:~/2026/c/shard$ gcc -shared -o ./lib/libfun.so ./src/fun.o
gcc@gcc:~/2026/c/shard$ ls ./lib/
libfun.so
参数详解:
-shared:指定生成动态库(而非可执行程序),必须加;-o libutil.so:指定动态库输出文件名(遵循libxxx.so规范)。
3.2、使用动态库
gcc@gcc:~/2026/c/shard$ gcc main.c -o app -I ./include -L ./lib -lfun -Wall
gcc@gcc:~/2026/c/shard$ ls
app include lib main.c src
gcc@gcc:~/2026/c/shard$ ./app
./app: error while loading shared libraries: libfun.so: cannot open shared object file: No such file or directory
参数详解:
-I./include:指定头文件util.h所在目录;-L./:指定动态库libutil.so所在目录(当前目录);-lutil:链接libutil.so(-l后接库名,自动补全lib和.so);- 与静态库链接命令完全一致,GCC 会自动优先链接动态库(若同时存在
.a和.so)。
3.3、解决动态库加载问题
方法 1:临时指定动态库路径(适合测试)通过 LD_LIBRARY_PATH 环境变量指定动态库所在目录:
gcc@gcc:~/2026/c/shard$ export LD_LIBRARY_PATH=./lib:$LD_LIBRARY_PATH
gcc@gcc:~/2026/c/shard$ ./app
sum = 30
方法 2:永久添加库路径 将动态库路径写入系统动态库配置文件:
# 1. 将库路径添加到 /etc/ld.so.conf.d/(推荐)
echo "lib路径" | sudo tee /etc/ld.so.conf.d/util.conf
# 2. 更新动态库缓存 sudo ldconfig
方法 3:编译时指定运行库路径(推荐)
通过 -Wl,-rpath 参数,将动态库路径写入可执行程序(永久生效):
gcc@gcc:~/2026/c/shard$ gcc main.c -o app -I./include -L./lib -lfun -Wl,-rpath=./lib -Wall
gcc@gcc:~/2026/c/shard$ ./app
sum = 30
3.4、动态库关键调试工具
- 查看程序依赖的动态库(ldd)
gcc@gcc:~/2026/c/shard$ ldd app
linux-vdso.so.1 (0x00007492da43b000)
libfun.so => ./lib/libfun.so (0x00007492da42b000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007492da200000)
/lib64/ld-linux-x86-64.so.2 (0x00007492da43d000)
- 若显示
libfun.so => not found,说明库路径未配置; - 若显示
libfun.so => /usr/lib/libfun.so,说明系统优先加载了其他版本的库。 - 查看动态库中的函数(nm)
gcc@gcc:~/2026/c/shard$ nm -D ./lib/libfun.so
00000000000010f9 T add
w __cxa_finalize
w __gmon_start__
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
- 检查动态库兼容性
gcc@gcc:~/2026/c/shard$ file ./lib/libfun.so
./lib/libfun.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=8a31f8d0979be0b8dc1966da76954ba33642038a, not stripped
[! 注意] 64 位程序无法加载 32 位动态库(加
-m32/-m64指定编译架构)。