文章目录
一、通过gcc生成静态库和动态库
(一)创建生成例子程序
首先创建对应的test1目标目录,使用vim生成序 hello.h、hello.c 和 main.c文件
生成test1目录并跳转到该目录下
程序hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif //HELLO_H
程序hello.c
#include <stdio.h>
void hello(const char *name)
{
printf("Hello %s!\n", name);
}
程序main.c
#include "hello.h"
int main()
{
hello("everyone");
return 0;
}
(二)静态库
1.将 hello.c 编译成.o 文件
无论是静态库还是动态库都是由.o文件创建,所以我们需要先使用gcc将hello.c编译成.o文件
生成hello.o命令:
gcc -c hello.c
查看是否生成成功
可以看到该目录下已经生成了hello.o文件
2.用生成的.o文件创建静态库
静态库的命名规范是使用lib为前缀,后面跟静态库名称,扩展名为.a。所以将本次的静态库名称命名为libhello.a
使用ar命令创建我们的libhello.a静态库文件
ar -crv libhello.a hello.a
使用ls命令查看是否生成成功
可以看到libhello.a生成成功
3.在程序中使用静态库
如何使用静态库内部函数?只需要在使用到这些公用函数的源程序中包 含这些公用函数的原型声明,在gcc生成目标文件时指明对应的静态库,gcc 将会从 静态库中将公用函数连接到目标文件中
main.c 中,我们包含了静态库的头文件 hello.h,然后在主程序 main 中直接调用 公用函数 hello,生成hello文件然后运行查看结果
方法一:
将 -L. 放在main.c和-lhello之间,注意不能将 -L. 放在-lhello后
gcc -o hello main.c -L. -lhello
解释:
L. 表示要连接的库在当前目录中;(多个库:在编译命令行中,将使用的静态库文件放在 源文件后面就可以了。比如: gcc -L/usr/lib myprop.c libtest.a libX11.a libpthread.a -o myprop 其中-L/usr/lib 指定库文件的查找路径。编译器默认在当前目录下先查找指定的库文件
查看结果:
方法二:
gcc main.c libhello.a -o hello
方法三:
先生成main.o文件
gcc -c main.c
在生成可执行文件
gcc -o hello hello.o libhello.a
(二)动态库
1.用生成的.o文件创建动态库
动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀 lib,但其 文件扩展名为.so,例如我们要创建的动态库名为hello,则动态库文件名为libhello.so
使用gcc命令创建动态库文件
gcc -shared -fPIC -o libhello.so hello.o
解释:
-shared 该选项指定生成动态连接库(让连接器生成 T 类型的导出符号表,有时候也生成 弱连接 W 类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件。
-fPIC 表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载 入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
使用ls查看是否生成成功
可以看到libhello.so生成成功
2.在程序中使用动态库
程序中使用动态库和使用静态库完全一样,但是需要注意的是程序运行时调用动态库是在/usr/lib目录下寻找的,所以我们需要将动态库文件复制到目录/usr/lib下:
在管理员权限下用mv命令将libhello.so复制到/usr/lib目录下
sudo mv libhello.so /usr/lib
再cd到该目录下查看是否含有该文件
可以看到已经将libhello.so复制到/usr/lib下
我们再使用gcc命令链接hello动态库重新生成hello1可执行文件
gcc -o hello1 main.c -L. -lhello
查看结果
可以看到hello1可执行文件成功生成并运行
(三)思考
静态库和使用动态库编译成目标程序使用的 gcc 命令完全一样, 那当静态库和动态库同名时,gcc 命令会使用哪个库文件呢?
我们为了测试将生成的执行文件和usr/lib目录下的动态库删除重新移动到当前test1目录下,由于动态库文件没有在/usr/lib目录下,如果重新生成hello可执行文件,如果提示错误那么就是优先调用动态库,反之就是优先调用静态库。
首先使用rm命令删除可执行文件
再cd到目录/usr/lib下将libhello.so移动回test1目录下
可以看到相关文件都已经准备好了,接下来使用gcc命令创建可执行文件
gcc -o hello main.c -L. -lhello
运行hello文件
可以看到发生错误,没有连接到到对应的库,所以可以认为当静态库和动态库名称一样时优先调用动态库
(四)实例使用静态库
经过上面讲解,让我们重新创建一个例子熟悉一下静态库的创建和使用吧!
具体要求:
创建一个x2x函数,x2y函数以及main函数,将这3个函数分别写成单独的3个 .c文件,并用gcc分别编译为3个.o 目标文件;将x2x、x2y目标文件用 ar工具生成1个 .a 静态库文件, 然后用 gcc将 main函数的目标文件与此静态库文件进行链接,生成最终的可执行程序,记录文件的大小。
首先创建对应文件
x2x.c
#include <stdio.h>
int x2x(int x)
{
return x*x;
}
x2y.c
#include <stdio.h>
int x2y(int x,int y)
{
return x*y;
}
x2x.h
#ifndef X2X_H
#define X2X_H
int x2x(int x);
#endif
x2y.h
#ifndef X2Y_H
#define X2Y_H
int x2y(int x,int y);
#endif
main.c
#include <stdio.h>
#include "x2x.h"
#include "x2y.h"
void main()
{
int x,y;
printf("Please input the value of x:");
scanf("%d",&x);
printf("Please input the value of y:");
scanf("%d",&y);
printf("x*x=%d\n",x2x(x));
printf("x*y=%d\n",x2y(x,y));
}
用gcc分别编译为3个.o 目标文件
gcc -c main.c x2x.c x2y.c
相关.o文件生成成功
接下来使用ar命令生成静态库
ar crv libmultip.a x2x.o x2y.o
连接静态库生成可执行文件
gcc -o multip1 main.c -L. -lmultip
使用命令ls查看可执行文件大小
ls -lh multip1
可以看到文件大小为7.4k
(五)实例使用动态库
利用上面生成的.o文件创建一个动态库
gcc -shared -fPIC -o libmultip.so x2x.o x2y.o
利用动态库创建可执行文件
gcc main.c libmultip.so -o multip2
可以看到动态库生成可执行文件为7492B而静态库生成的可执行文件为7528B;动态库.so文件大小为6888B,静态库.a文件大小为1936B。
所以可以得出结论:
通过比较发现静态库要比动态库要小很多,生成的可执行文件大小也存在较小的差别。