内容回顾
- 静态库是指后缀为.a的库文件,windows下为.lib
- 动态库是指后缀为.so的库文件,windows下为.dll
使用
当一个文件要使用静态库的时候,它需要将它想使用的静态库的部分内容拷贝进自己的文件,然后再执行自己的程序。
当一个文件要使用动态库的时候,当它执行到库函数时,会跳转到动态库中,找到该函数的.o文件,去链接标准库中库函数的.o文件,最后再跳转回来。
正是因为两种库的差距,所以一般使用动态库的文件占用空间会比静态库小。
静态库
如何制作静态库
如果我们想自己写一个静态库,该怎么做?
我们知道,对于任何一个库,都至少包含了一个头文件。这个头文件的作用是提供库的使用方法(相当于使用说明书)。而真实的库文件,是二进制代码,库的作者可以选择不公开,只提供使用,不让库的使用者看到具体的代码。
准备工作
如果我们要创建一个静态库,首先需要一个头文件。
下一步是要写对应的方法。
此时,我们已经具备制作一个库的全部条件了(准备好配菜了),接下来就是进行具体的制作(进厨房加工)。
处理
想要将一个文件变成可执行程序,需要做的是:预处理,编译,汇编,链接。
而这里,我们首先需要将源文件打包成一个二进制文件,也就是.o文件。
我们执行红色框中的指令,最后可以得到黄色框中的.o文件。
注意白色框,可以看到,我们所做的一切都是在mylib目录下的。我们在这个目录下制作了一个库。
如何使用静态库
此时我创建了一个classmate的目录,目的是模拟别人使用库的情况。
此时可以看到这个classmate目录里什么都没有。
此时,我们把别人目录下的.o和.h文件都拿过来了。相当于把我需要的都拿过来了。
.h用于告诉我库的使用方法。
.o是库的具体实现方案。
这一步就是编写程序,并且使用别人的库
多个静态库文件一起打包
如果我今天写了很多个静态库文件,该如何打包?
- 指令 ar -rc libname.a 待打包的库文件.o
- 作用:将所有待打包的库文件制作成静态库
1.创建源文件![](https://img-blog.csdnimg.cn/direct/32e3f6c6a03c4be6bfd5195cc2be616f.png)
上面这一系列操作表示我写了两个头文件和源文件,并且,将这两个文件都制作成.o文件了。
接下来,我将使用ar指令将这些.o文件打包制作成一个静态库。
2.将.o文件生成静态库
接下来将我们的静态库打包给别人用,可以使用makefile一步到位
这一步的意义是:
- make指令,一步将所有的.c源文件编译成.o文件,并且制作成静态库
- make ouput执行,一步创建三个目录,分别是总的目录myliba和myliba下的两个子目录include和lib。并将,h文件都放在include目录下,将.a文件都放在lib目录下。
效果:
3.将静态库压缩打包
- tar指令:tar czf 打包文件.tgz 被打包的文件
- 作用:用于打包压缩
- czf表示:c--打包, z--压缩, f--指定打包后的文件名
使用打包好的静态库
这里的将myliba.tgz从其他地方拿过来和解压缩,就像是从网上下载库一样。
写好test.c文件,准备使用库
make的时候报错,说找不到头文件。
明明已经弄好库了,怎么可能找不到呢? --就在下面,myliba里面
方法1:直接将第三方库安装在系统的默认路径下
这种方法类似于我们安装软件,使用gcc的时候,它会自动去系统默认路径下搜索所需要的头文件和库文件,也就是C语言标准库所在的路径。
- 头文件默认搜索路径:/usr/include;
- 库文件默认搜索路径:/usr/lib64;
因此,我们只需要将头文件和库文件安装到系统默认的路径下就行了。
到usr/include目录下就可以看到我们的.h文件了
同时,在usr/lib64目录下也能看到我们的静态库了
接下来直接像使用以前的静态库一样使用我们的静态库就行了。
直接make之后报错说找不到Add。这是因为,gcc不知道要链接默认路径库里的哪个库(找不到使用接口的定义 -- 代表是库出问题了)。
我们需要告诉编译器使用的库的名字是什么就行了。
指令:gcc -o test test.c -lmylib
mylib是libmylib.a掐头去尾的结果,也是库真实的名字。
涉及一个问题:为什么我们使用stdio这样的库的时候,gcc时就不需要加上-l呢?
---- 因为那不是第三方库,是官方提供的库,系统能够默认认识,所以不需要特别指明。
方法2:告诉编译器就头文件路径,库路径,库名
但是,我们所写的第三方库并没有经过验证,如果直接放到系统的默认路径下,很可能导致污染系统的其他库和头文件。所以,我们可以采用第二种方式:
自己指定
也可以将上述指令写入makefile,这样就不用每次都这么繁琐了。
动态库
如何制作动态库
拥有前面的基础,这里就直接使用makefile文件一键生成
这是目前所拥有的源文件和头文件,直接生成.o文件制作成动态库
使用指令之后得到如下结果:
接下来,打包动态库,将动态库压缩,就可以拿给别人用了。
如何使用动态库
此时我作为使用者,将别人的mylibso.tgz下载到我的目录下了。我该如何使用呢?
使用方法有四种。下面分别讲解
1.安装到默认路径(永久)
像静态库一样,直接将文件解压缩,安装到系统gcc执行的默认路径
头文件:usr/include
库文件:usr/lib64
2.将库文件路径放在环境变量里(暂时)
这一步是将我们的文件和库文件进行链接。
可以看到,我们链接的步骤是正确的,并没有报错。
生成的文件是这样的:
接下来我们直接运行文件:
出现报错:显示找不到动态库
这里需要说明,为什么静态库进行到上一步可以直接运行,而动态库却不行?显示找不到动态库?
因为如果使用静态库,是将内容直接拷贝到文件中
如果使用动态库,是将内容链接到文件中
所以我们之前所做的 gcc -o test test.c -I ……是在告诉gcc编译器,我们需要链接哪个文件,但是,编译完成之后就和gcc没有关系了。真正运行程序的时候就是要操作系统去动态库中找我们用到的内容。
但是,我们并没有告诉操作系统,我们的动态库在哪里,所以找不到。
告诉操作系统动态库在哪里:
在执行程序的时候,操作系统会从环境变量LD_LIBRARY_PATH中读取动态库的路径。
所以,我们只需要将动态库的路径放入到LD_LIBRAY_PATH中就行了。
3.将库文件路径放在配置文件中(永久)
/etc/ld.so.conf.d/路径下有很多的配置文件
创建一个文件,文件名随意,但是后缀必须是conf。
最后将动态库的路径放到这个.conf文件中
sudo ldconfig -- 更新配置文件
4.软链接到系统默认搜索路径中
系统中装库的路径是usr/lib64
所以我们只需要将我们的动态库软链接到usr/lib64中,就可以直接使用了。
用ldd也可以看到test配置了动态链接