目录
- 静态库(.a)
- 制作静态库
- 如何使用静态库
- 动态库(.so)
- 制作动态库
- 如何使用动态库(.so)
静态库(.a)
静态库顾名思义是静态的,即程序编译链接时,会把静态库的代码链接到可执行文件中。运行时不需要静态库(将静态库删了也能运行)。相当于静态库的代码复制到了可执行文件中。
制作静态库
分别有如下add.c add.h sub.c sub.h四个文件格式。
- 首先把.c文件都编译成.o文件。使用下面命令
//-c 编译到二进制文件就停止
gcc -c add.c -o add.o
gcc -c sub.c -o sub.o
- 把.o打包的过程就是形成静态库的过程。使用下面命令:
# ar:archive file 归档文件 -rc:replace create
# libhello.a:lib是前缀名,必须加的;.a是静态库的后缀,必须加;hello是自己库的名字
ar -rc libhello.a add.o sub.o
- 这样我们的静态库就制作好啦。使用下面的命令可以查看静态库中的目录列表:
# t:列出静态库中的文件
# v:verbose 详细信息
ar -tv libhello.a
创建一个makefile来使编译程序简化:
如何使用静态库
首先将我们的库函数放在一个文件夹里面:
运行完如下图所示:
使用:main函数如下:
方法一:将该库放到系统搜索的库中。
头文件gcc的默认搜索路径是:/usr/include
库文件的默认搜索路径是:/lib64 or /usr/lib64
- 使用如下命令将自己的库,复制到上面目录中:
#复制头文件
sudo cp ./hello/include/* /usr/include/ -rf
# 复制库文件
sudo cp -rf ./hello/lib/* /lib64
- 使用该库
为什么我们使用c语言库不用告诉他链接哪个库呢?
因为gcc是专门链接C语言的,他自己本身就设定好了,去哪个库找。但是我们自己的库,我们需要自己指定目录。
# -l链接的意思 -lhello链接名字为hello的库
# -static 选择静态链接的方式
gcc main.c -lhello -static //默认生成a.out
gcc -o main main.c -lhello -static //指定生成main可执行文件
总结:这种方法不推荐,因为涉及到更改系统目录的内容了。
我们再把那俩文件删除:
sudo rm /usr/include/add.h /usr/include/sub.h
sudo rm /lib64/libhello.a
方法2:硬要使用。推荐
直接让gcc找指定路径的指定库。
如下命令:
# -I:指定头文件搜索路径
# -L: 指定库文件搜索路径
# -lhello:指定使用哪个库
gcc -o main main.c -I ./mklib/hello/include/ -L ./mklib/hello/lib/ -lhello
方法3:在系统的搜索路径下,创建一个硬链接。也不推荐使用
动态库(.so)
- 程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
- 一个动态库链接的可执行文件,仅仅包含用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。
- 在可执行文件开始运行之前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接。
- 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间,OS采用虚拟内存机制允许物理内存中的一份动态数据库被要用到该库的所有进程共用,节省了内存和磁盘空间。
制作动态库
- 首先将.c文件变成与位置无关的二进制.o文件。
# -fPIC: 与二进制无关选项
gcc -fPIC -c add.c -o add_d.o
gcc -fPIC -c sub.c -o sub_d.o
- 将.o文件打包成动态库
# -shared:动态库选项
# libhello.so:lib是前缀,.so是后缀, hello是动态库名字
gcc -shared add_d.o sub_d.o -o libhello.so
这样我们的动态库就制作成功啦。
如何使用动态库(.so)
首先写一个makefile方便制作动态库。
hello文件结构如图所示:
仍然用静态库的那个命令(不加static了,默认就是动态链接),如下:
**解释:**我们实际上用的方法是对的,也告诉gcc使用hello的库了,并且默认也是动态链接。但是还是无法执行。是因为,我们只是告诉gcc了,但是没有告诉os,os在执行此动态库时,并不知道要去哪里把动态库搬进内存。因此我们要告诉,os去哪里找这个动态库。
方法一:添加系统变量
- OS使用LD_LIBRARY_PATH加载环境变量。
将自己的库的绝对路径,添加到环境变量即可。
# 注意添加库的路径即可。
export LD_LIBRARY_PATH=$LD_LIBRARY:/home/xty/cplusplus/linux/20140110/mklib/hello/lib
总结:不持久,重新登录一次就又不能用了。因为环境变量会重新加载,我们弄得是临时的环境变量。
方法二:修改配置文件
# 创建一个mylib.conf 配置文件,直接把库的绝对路径写入即可。
sudo vim /etc/ld.so.conf.d/mylib.conf
# 更新缓存
sudo ldconfig
总结:持久,推荐使用。
方法三:使用软链接也可以
在/lib64/目录里面,创建一个libhello.so软链接,链接库文件的地址。这个方法请读者自行实现,但是也不推荐,因为同样更改了系统目录内容。