Linux 动静态库的制作和使用
序言:
我们在之前的代码练习中都用过标准C和C++库,如果我们也想去制作一个库应该如何去做?这篇博客会详细讲解如何去制作和使用一个库。下面我们先来介绍一下Linux中的一个命令去查看一个可执行程序依赖于哪些库。
ldd + 可执行程序:
在接下来的内容中我们会用这个命令去检查我们程序依赖的动态库。
无论在Windows还是Linux中动静态库都有不同的后缀,我们可以通过后缀来区分它是静态库还是动态库。
Ⅰ、静态库
一、如何生成静态库?
下面介绍一个工具可以帮我们生成静态库 :ar
ar -rc .o文件
-rc(replace and create)如果我们已经生成了一个静态库,我们再次生成同名的静态库,-rc会将以前静态库里没有的.o文件加上,对于更新的.o文件也会更新这个文件,所以静态库是一种归档文件。
二、如何使用静态库?
静态库相当于把.o文件打了个包,但我们不需要去解包gcc/g++会自动去链接静态库
如果直接去编译可执行文件编译器会报函数没有定义的错误,这是因为编译器去寻找库会在系统默认的路径下去寻找我们的静态库不在这个路径下,所以会报错下面介绍两种方法去解决这个问题
1、编译的时候+库的路径+库名
上面的问题是编译器找不到我们的静态库文件,只要我们能够让编译器知道我们的静态库文件在哪?叫什么名字?这就不可以解决这个问题了吗?那么我们应该如何去做?下面介绍gcc/g++的三个选项
-I:如果库的头文件不在当前的路径下和系统默认的路径下编译器会找不到头文件而报错,这个时候-I +同文件路径 编译器就可以知道去哪里寻找头文件。
-L:如果库不在系统默认的路径下编译器就无法找到函数的实现和定义,-L + 库所在的路径 编译器就知道去哪里去寻找库文件。
-l:编译器能够知道库的路径也不行,还需要知道库的名称才能够准确找到所需要的库,-l + 库文件名 。这里需要强调一下:库真正的名字是去掉lib和后缀以后的名字,比如 libmystdio.a 那这个库的名称结束mystdio。
因为库的头文件在当前的路径下所以不需要写出来编译器可以找到。
2、把库文件加到系统默认路径下
如果我们把库文件加到系统默认路径下编译器在去寻找的时候我们只需要告诉编译器需要寻找的库名字编译器就可以找到了。
那系统默认去哪里去寻找呢?
系统头文件默认路径 /usr/include
系统库文件默认路径 /lib/x86_64-linux-gnu(系统有差异可以路径不同)
下面我们把 libmystdio.a 拷贝一份放进去再去编译。
可以看见程序可以执行。
Ⅱ、动态库
一、如何生成动态库?
动态库的生成与静态库相似,只是在工具不同。制作动态库不需要额外的工具只需要gcc/g++就可以了。
先把.c 文件生成.o 文件并且生成位置无关码(具体原因等我们说到动态库加载的时候才能明白)
g++/gcc -fPIC -c 文件名
再把.o文件做成动态库
g++/gcc -o 库名 -shared
接下来我们在生成可执行程序
但是如果我们去执行这个可执行文件我们可以发现无法执行
这是为什么呢?上面的报错说没有这个动态库,但这个动态库不是在当前的路径下吗?我们不是告诉编译器库的路径和名字,我们都已经生成了可执行文件说明编译器已经找到这个动态库了,为什么还报找不到的错误呢?
这是因为我们只告诉了编译器我们的库在哪,从而编译器没有报错生成了可执行程序,但动态库是在运行的时候才去链接的,我们只告诉了gcc/g++库的位置但没有告诉系统库的位置,所以才会报找不到对应的动态库的错误。那这个问题静态库没有啊?这是因为静态库是在编译器在链接这一步就会把程序需要的方法拷贝进去,所以静态库不存在这个问题。
二、如何去找到动态库?
要想程序可以正确的找到动静态库,一共有四种方法:
1、拷贝至默认路径下
这个和静态库一样,在程序执行的时候会去默认路径下去找,我们拷贝到默认路径下只需要去指明是哪个动态库就可以找到,程序就可以执行。
2、在系统默认的路径下建立同名的软链接
我们可以在系统默认的路径下建立一个软链接指向当前路径下的动态库,这样当程序启动的时候去寻找对应的动态库的时候就可以找到这个软链接然后就可以找到我们当前路径下的动态库。(注意软链接的名字一定要和动态库一样)
3、更改环境变量
LD_LIBRARY_PATH:在 Linux 系统中,LD_LIBRARY_PATH 是一个用于指定动态链接库(.so 文件)搜索路径的环境变量。它的主要作用是告诉系统动态链接器(ld.so 或 ld-linux.so)在加载动态库时,除哪些额外的路径需要优先查找。
可以我们去查这个环境变量的时候,这个环境变量是空的
我们可以用export去添加这个环境变量但这种方式是临时的,也可以去更改对应的配置文件这样这个配置文件就会被保存在磁盘中永久生效。
下面我们采用的是export临时添加环境变量:
接下来我们再执行程序
4、改配置文件
/etc/ld.so.conf.d/
目录是用于存放动态链接器(ld.so
或 ld-linux.so
)的配置文件的地方
我们建立一个.conf文件内容是动态库的路径这样当程序执行的时候会调用动态配置器,动态配置器就可以找到这个文件了
还需要输入指令ldconfig,使配置文件生效。
Ⅲ、总结
无论对于动态库还是静态库来说,库的本质就是 .o 文件的集合。使用动态库可以节省内存空间在使用到库方法的时候跳转到库中等执行结束了以后再接着执行可执行程序中接下来的代码,多个程序可以共用一个动态库,所以动态库又叫共享库,而静态库可以将二进制数据拷贝到可执行程序文件中,在执行的时候不需要跳转,但每个可执行程序都需要拷贝对应的数据造成内存浪费。
=========================================================================
本篇关于Linux的文件理解与操作的介绍就暂告段落啦,希望能对大家的学习产生帮助,欢迎各位佬前来支持纠正!!!