库:将已经实现的代码进行打包,将代码集合封装在库文件当中,给调用者提供库和相应库中的头文件,提供接口给调用者使用,并不是为了生成可执行程序
动态库:打包,产生与位置无关的代码
- win平台------ 后缀为 .dll
- Linux平台---- 前缀为lib,后缀为 .so
静态库:
- win----- 后缀为.lib
- Linux --前缀为lib,后缀为.a
- 动态链接:生成可执行程序时连接动态库,记录库中的符号表,生成的程序小,并且多个程序运行时在内存可以共享使用同一个动态库,运行时依赖库的存在,因为是运行程序的适合才会将动态库加载到内存中
- 静态连接:生成可执行性程序的适合,连接静态库,直接将库中所用到的函数的实现拿到可执行程序中,不存在运行依赖,效率高,但是生成的可执行程序较大
- 生成库:把大量的已经实现的代码打包起来
先把所有的源码进行编译汇编生成各自的二进制指令,.c变.o文件
所有生成的二进制文件打包到一起- gcc默认生成exe,告诉其要生成一个库,库中没有main函数
动态库生成
gcc -fPIC -c child.c -o child.o
gcc --shared child.o -o libchild.so
- fPIC:在生成指令的时候产生与位置无关的代码(变量指令的地址都是相对偏移量)
各个变量在库中有一个地址,加载后映射到共享区,从共享区相对起始地址开始映射- c:不进行连接处理
- 告诉编译器要生成的是一个库文件,而不是可执行程序
静态库生成
使用ar -cr
gcc -c child.c -o child.o
ar -rc libmychild.a child.o//库文件名称
使用库
gcc main.c -o main -lmychild
会报错,因为编译器会到系统指定的目录下(/usr/lib64)查找这个库文件
但是直接拷贝到系统路径下不好
动态库与静态库同时存在默认连接动态库
gcc是动态连接
使用动态库
先创建bin和so文件夹
gcc是在指定位置下找库
-l告诉编译器要使用哪个库
gcc main.c -o -lmychild
先将库文件放到执行路径下:64位系统-usr/
模拟用户操作
编辑main.c源文件
#include<stdio.h>
#include"print"
int main()
{
print();//该函数在libprint.so的动态库中
return 0;
}
- 需要gcc的两个命令行参数:
-L +路径 |指定当前链接库文件所在路径(告诉gcc链接库文件的位置)
-l+库文件名(去掉前后缀) 表示链接某个库文件
最终命令
gcc main.c –o mymain –lprint –L
- 注意空格,
- 此时-L后没有带路径,所以为当前的默认路径
- 用ldd +可执行程序可查看该可执行程序链接的库
环境变量
如果将生成的动态库从当前路径下移出,就需要用环境变量,在链接时告诉动态库的位置,
将动态库移到上级路径,此时就不能运行mymain这个可执行程序
解决方法:指定动态库的位置
1.将库路径放入系统库路径下(可以但是不推荐,里面都是系统库)
2.设置环境变量
- 有一个环境变量下保存了库的路径,在链接时编译器是遍历该环境变量找到的
- 动态库的环境变量:LD_LIBRARY_PATH
- 添加环境变量命令(临时生效):
export+环境变量名称=$环境变量名称:+新添加环境变量的值
- 步骤:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库的路径
使可执行程序找到自己依赖的动态库:
- 将动态库放到可执行程序的路径下;
会默认搜索当前可执行程序所在路径 - 将动态库路径设置到LD_LIBRARY_PATH环境变量中
- 放到系统库路径下
静态库
生成:
- 用gcc将
print.c
源代码文件编译成目标文件(.o文件)
gcc –c print.c –o print.o- 使用ar –rc命令编译目标文件生成静态库
ar –rc libprint.a print.o
使用方式(同动态库)
gcc main.c –o mymain –lprint –L .
现在编译的可执行程序并不依赖该库文件
以上main.c链接静态库和动态库的方式都是动态链接