【C】静态链接和动态链接

一、静态库和动态库

Linux的库文件一般分为静态库和动态库:

静态库(.a): 库文件以.a为后缀,程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库 动态库(.so): 库文件以.so为后缀,程序运行的时候才会去链接动态库的代码,多个程序共享使用库的代码

二、理解库

如果不想给对方我们的源代码,我们可以选择给用户提供我们的.o可重定位目标二进制文件(gcc -c 文件)与.h头文件。让用户用我们提供的.o文件进行链接即可。在编译时,只要把源文件编译成.o文件在将其链接便可形成一个可执行的程序:

通过 gcc -o 链接目标文件,生成可执行程序:

我们可以把 .o 和 .h 文件提交给用户,可是如果有成百上千个,那一个个提供太过麻烦。因此为了让用户简单的使用库,我们就把所有 .o文件打包成一个包,给对方提供一个库文件即可。把多个文件合并成一个文件,这个文件就是库,打包的方式就分为了静态库和动态库。

三、制作静态库

创建Makefile

c 复制代码
libmymath.a: my_add.o my_sub.o
		ar -rc $@ $^

my_add.o: my_add.c
		gcc -c my_add.c -o my_add.o

my_sub.o: my_sub.c
		gcc -c my_sub.c -o my_sub.o

.PHONY: output
output:
		mkdir -p mylib/include
		mkdir -p mylib/lib
		cp -f *.a mylib/lib
		cp -f *.h mylib/include

.PHONY: clean
clean:
		rm -rf *.o libmymath.a

在Makefile中,$@和$^是自动变量,用于表示规则中的目标和依赖项。

  • $@表示当前规则的目标(target),即规则左侧的文件名。
  • $^表示当前规则的所有依赖项(prerequisites),即规则右侧的文件名。

在Makefile中,libmymath.a: my_add.o my_sub.o规则中的 $@ 表示 libmymath.a,即目标文件名。$^ 表示 my_add.o my_sub.o,即所有依赖项的列表。

当执行命令时,$@和$^会被替换为实际的目标和依赖项的文件名,以便进行相关操作。例如,ar -rc $@ $^ 中的 $@ 将被替换为 libmymath.a,$^ 将被替换为 my_add.o my_sub.o。因此,该命令最终将执行 ar -rc libmymath.a my_add.o my_sub.o,将 my_add.o 和 my_sub.o 打包成 libmymath.a 静态库。

output 是我们要生成的库

链接库:

c 复制代码
 gcc -o mytest my_test.c  -I ./mylib/include -L ./mylib/lib -lmymath

-I:指明头文件的搜索路径

-L:指明库文件的搜索路径

-l:指明要链接哪个库,带上库的名称(去掉前缀和后缀)

四、制作动态库

首先我们需要把库文件全部编译成.o文件,这里与静态库不同,需要带上选项 -fPIC,形成与位置无关码:

c++ 复制代码
gcc -c -fPIC my_add.c

动态库打包:-shared

c++ 复制代码
gcc -shared -o libmymath.so my_add.o my_sub.o

目录结构:

c 复制代码
➜  test tree
.
├── libmymath.so
├── Makefile
├── my_add.c
├── my_add.h
├── my_add.o
├── mylib
│   ├── include
│   │   ├── my_add.h
│   │   └── my_sub.h
│   └── lib
│       └── libmymath.so
├── my_sub.c
├── my_sub.h
├── my_sub.o
├── mytest
└── my_test.c

链接动态库:

c 复制代码
gcc -o mytest my_test.c -I mylib/include -L mylib/lib  -lmymath

报错了:

我们此时已经告诉了库文件,路径和库名称,选项已经给gcc带上了。但是我们当编译完之后,和gcc还有关系吗?答案是无关的,接下来运行是和OS有关的,动态库是运行时才加载的,所以程序运行起来,OS和shell也是需要知道库是在哪里的!而我们自己制作的库并没有在系统路径下,OS无法找到!如何找到动态库。

把库路径添加到环境变量LD_LIBRARY_PATH:

c 复制代码
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/zmm/playground/test/mylib/lib
相关推荐
誰能久伴不乏18 分钟前
用 UDP 做一条“可靠“的控制通道
c++·qt·网络协议·udp
十五年专注C++开发35 分钟前
FlatBuffers: 一个高效的零拷贝二进制序列化库
c++·序列化·反序列化·flatbuffers
xys_6781 小时前
深挖C++:C++入门基础
开发语言·c++
高冷小鱼殿下1 小时前
C 语言指针与输入输出
c++
路溪非溪2 小时前
C++标准库之智能指针
linux·开发语言·c++
hetao17338372 小时前
2026-11-02 hetao1733837 的刷题记录
c++·算法
Tairitsu_H3 小时前
[C++高阶数据结构·图论下] 最短路径:为什么“挑最小的”一定正确?
数据结构·c++·图论
weixin199701080164 小时前
官方授权通道和灰色爬虫,做数据服务该选哪条路(附 python 源码)
c++·爬虫·python
wuminyu4 小时前
JVM执行引擎学习总结:热点字节码编译成本地机器码
java·linux·c语言·jvm·c++
Tairitsu_H4 小时前
[C++高阶数据结构·图论上] 最小生成树:为什么“选边”和“选点”是两条路?
数据结构·c++·图论·最小生成树