@TOC

动静态库

1. 设计库

库分为 静态库(.a)和动态库(.so) 库的命名 以c++的库为例 输入 ls /lib64/libstdc++* 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 指令


出于安全和便捷性考虑,都不想把源代码给别人,所以要把源代码打包


【Linux】动静态库_第三方库

创建mylib目录代表自己 , otherperson目录代表其他人


main.c应该是另一个人用的代码,所以把main.c移动到otherprson目录中 输入指令 mv main.c otherperson/


在链接之前把源代码编译成.o的二进制目标文件 把所对应的源文件 经过预处理 编译 汇编 形成 .o文件

【Linux】动静态库_动态库_02


【Linux】动静态库_第三方库_03

分别通过myadd.c 与mysub.c形成 myadd.o 与 mysub.o


为了不想给别人交付源代码,把所有的.h文件拷贝到 otherperson里面 同时把 所有的.o文件 也拷贝到 otherperson里面

[yzq@VM-8-8-centos lesson1]$ cp *.h otherperson
[yzq@VM-8-8-centos lesson1]$ cp *.o otherperson

在otherperson 目录中 将main.c形成一个main.o的文件

【Linux】动静态库_头文件_04

把add.o sub.o main.o 链接形成 mytest 可执行程序


【Linux】动静态库_头文件_05

此时在otherperson目录中 使用 mytest 可执行程序去执行 就可以了

但是把一大堆的头文件和目标文件都传给 otherperosn目录 调用有点太繁琐了

1. 静态库打包

只有一个.o的压缩包

tar - c :创建一个新的归档文件即压缩包 tar- r : 若.c文件修改了,则对一个或者多个.o文件做替换


【Linux】动静态库_第三方库_06

当前目录下包含 mylib otherperson 目录 以及 .o和.c文件


[yzq@VM-8-8-centos lesson1]$  ar -rc libmymath.a *.o

将当前目录下的 所有.o目标文件打包 并命名为 libmymath.a


【Linux】动静态库_头文件_07

在otherperson目录中,删除之前所预留的所有.o与.h文件以及 myetst可执行程序 此时otherperosn目录中只剩下 main.c


重新在mylib目录中取.o与.a文件

【Linux】动静态库_第三方库_08

此时otherperson目录中存在.h文件 与main.c 以及 .o目标文件的压缩包

报错1

输入 gcc - o myetst main.c 指令 会报错

【Linux】动静态库_头文件_09

有库后,将库引入项目,必须让编译器找到头文件和库文件 因为引入的库 属于第三方库,gcc并不能理解用的那个库,要让编译器认识这个库


加入 -l选项 要链接哪一个库

【Linux】动静态库_第三方库_10

此时依旧会报错


加入-L.选项 对应的库在那个路径下

【Linux】动静态库_动态库_11


输入 gcc -o mytest main.c -L. -lmymath 指令 即可正常运行可执行程序

【Linux】动静态库_第三方库_12


创建.o与.h的压缩包

在mylib目录下

【Linux】动静态库_第三方库_13


创建include目录 与 lib目录拷贝所有的.h文件放在include目录下 ,拷贝所有的.a文件放在lib目录下

【Linux】动静态库_动态库_14


所以未来是将这两个目录传给用户 tar - c :创建一个新的归档文件即压缩包 tar - z : 使用打包的同时可以进行压缩 tar - f : 给归档文件一个名字 建议把 f 放在最后 tar -czf + 文件名.tgz +文件名

【Linux】动静态库_动态库_15

将dir与include两个目录进行打包 生成 mymath.tgz


在otherperson目录下

【Linux】动静态库_动态库_16

将属于mylib目录下的压缩包 mymath.tgz 拷贝到 otherperson 目录下


tar -x 解开文件tar -xzf 文件名.tgz

【Linux】动静态库_第三方库_17

使用 tar xzf 进行解包


报错2

【Linux】动静态库_头文件_18

头文件找不到 因为头文件在inlcude 里,不在当前路径下


【Linux】动静态库_动态库_19

在include的路径下,寻找头文件 依旧报错了,但是头文件找到了


【Linux】动静态库_头文件_20

告诉编译器库在lib中 还是会报错 ,因为lib库并不属于c/c++的标准库 还需要告诉库的名字是什么


【Linux】动静态库_头文件_21

将独立的将库引入otherperson中 ,可以正常运行

第三方库的使用

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

将头文件和库拷贝对应的系统路径

在otherperson目录下

【Linux】动静态库_动态库_22


【Linux】动静态库_头文件_23

将当前include下的所有内容拷贝到系统对应的include路径下


【Linux】动静态库_头文件_24

查看系统路径中就存在 myadd.h 与mysub.h


【Linux】动静态库_头文件_25

将dir拷贝到库的搜索路径下


【Linux】动静态库_头文件_26

由于将include对应的文件传入系统路径中以及将dir对应的文件传入库的搜索路径下 , 此时otherperson目录下只存在 main.c 文件 刚刚拷贝过去的库,属于非C/C++标准的库,所以被认为是第三方库


【Linux】动静态库_头文件_27

告诉它需要链接mymath库,就可以正常运行了,而不需要告诉头文件

  • Linux下安装库对于任何软件而言,安装和卸载的本质是拷贝到系统特定的路径下
  • 如果要安装第三方的库,(第一方库是语言,第二方库是操作系统系统接口),要正常使用,即便已经全部安装到系统中,gcc/g++必须用 -l 来指明具体库的名称

2. 动态库打包

在mylib目录下制作动态库也需要.o目标文件,再将目标文件打包

【Linux】动静态库_第三方库_28


动态库打包不使用 ar,而是直接使用gcc 并且加上 fPIC的选项P代表 position 位置I代表 independent 忽略C 代表 code

【Linux】动静态库_第三方库_29

生成myadd.o与mysub.o的目标文件,并形成与位置无关码


shared选项 代表打包的是一个共享库/动态库

【Linux】动静态库_动态库_30

将myadd.o 与mysub.o打包 成动态库,并命名为 mymath


在mylib目录下使用 mkdir 分别创建 目录 include 与lib

【Linux】动静态库_头文件_31


【Linux】动静态库_头文件_32

将所有的.h文件拷贝到 include 目录下 即 include中存在头文件 将所有的.so文件拷贝到 lib目录下 即 lib中存在 动态库


【Linux】动静态库_动态库_33

将include 与lib 打包,并命名为 mymath.tgz


【Linux】动静态库_第三方库_34

将 mymanth.tgz 这个包 拷贝到 otherperson目录中


在otherperson目录下

【Linux】动静态库_头文件_35

此时的otherperson目录下存在 mymanth.tgz 与main.c


【Linux】动静态库_动态库_36

通过 xzf 解包,显示出 include (存放头文件)与 lib (存放动态库)

报错

【Linux】动静态库_第三方库_37

显示找不到头文件


【Linux】动静态库_第三方库_38

加入-I后,在include下寻找头文件,但依旧会报错 ,因为找不到库了


【Linux】动静态库_第三方库_39

加入 -L 后在lib 中寻找库 ,并加入-lmymath ,链接库mymath


运行时报错

【Linux】动静态库_动态库_40

但是在运行生成的可执行程序mytest时,还是会报错

说明链接时,动态库并没有真正链接到可执行程序


在上面 gcc 时,已经告诉系统库在哪里,叫什么了,为什么还是找不到?只是告诉了编译器,并不是操作系统运行时,你的.so并没有在系统默认的路径下,所以操作系统依旧找不到

找到动态库的方法
方法1 ——环境变量(临时方案)

LD_LIBRARY_PATHLD代表链接LIBRARY 代表库PATH 代表路径

【Linux】动静态库_第三方库_41


【Linux】动静态库_头文件_42

显示为库的路径


【Linux】动静态库_第三方库_43

将当前库的路径添加到环境变量中


【Linux】动静态库_第三方库_44

查询环境变量时,发现当前库的路径已经在环境变量中


【Linux】动静态库_第三方库_45

再次查看第三方库时,mymath.so有对应的第三方库了


【Linux】动静态库_第三方库_46

此时mytest可以正常执行了

但是环境变量只在本次登录有效,若退出再进入,则环境变量还是找不到

方法2 ——建立软链接

【Linux】动静态库_第三方库_47

在系统默认的路径下,建立一个软链接指向库


【Linux】动静态库_第三方库_48

此时软链接指向这个库


【Linux】动静态库_第三方库_49

查看第三方库时,libmymath.so有自己的第三方库


【Linux】动静态库_第三方库_50

软链接是一个文件,所以即便关闭xshell,再次打开也能正常运行mytest 可执行程序

方法3——配置文件方案

【Linux】动静态库_动态库_51

使用 ldd 找不到 libmymath对应的第三方库


在系统当中存在配置文件ld代表链接库so代表动态库conf代表配置文件

【Linux】动静态库_头文件_52

创建一个配置文件,并命名为look


输入 ls /etc/ld.so.conf.d/ 指令

【Linux】动静态库_第三方库_53

查看系统的配置文件,就发现多了一个look的配置文件


【Linux】动静态库_动态库_54

由于动态库存放在otherperosn目录下的lib中, 所以进入lib目录中,显示当前库的路径,将其复制


【Linux】动静态库_动态库_55

使用vim进入自己创建的配置文件中,并把 上述复制好的库的路径粘贴到里面


【Linux】动静态库_第三方库_56

输入 ldd mytest 指令,发现还是找不到第三方库


【Linux】动静态库_动态库_57

查看自己的配置文件时,已经有了对应的库的路径 还需让其生效


输入 sudo ldconfig 指令

【Linux】动静态库_头文件_58

就会让系统加载新的配置文件


【Linux】动静态库_第三方库_59

即可正常运行程序