Linux下GCC生成静态库和动态库过程详解

一、用GCC生成.a静态库和.so动态库

创建函数库之前,先准备举例所需源程序,并将函数库的源程序编译成.o文件。

1.编辑生成例子程序hello.c,hello.h,main.c

先创建一个作业目录,保存本次练习的文件

#mkdir test1
#cd test1

在这里插入图片描述

然后用vim、nano或gedit等文本编译器编辑生成所需要的3个文件。我这里使用vim编辑器

1.1编辑生成hello.h

vim hello.h

在这里插入图片描述
1.2编辑生成hello.c

vim hello.c

在这里插入图片描述

1.3编辑生成main.c

vim main.c

在这里插入图片描述

2.将hello.c编译成.o文件

gcc -c hello.c
ls

并查看是否生成了hello.o文件
在这里插入图片描述

3.由.o文件创建静态库

静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将创建的静态库名为myhello,则静态库文件名就是libmyhello.a。在创建和使用静态库时,需要注意这点。创建静态库用ar命令。在系统提示符下键入以下命令将创建静态库文件libmyhello.a.

ar -crv libmyhello.a hello.o

并检查是否生成。
在这里插入图片描述

4.在程序中使用静态库

静态库制作完了,使用它内部的函数,只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明静态库名,gcc将会从静态库中将公用函数连接到目标文件中。注意,gcc 会在静态库名前加上前缀lib,然后追加扩展名.a得到的静态库文件名来查找静态库文件。
方法一:

#gcc -o hello main.c -L.-lmyhello

自定义的库时,main.c还可放在-L.和-lmyhello之间,但是不能放在它俩之后,否则会提示myhello没定义,但是是系统的库时,如 g++ -o main (-L/usr/lib)-lpthread main.cpp就不出错。
方法二:

#gcc main.c libmyhello.a -o hello

方法三:
先生成main.o:

gcc -c main.c

再生成可执行文件:

gcc -o hello main.o libmyhello.a

动态库连接时也可以这样做。

#./hello
Hello everyone!

我们删除静态库文件试试公用函数 hello是否真的连接到目标文件hello 中了。

#rm libmyhello.a

rm: remove regular file 'libmyhello.a"? y

#.hello

Hello cveryone!
程序照常运行,静态库中的公用函数已经连接到目标文件中了。
这里我直接采用最快捷的一种:方法二。
在这里插入图片描述

5.由.o文件创建动态库文件

动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其文件扩展名为.so。例如:我们将创建的动态库名为myhello,则动态库文件名就是libmyhello.so。用gcc来创建动态库。
代码如下:

gcc -shared -fPIC -o libmyhello.so hello.o

并用ls命令查看是否创建成功
在这里插入图片描述

6.在程序中使用动态库

先运行gcc命令生成目标文件

gcc main.c libmyhello.so -o hello
./hello

在这里插入图片描述

出现错误,找不到动态库文件libmyhello.so。 程序在运行时,会在/usr/ib和/ib等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述误而终止程序运行。将文件libmyhello.so复制到目录/usr/lib中。

mv libmyhello.so /usr/lib
./hello

在这里插入图片描述

7.当静态库和动态库同名时,gcc优先使用动态库

尝试当静态库和动态库同名时,gcc优先使用那种?

第一步:先删除以上情况下的除hello.c,hello.h,main.c的所有文件

# rm -f hello hello.o /usr/ib/libmyhello.so

第二步:再来创建静态库文件libmyhello.a 和动态库文件

# gcc -c hello.c
# ar -cr libmyhello.a hello.o (或-cvr )
# gcc -shared -fPIC -o libmyhello.so hello.o

在这里插入图片描述
运行gcc命令来使用函数库myhello生成目标文件 hello,并运行程序hello。通过上述最后一条ls命令,可以发现静态库文件libmyhello.a和动态库文件libmyhello.so都已经生成,并都在当前目录中。

第三步:运行gcc命令来使用函数库myhello生成目标文hello,并运行程序hello。

gcc -o hello main.c -L. -lmyhello

在这里插入图片描述
动态库和静态库同时存在时,优先使用动态库,当然,如果直接#gcc main.c libmyhello.a -o hello的话,就是指定为静态库了)

二、静态库.a与.so文件的生成和使用

1.编辑生成所需的四个文件A1.c、A2.c、A.h、test.c

先创建一个作业目录,保存本次练习的文件

#mkdir test2
#cd test2

1.1编辑生成A1.c
在这里插入图片描述

1.2编辑生成A2.c
在这里插入图片描述

1.3编辑生成A.h
在这里插入图片描述

1.4编辑生成test.c
在这里插入图片描述

2.生成和使用静态.a文件

2.1.生成目标文件(.o)
gcc -fPIC -c A1.c A2.C

2.2.生成静态.a文件
ar -crv libafile.a A1.o A2.o

2.3.使用.a库文件
gcc -o test test.c libafile.a
在这里插入图片描述

3.生成与使用共享库.so文件

3.1.生成目标文件

gcc -c -fpic A1.c A2.c

3.2.输出共享库.so文件

gcc -shared *.o -o libsofile.so

3.3.使用.so库文件,创建可执行文件

gcc -o test test.c libsofile.so
./test

在这里插入图片描述

三、对第一次作业改编

1.扩展x2y

vim sub2.c
vin sub2.h

在这里插入图片描述
在这里插入图片描述

2.gcc分别编译为3个.o 目标文件;

将x2x、x2y目标文件用 ar工具生成1个 .a 静态库文件, 然后用 gcc将 main函数的目标文件与此静态库文件进行链接,生成最终的可执行程序.
在这里插入图片描述
在这里插入图片描述

3.记录文件大小

在这里插入图片描述

四、学习Linux GCC常用命令

示例程序:

//test![在这里插入图片描述](https://img-blog.csdnimg.cn/e65bc952ec444b49bbdae77fb65ba698.png)
.c
#include <stdio.h>
int main (void)
{
printf(“Hello World! \n”);
return 0;
}

在这里插入图片描述

1.简单编译

直接编译,这个程序,一步到位的编译指令是:

gcc test1.c -o test

在这里插入图片描述

实质上,上述编译过程 是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、 编译(Compilation)、汇编(Assembly)和连接(Linking)。

1.1预处理
gcc -E test.c -o tet.i
或gcc -E test.c

在这里插入图片描述

1.2编译为汇编代码
gcc -S test.i -o test.s

在这里插入图片描述

1.3汇编
gcc -c test.s -o test.o

在这里插入图片描述

1.4 连接
gcc test.o -o test

在这里插入图片描述

2.多个程序文件的编译

这里的a1.c文件对应得是前面第一次作业的sub1.c,这里的a2.c文件对应得是前面的main1.c,这里的a3.c文件对应得是前面的sub1.h,
在这里插入图片描述

如果同时处理的文件不止一个,GCC仍然会按照预处理、编译和链接的过程依次进行。如果深究起来,上面这条命令大致相当于依次执行如下三条命令:
gcc -c testl.c -o testi.o
gcc -c test2.c -o test2.o
gcc testl.o test2.o -o test

3.检错

现在test.c文件中设置一个错误
在这里插入图片描述

然后使用检错命令
在这里插入图片描述

4.库文件连接

先将上一步骤对test.c的错误修改修正回来
第一步:编译生成可执行文件
第二步:链接
第三步:强制链接时使用静态链接库
在这里插入图片描述在这里插入图片描述

五、GCC编译器背后的故事

1.准备工作

先创建目录test0,编写一个Hello.c
源代码如下:
在这里插入图片描述

2.编译过程

2.1.预处理

 gcc -E Hello.c -o Hello. i

将源文件hello.c文件预处理生成hello. i
GCC 的选项-E使GCC在进行完预处理后即停止
2.2编译

 gcc -S hello. i -o hello. s

将预处理生成的hello. i文件编译生成汇编程序hello. s2
GCC 的选项-S使GCC在执行完编译后停止,生成汇编程序
2.3.汇编

gcc -c hello.s -o hello. o

将编译生成的hello.s文件汇编生成目标文件hello. o
GCC 的选项-c使GCC在执行完汇编后停止,生成目标文件

2.4.连接

gcc hello.c -o hello

size hello //使用size查看大小
ldd hello //可以看出该可执行文件链接了很多其他动态库,主要是Linux的glibc动态库
在这里插入图片描述

3.分析ELF文件

3.1 ELF文件的段

readelf -S Hello

在这里插入图片描述
3.2反汇编ELF
(1)使用objdump -D 对其进行反汇编如下:

objdump -D Hello

在这里插入图片描述
(2)使用objdump -S 对其进行反汇编并且将其C语言源代码混合显示出来:

gcc -o Hello -g Hello.c
objdump -S Hello

在这里插入图片描述

六、总结

通过本次gcc生成静态库和动态库的练习,熟悉了生成静态库和动态库的基本操作,以及相关概念,收获颇丰。

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值