目录
1. 了解动静态库
1. ldd 命令的使用
2. C语言库与C++语言库
3. 库的分类
4. 库的命名
5. 库的内容
2. 静态库的制作和使用
1. 静态库的制作
2. 静态库的使用
3.动态库的制作和使用
1. 动态库的制作
2. 动态库的使用
Linux🌷
1. 了解动静态库
1. ldd 命令的使用
我们使用C语言编写了一个test1.c的源程序,将test1.c进行编译生成test1的目标文件;
使用 ldd 可执行文件名 命令查看该可执行程序依赖的动态库;
进而我们对依赖的库进行了查看,发现该库其实是一个软链接,链接的文件是一个可执行文件;
因此我们便可以得出结论:
库在Linux中也是一个文件。
2. C语言库与C++语言库
我们使用C语言编写了test1.c文件,查看编译生成的目标文件test1依赖的库如下所示:
使用C++编写了一个test2.cc文件,查看编译生成的目标文件test2依赖的库如下所示:
在这里要提一下:
在Linux中,后缀为 .cc .cpp .cxx 都表示C++文件。
3. 库的分类
一般库分为两种:动态库 和 静态库;
在Linux中:
- 如果是动态库:库文件是以 .so 作为后缀的;
- 如果是静态库:库文件是以 .a 作为后缀的。
我们平常使用 gcc -o 目标文件名 待编译的文件名 编译是默认以动态方式链接的;
若想以静态方式链接则使用如下命令: gcc -o 目标文件名 待编译的文件名 -static
我们使用的服务器一般没有内置语言的静态库,只有动态库,需要yum安装C/C++静态库。
sudo yum install glibc-static
sudo yum install libstdc++-static
我们对test1.c文件分别进行了动态和静态编译;
经过查看发现静态生成的可执行文件大小大于动态生成的可执行文件
我们便可以在这里说一下动静态编译生成目标文件的区别:
静态编译:将库里对应的模块拷贝至目标文件,此后运行不再依赖库,可移植性好;
动态编译:程序在运行的时候才去链接动态库的代码,多个程序共享使用库里的代码,此后运行还
要依赖库,可移植性差;
在这里要提一下:
Linux中一些命令也是依赖动态库的,若删掉动态库,则这些命令也无法执行,你的shell就可能会
崩溃;
我们还可以使用 file 命令查看可执行文件的类型:
4. 库的命名
动态库:lib库名.so[其他内容]
静态库:lib库名.a[其他内容]
注意:
库的真正名字为:上述中的库名
5. 库的内容
我们试着打开上述标准的C语言库,发现是二进制的:
库其实就是封装好的一些函数的声明及实现的集合,供用户调用。
其实一套完整的库包含三个内容:
1. 头文件(里面写函数声明);
2. 库文件本身(里面是函数实现);
3. 说明文档;
头文件:是 .c .cc 文件(不对其进行编译,使用语言写出来的文件,说明库中暴露出来的方法
的基本使用!)
库文件本身:是编译生成的 .o 的二进制文件的打包(隐私函数的具体实现)
如果有别人想使用你的函数,你便可以制作一个动态或静态库给他~
2. 静态库的制作和使用
1. 静态库的制作
目标:制作一个能进行加法和减法的库;
1. 我们使用声明和定义相分离的方式写了四个代码:
具体内容如下:
2. 对书写函数实现的 .c 文件进行编译生成 .o 文件;
3. 打包生成的 .o 文件;
ar -rc [生成的.a文件名] [要打包的.o文件名]
//ar是gnu归档工具,rc表示(replace and create)
4. 查看打包好的 .a 文件;
ar -tv [生成的.a文件名]
//t:列出静态库中的文件
//v:显示详细信息
5. 静态库
静态库便是刚才打包 .a 文件和函数声明 .h 文件的集合
my_math_lib便可称为一个静态库。
2. 静态库的使用
目标:如下所示,我们想要利用生成的库编译test.c文件
1. test.c 文件内容如下:
2. 编译test.c文件
gcc [待编译的.c文件] -I[头文件搜索路径] -L[库文件的搜索路径] -l[要链接库名]
注意:
第一个 -I
是因为:编译器并不会查找你同级目录下目录中有啥, 因此必须要带-I;
第三个 -l 中的库名必须是去掉 lib开头 和 .a/.so 结尾的中间部分。
静态库的制作和使用就到此结束,此后便可以直接将包含静态库和.h的目录丢给别人,别人便可以
使用库中的函数。
不光静态库可以制作,动态库也可以。
3.动态库的制作和使用
1. 动态库的制作
目标:制作一个能进行加法和减法的库;
1. 我们使用声明和定义相分离的方式写了四个代码:
具体内容如下:
上述从静态库的制作中拷过来的!!!😁
2. 对书写函数实现的 .c 文件进行编译生成 .o 文件;
gcc -fPIC -c [要编译的.c文件]
与静态库的制作不同,动态库的编译时要加 -fPIC :产生位置无关码;
3. 打包生成的 .o 文件;
gcc -shared -o [将形成的动态库名] [编译生成的.o文件]
4. 动态库
动态库便是刚才打包 .so 文件和函数声明 .h 文件的集合
test便为可以使用动态库。
2. 动态库的使用
目标:如下所示,我们想要利用生成的库编译test.c文件
1. test.c 文件内容如下:
2. 编译test.c文件
gcc [待编译的.c文件] -I[头文件搜索路径] -L[库文件的搜索路径] -l[要链接库名]
编译与静态库都一样,但在运行前还有一步工作;
3. 导环境变量
export LD_LIBRARY_PATH=动态库的路径 #导入环境变量
为什么要导入环境变量?
在上述编译时,我们指明了库的.h所在及库的文件所在,所以编译不会报错;
运行的时候加载器还是不知道它们在哪儿,因此导入变量告诉加载器动态库的位置;
注意:这个环境变量只在本次会话有效;
告诉加载器动态库位置的方法有多种,但上述方法是最为推荐的!!
如果想知道其他方法,请看下方博客!!!
https://blog.csdn.net/qq_54851255/article/details/125807460?spm=1001.2014.3001.5502
总结:
如果只提供静态库,我们只能将我们的库,静态链接到我们的程序中—>静态使用;
如果只提供动态库,我们只能将我们的库,采用动态链接到我们的程序中—>动态使用;
我们在Linux中使用gcc编译器默认是采用动态连接的,但若在后面加-static则采用静态链接,
本质上是提供了两种版本的库,加上-static只是区分静态或动态链接的方式罢了,不是因为只有动
态库加上-static后就能静态链接的!!!
坚持打卡!😃