Linux系统下创建并使用动静态库

假设要通过printf函数打印“hello,world”,程序开始运行后,经过预处理、编译、汇编等过程,在链接阶段需要调用printf函数,那么就会去C语言库里找printf函数

一般库分为两种:动态库(.so) 和 静态库(.a)

链接时,如果是去动态库里找,这种找函数的方式就是动态链接;如果是去动态库里找,这种找函数的方式就是静态链接


目录

一、认识动静态库

1、静态库

(1) 什么是静态库?

(2) 静态库的命名

2、动态库

(1)什么是动态库? 

(2) 动态库的命名

二、创建动静态库

1、为什么要创建库?

2、创建静态库文件

 3、打包成一个完整的库

4、使用创建好的库

 三、创建动态库

1、创建动态库文件

 2、使用动态库


一、认识动静态库

1、静态库

(1) 什么是静态库?

在编译链接阶段,会把要用到的库文件加入到可执行文件中,在链接阶段就不需要去找可执行文件外部的库文件了

正是因为如此,这个时候的可执行文件会比较大

(2) 静态库的命名

动态库:库文件以 .a作为后缀

动态库的基本命名:libxxx.a

2、动态库

(1)什么是动态库? 

动态库是我们最常用的一种方式,在编译链接时不会把要用到的库文件代码加入到可执行文件中,而是在链接阶段需要用到的时候,再链接库文件来加载库

(2) 动态库的命名

动态库:库文件以 .so作为后缀

动态库的基本命名:libxxx.so

ldd 可执行文件名            #查看当前可执行程序依赖的动态库
                          #前提是当前可执行程序是以动态链接的方式编译的
file 可执行文件名           #查看当前可执行文件的链接方式

二、创建动静态库

一个完整的库包含 库文件本身头文件说明文档,现在我们仅需要关注前两者

制作动静态库的本质:就是将所有的.o文件打包。——》使用ar或者gcc打包

1、为什么要创建库?

我们希望把我们写好的代码给别人用,但是不希望别人看到源码,所以我们可以创建一个动/静态库,相当于给了别人.o文件,以及提供说明的.h文件

因为在连接时,可执行文件连接的是.o文件,如果有多个.o文件,我们可以把这些文件打包成一个.a 或者 .so文件,这些 .a或 .so文件就是库文件!!

静/动态库 《—— .o 文件 《—— .o文件较多,打包成一个文件

2、创建静态库文件

现在我们已经在一个目录下创建好了要打包成库的文件

 然后我们编写Makefile文件来编译形成 .o文件,并将其打包,打包使用下面这条指令

#-rc 表示replace/create,如果有这个文件就替换,没有就创建一个
ar -rc 目标文件 依赖文件

ar -tv 打包好的静态库           #查看打包好的静态库

 3、打包成一个完整的库

上面我们将.o文件打包成了一个静态库文件,但这不是一个完整的库,一个完整的库包含库文件、头文件、说明文档(暂不考虑)

我们需要在Makefile中再加一点东西,包含的内容如下:

 纠正一下:-f改为 -rf,output是目录,删除目录要递归删除

我们只要输入make output就能快速打包了

4、使用创建好的库

=======================准备工作=======================

现在库有了,那么该如何使用这个库呢??我们新建一个目录来单独测试

 =======================开始测试=======================

我们输入编译指令 gcc -o test test.c,但是编译器似乎没有找到头文件sub.h

这是因为,编译器会去自己默认的库路径下找头文件,所以我们这里需要指明头文件的路径,此时需要添加附加选项

-I头文件的路径 -L库文件路径 -l真实的库文件名

注意:
#-l 是小写的 L
#真实的库文件名是去掉前缀lib 和 后缀.a以后剩下的,即mymath

(1)  在test.c中指明了要使用头文件sub.h,所以这里我们只需要给出头文件的路径即可

(2)  test.c既没有指明库文件的路径,也没有指明要用哪个库文件,所以我们需要自己指明这两样

 这个时候我们就发现,成功生成了test执行文件,因为连接的是静态库,test把静态库拷贝到了自己内部,文件会比较大

=======================放入Makefile中=======================

 三、创建动态库

1、创建动态库文件

在了解静态库的创建以后,了解动态库就方便很多了

但是打包成动态库使用的是gcc指令,而不是 ar,这个需要注意

 2、使用动态库 

使用动态库的时候,和使用静态库又有所不同,我们的库名叫做 lib,路径这里需要更换一下

 然后我们make一下发现能生成 执行文件test

但是运行的时候就出错了,我们再来看看执行文件test链接的 动态库,我们会发现,test执行文件运行的时候没有找到对应的动态库

 =======================原因分析=======================

Makefile里写路径,只是在编译的时候帮助我们找到动态库,但是那个时候,静态库已经把库文件拷贝到自己的可执行文件test里了,但是动态库不会拷贝

所以运行的时候,动态库只是知道自己和这个动态库有关,但是找不到这个动态库

=======================问题解决=======================

在Linux中的环境变量有一个动态库的搜索路径LD_LIBRARY_PATH,一般情况下为空,可执行文件运行时,会去这个环境变量中搜索动态库路径

我们可以向这个环境变量中添加我们的动态库路径

 最后我们打印这个环境变量,发现有路径了,而且可执行文件也连接到这个动态库了。可执行文件也能成功运行了

四、gcc -o 目标文件 依赖文件  -static

这种写法我们在很久之前就见过了,不加-static 表示当前执行文件默认是动态连接,连接的是动态库;加了-static 表示当前执行文件是静态连接,连接的是静态库

如果我们现在只有动态库,但是我们加了 -static

这个时候就会报错,因为现在要静态连接,但是在搜索路径里找不到对应的静态库!!

所以为了保证动态库和静态库都能连接到,我们一般会在我们制作的库里,同时放动态库和静态库


版权声明:本文为challenglistic原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。