版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/men_wen/article/details/75205499
gcc 编译工具(下)— 外部库、共享库、静态库、动态库
1. 头文件与库文件
- 在使用C语言和其他语言进行程序设计时,需要头文件来提供对常数的定义和对系统及函数调用的声明。
- 库文件是一些预先编译好的函数集合,那些函数都是按照可重用原则编写的。他们通常有一组互相关联的用来完成某项常见工作的函数构成。比如用来处理屏幕显式情况的函数(ncurses库)和数据库访问例程(dbm库)等。
- 使用库的好处:
- 模块化:将不同功能模块的文件编译成不同的库,有利用明确项目之间的分工。
- 可重用性高:无需关心内部实现,直接调用即可。
- 可维护性:当库文件的代码发生改变,无需更改使用库文件的代码,增强代码的可维护性。
2. 头文件与库文件的位置
- /usr/include 及其子目录底下的 include 文件夹
- /usr/loacl/include 及其子目录底下的 include 文件夹
- /usr/lib
- /usr/local/lib
3. 使用外部库(-l选项)
如下面这个例子:
#include <math.h>
#include <stdio.h>
int main(void)
{
double d = pow(2.0, 4.0);
printf("The cubed is %f\n", d);
return 0;
}
我们想使用math.h
库中的pow()
函数,因此在编译时,需要连接对应的库。执行如下命令:
➜ test gcc -Wall calc.c -o calc -lm
➜ test ./calc
The cubed is 16.000000
其中-lm
表示要链接libm.so
或者libm.a
库文件。
4. 静态库与共享库
- 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候不再需要静态库。静态库会被链接到可执行文件中,比较占用磁盘空间,并且执行时会将库的代码加载到内存,占用更多的内存,并且多个程序无法共享。
- 共享库(.so 或 .sa):程序在运行的时候才去链接共享库的代码,多个程序可以共享使用库的代码。共享库可以在多个程序间共享,所以动态链接使得可执行程序文件更小,节省了磁盘空间,操作系统采用虚拟内存机制允许物理内存中的一份共享库被要用到该库的所有进程共用,节省了内存和磁盘空间。
一个与共享库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数在目标文件的整个机器码。
在可执行文件开始运行以前,外部的机器码由操作系统从磁盘上的该共享库中复制到内存中,这个过程成为动态链接(dynamic linking)。
5. 生成静态库
生成静态库可以理解为将一个对.o
文件的归档。将一个或多个.o
文件打包生成.a
文件。
可以使用ar
工具,例如:
➜ test gcc -Wall -c hello.c -o hello.o
➜ test ar rcs libhello.a hello.o
➜ test ls -l libhello.a
-rw-rw-r-- 1 menwen menwen 1518 7月 16 14:33 libhello.a
// ar是gnu的归档工具
// rcs = replace、create、save
接下来就是将生成的.a
库文件和调用库函数的文件生成可执行文件。
➜ test gcc -Wall main.c libhello.a -o main
➜ test ./main
hello world
这样生成可执行文件时要注意main.c libhello.a
这两个文件的书写顺序,否则编译会出错。
还有一种方法来生成可执行文件,就是通过-l
选项。例如:
➜ makefile gcc -Wall -L. main.c -o main -lhello
➜ makefile ./main
hello world
// -L.:-L选项来指定库的位置,在当前目录下
6. 生成共享库
生成共享库的过程如下:
➜ makefile gcc -Wall -c -fPIC hello.c // 编译生成.o文件时一定要加上-fPIC选项
➜ makefile gcc -shared -fPIC hello.o -o libhello.so
➜ makefile ls -l libhello.so
-rwxrwxr-x 1 menwen menwen 8024 7月 16 14:58 libhello.so
// -shared:生成共享库格式
// -fPIC:产生位置无关码(position independent code)
链接库生成可执行文件:
gcc -Wall -L. main.o -o main -lhello
➜ test ./main
./main: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory
但是执行可执行文件时报错:无法链接到共享库。因此我们要运行共享库,一共有三种方式:
- 拷贝
.so
文件到系统共享库路径下,一般是/usr/lib - 更改LD_LIBRARY_PATH
- ldconfig。配置/etc/ld.so.conf,ldconfig更新ld.so.cache
我们将生成的.so
库拷贝到系统共享库路径下,就可以成功执行
➜ test sudo cp libhello.so /usr/lib
➜ test ./main
hello world
7. 库搜索路径
- C_INCLUDE_PATH、LIBRARY_PATH(在~/.bash_profile文件中配置用户的环境变量)
- 从左到右搜索-I、-L指定的目录
- 由环境变量指定的目录
- 由系统指定的目录
如果按照以上顺序无法找到链接的库,则会报错。