瑞星 发表于 2024-8-9 06:56:08

【Linux】动静态库

动静态库

1. 设计库

库分为 静态库(.a)和动态库(.so)
库的定名
以c++的库为例
输入 ls /lib64/libstdc++*
以lib开头要去除
库的真实名字为 stdc++
一样平常云服务器,默认只会存在动态库,不需要动态库,静态库需要单独安装
myadd.h
实现一个加法的声明
#pragma once   
int myadd(int d1,int d2);   
                           
myadd.c
实现一个加法的实现
#include"myadd.h"   
int myadd (int d1,int d2)   
{   
   return d1+d2;   
}   
   
mysub.h
实现一个减法的声明
#pragma once   
int sub(int d1,int d2);   
mysub.c
实现一个减法的实现
#include"mysub.h"   
int mysub(int d1,int d2)   
{   
return d1-d2;   
}
main.c
实现对myadd和mysub的调用
#include<stdio.h>   
#include"myadd.h"   
#include"mysub.h"   
int main()   
{   
      
    int x=100;   
    int y=34;   
    printf("%d+%d=%d\n",x,y,myadd(x,y));   
E>printf("%d-%d=%d\n",x,y,mysub(x,y));   
    return 0;   
}
利用main.c mysub.c myadd.c 生成一个可执行程序 mytest 输入 gcc -o mytest myadd.c mysub.c main.c 指令
出于安全和便捷性考虑,都不想把源代码给别人,所以要把源代码打包
https://i-blog.csdnimg.cn/blog_migrate/c646d38d85bf6c3c693136066a8b0701.png 创建mylib目次代表自己 , otherperson目次代表其他人
main.c应该是另一个人用的代码,所以把main.c移动到otherprson目次中
输入指令 mv main.c otherperson/
在链接之前把源代码编译成.o的二进制目标文件
把所对应的源文件 颠末预处理 编译 汇编 形成 .o文件
https://i-blog.csdnimg.cn/blog_migrate/d5aa22d4e8409c697d2d8ee02ac1a39e.png https://i-blog.csdnimg.cn/blog_migrate/906f3c7a4a33e95014034a839d6f1d67.png 分别通过myadd.c 与mysub.c形成 myadd.o 与 mysub.o
为了不想给别人交付源代码,把所有的.h文件拷贝到 otherperson里面
同时把 所有的.o文件 也拷贝到 otherperson里面
$ cp *.h otherperson
$ cp *.o otherperson

在otherperson 目次中
将main.c形成一个main.o的文件
https://i-blog.csdnimg.cn/blog_migrate/98faf792fdf48fdba2598dc9c6a2d5b8.png 把add.o sub.o main.o 链接形成 mytest 可执行程序
https://i-blog.csdnimg.cn/blog_migrate/068aabb5a6eaa5fdea4eeae8c8dee146.png 此时在otherperson目次中 利用 mytest 可执行程序去执行 就可以了
但是把一大堆的头文件和目标文件都传给 otherperosn目次 调用有点太繁琐了
1. 静态库打包

只有一个.o的压缩包

tar - c :创建一个新的归档文件即压缩包
tar- r : 若.c文件修改了,则对一个或者多个.o文件做替换
https://i-blog.csdnimg.cn/blog_migrate/9bf9ccb08fce5942c0d17fa0d6b21e66.png
当前目次下包含 mylib otherperson 目次 以及 .o和.c文件
$ar -rc libmymath.a *.o

将当前目次下的 所有.o目标文件打包 并定名为 libmymath.a
https://i-blog.csdnimg.cn/blog_migrate/1af1f7a717f42ea78a1ff221a5c75c5c.png 在otherperson目次中,删除之前所预留的所有.o与.h文件以及 myetst可执行程序
此时otherperosn目次中只剩下 main.c
重新在mylib目次中取.o与.a文件
https://i-blog.csdnimg.cn/blog_migrate/8fe215c11f5c4bfb3f92c94f8ec9c315.png
此时otherperson目次中存在.h文件 与main.c 以及 .o目标文件的压缩包
报错1

输入 gcc - o myetst main.c 指令 会报错
https://i-blog.csdnimg.cn/blog_migrate/645ba1d1e8014277d6a9bbd0259a3166.png
有库后,将库引入项目,必须让编译器找到头文件和库文件
因为引入的库 属于第三方库,gcc并不能明确用的那个库,要让编译器熟悉这个库
加入 -l选项 要链接哪一个库
https://i-blog.csdnimg.cn/blog_migrate/94b2d32e50f0caa4012793885f97ffa9.png
此时依旧会报错
加入-L.选项 对应的库在那个路径下
https://i-blog.csdnimg.cn/blog_migrate/ac65f37bb62820d1fd1a5e5da9e79577.png
输入 gcc -o mytest main.c -L. -lmymath 指令 即可正常运行可执行程序
https://i-blog.csdnimg.cn/blog_migrate/6568799fd302743d9003831b87ac589f.png
创建.o与.h的压缩包

在mylib目次下
https://i-blog.csdnimg.cn/blog_migrate/cabe35ad7292b0bf1b566724a37faa27.png
创建include目次 与 lib目次
拷贝所有的.h文件放在include目次下 ,拷贝所有的.a文件放在lib目次下
https://i-blog.csdnimg.cn/blog_migrate/7aa23bea57c906cb3252550534be5abc.png
所以将来是将这两个目次传给用户
tar - c :创建一个新的归档文件即压缩包
tar - z : 利用打包的同时可以举行压缩
tar - f : 给归档文件一个名字 建议把 f 放在末了
tar -czf + 文件名.tgz +文件名
https://i-blog.csdnimg.cn/blog_migrate/73d4db35b6e4ca70607d29e863e53333.png
将dir与include两个目次举行打包 生成 mymath.tgz
在otherperson目次下
https://i-blog.csdnimg.cn/blog_migrate/7c0492090d9af19bf1dcd111474804ac.png
将属于mylib目次下的压缩包 mymath.tgz 拷贝到 otherperson 目次下
tar -x 解开文件
tar -xzf 文件名.tgz
https://i-blog.csdnimg.cn/blog_migrate/941e3f9d6c04a7c0ae082deeaf27b2ab.png
利用 tar xzf 举行解包
报错2

https://i-blog.csdnimg.cn/blog_migrate/9cb1716b5862e62a9a2ecec9a97bfad4.png
头文件找不到
因为头文件在inlcude 里,不在当前路径下
https://i-blog.csdnimg.cn/blog_migrate/14403ee4cd667e0b4b687fb42e7a92ee.png
在include的路径下,寻找头文件
依旧报错了,但是头文件找到了
https://i-blog.csdnimg.cn/blog_migrate/31c148bfdc81a885060f799e6338d65a.png
告诉编译器库在lib中
还是会报错 ,因为lib库并不属于c/c++的标准库
还需要告诉库的名字是什么
https://i-blog.csdnimg.cn/blog_migrate/aa220e1f5add6c576b987247da029b25.png
将独立的将库引入otherperson中 ,可以正常运行
第三方库的利用

第三方库的利用
1.需要的是指定的头文件和库文件
2.如果没有默认安装到体系的gcc/g++默认的搜索路径下,用户必须指明对应的选项,告知编辑器, 头文件在哪里,库文件在哪里,库文件具体是谁
将头文件和库拷贝对应的体系路径

在otherperson目次下
https://i-blog.csdnimg.cn/blog_migrate/9d536d37d982bc06c1bdd8eb1423cd10.png
https://i-blog.csdnimg.cn/blog_migrate/831eee14406b0602e399d5a0537a1250.png
将当前include下的所有内容拷贝到体系对应的include路径下
https://i-blog.csdnimg.cn/blog_migrate/7eeed988ea85bc93d512ac067ea4886e.png
查看体系路径中就存在 myadd.h 与mysub.h
https://i-blog.csdnimg.cn/blog_migrate/812f15bcbabf4f421ec1d0de88c16fa8.png
将dir拷贝到库的搜索路径下
https://i-blog.csdnimg.cn/blog_migrate/bd324b936c712b85c576a42d6b66bc17.png
由于将include对应的文件传入体系路径中以及将dir对应的文件传入库的搜索路径下 ,
此时otherperson目次下只存在 main.c 文件
刚刚拷贝过去的库,属于非C/C++标准的库,所以被认为是第三方库
https://i-blog.csdnimg.cn/blog_migrate/bd3378d6c3622f581f90415fa46bdc77.png
告诉它需要链接mymath库,就可以正常运行了,而不需要告诉头文件


[*] 将下载下来的库和头文件,拷贝到体系默认路径下,这个活动就叫做在Linux下安装库
对于任何软件而言,安装和卸载的本质是拷贝到体系特定的路径下
[*]如果要安装第三方的库,(第一方库是语言,第二方库是操纵体系体系接口),要正常利用,即便已经全部安装到体系中,gcc/g++必须用 -l 来指明具体库的名称
2. 动态库打包

在mylib目次下
制作动态库也需要.o目标文件,再将目标文件打包
https://i-blog.csdnimg.cn/blog_migrate/c3434f3be0f494349bdad6083387ddd0.png
动态库打包倒霉用 ar,而是直接利用gcc 并且加上 fPIC的选项
P代表 position 位置
I代表 independent 忽略
C 代表 code
https://i-blog.csdnimg.cn/blog_migrate/4d5affd7301d963570378d44e379cdb4.png
生成myadd.o与mysub.o的目标文件,并形成与位置无关码
shared选项 代表打包的是一个共享库/动态库
https://i-blog.csdnimg.cn/blog_migrate/cf13ac9a0a4e6da7953a9fedfc192b52.png
将myadd.o 与mysub.o打包 成动态库,并定名为 mymath
在mylib目次下
利用 mkdir 分别创建 目次 include 与lib
https://i-blog.csdnimg.cn/blog_migrate/e50285fc258eaf7876cc669d192b0e64.png
https://i-blog.csdnimg.cn/blog_migrate/14c6eb5ada4aca91e569c2b9ede810af.png
将所有的.h文件拷贝到 include 目次下 即 include中存在头文件
将所有的.so文件拷贝到 lib目次下 即 lib中存在 动态库
https://i-blog.csdnimg.cn/blog_migrate/5bdc2583971bc60c2ab9d533d72b0c77.png
将include 与lib 打包,并定名为 mymath.tgz
https://i-blog.csdnimg.cn/blog_migrate/814939d68e55742c9778318f17f2abe3.png
将 mymanth.tgz 这个包 拷贝到 otherperson目次中
在otherperson目次下
https://i-blog.csdnimg.cn/blog_migrate/c8ae45425ecef609a7d0f45e727eea34.png
此时的otherperson目次下存在 mymanth.tgz 与main.c
https://i-blog.csdnimg.cn/blog_migrate/72c04d93348452b9ac0df5a8802a73de.png
通过 xzf 解包,表现出 include (存放头文件)与 lib (存放动态库)
报错

https://i-blog.csdnimg.cn/blog_migrate/ab6b4a7f90c8f00619bc763fd3c58ec0.png
表现找不到头文件
https://i-blog.csdnimg.cn/blog_migrate/a41d3d3a9adec14fc17d312ed9a9aac7.png
加入-I后,在include下寻找头文件,但依旧会报错 ,因为找不到库了
https://i-blog.csdnimg.cn/blog_migrate/a0e5bd89845bb9aba65bbf3b6f66142f.png
加入 -L 后在lib 中寻找库 ,并加入-lmymath ,链接库mymath
运行时报错

https://i-blog.csdnimg.cn/blog_migrate/8296ea9628e1c563d69fc3db28522687.png
但是在运行生成的可执行程序mytest时,还是会报错
说明链接时,动态库并没有真正链接到可执行程序
在上面 gcc 时,已经告诉体系库在哪里,叫什么了,为什么还是找不到?
只是告诉了编译器,并不是操纵体系
运行时,你的.so并没有在体系默认的路径下,所以操纵体系依旧找不到
找到动态库的方法

方法1 ——情况变量(暂时方案)

LD_LIBRARY_PATH
LD代表链接
LIBRARY 代表库
PATH 代表路径
https://i-blog.csdnimg.cn/blog_migrate/205d7b36169619317d892d56c5f7f52b.png
https://i-blog.csdnimg.cn/blog_migrate/43e60c6e2dc1831b4f320704660405c1.png
表现为库的路径
https://i-blog.csdnimg.cn/blog_migrate/f1dcd47b4ce241a1c009c9276312a6c7.png
将当前库的路径添加到情况变量中
https://i-blog.csdnimg.cn/blog_migrate/e9b123702df14f1f454936df736fd222.png
查询情况变量时,发现当前库的路径已经在情况变量中
https://i-blog.csdnimg.cn/blog_migrate/39114be1d677e8988a34671876d357d7.png
再次查看第三方库时,mymath.so有对应的第三方库了
https://i-blog.csdnimg.cn/blog_migrate/5bd651f959270663ec88ccb4a7d4fc98.png
此时mytest可以正常执行了
但是情况变量只在本次登录有效,若退出再进入,则情况变量还是找不到
方法2 ——创建软链接

https://i-blog.csdnimg.cn/blog_migrate/4b12664e73b3c605b2a50aee46cd890e.png
在体系默认的路径下,创建一个软链接指向库
https://i-blog.csdnimg.cn/blog_migrate/4974177c25e8429d1c4a1e91be8e4d4c.png
此时软链接指向这个库
https://i-blog.csdnimg.cn/blog_migrate/126f81791120cde792e0e986bdf4d5a5.png
查看第三方库时,libmymath.so有自己的第三方库
https://i-blog.csdnimg.cn/blog_migrate/c588dac0915fa9d14fe1250d3ef8fe3d.png
软链接是一个文件,所以即便关闭xshell,再次打开也能正常运行mytest 可执行程序
方法3——配置文件方案

https://i-blog.csdnimg.cn/blog_migrate/f210ec55557b9cb993297191c6b3aa88.png 利用 ldd 找不到 libmymath对应的第三方库
在体系当中存在配置文件
ld代表链接库
so代表动态库
conf代表配置文件
https://i-blog.csdnimg.cn/blog_migrate/bd3fb47ade4dbdecd96c91d05da23ee5.png
创建一个配置文件,并定名为look
输入 ls /etc/ld.so.conf.d/ 指令
https://i-blog.csdnimg.cn/blog_migrate/41f3dd3a88281bca741addd5c53756f8.png
查看体系的配置文件,就发现多了一个look的配置文件
https://i-blog.csdnimg.cn/blog_migrate/bf2b2b1d81429ed6bbc83e3d285f0904.png
由于动态库存放在otherperosn目次下的lib中, 所以进入lib目次中,表现当前库的路径,将其复制
https://i-blog.csdnimg.cn/blog_migrate/1ead0ab947fa8b36ad0c8843e88bc50f.png
利用vim进入自己创建的配置文件中,并把 上述复制好的库的路径粘贴到里面
https://i-blog.csdnimg.cn/blog_migrate/6b2f504433d1bc3c56c863ff897e9be2.png
输入 ldd mytest 指令,发现还是找不到第三方库
https://i-blog.csdnimg.cn/blog_migrate/a66cf8404c1bec2948f75b39a9b3ac8a.png
查看自己的配置文件时,已经有了对应的库的路径
还需让其见效
输入 sudo ldconfig 指令
https://i-blog.csdnimg.cn/blog_migrate/be58ce899194b444e4812f93949cf98e.png
就会让体系加载新的配置文件
https://i-blog.csdnimg.cn/blog_migrate/e573395f3addc4d617b30a5b26c29d51.png 即可正常运行程序

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 【Linux】动静态库