使用gcc制作静态库和共享库

在linux中,静态库以.a结尾,动态库以.so结尾。
在windows中,静态库以.lib结尾,动态库以.dll结尾

库文件的作用是什么?
如果只想把功能提供给别人,而不想别人看到源代码,那么就需要把源代码制作成库文件提供给对方。

只需要使用头文件,然后调用函数接口
静态库的文件名:libxxx.a —> windows的 .lib文件。
制作步骤:两步
①把.c的文件变成.o的文件
②对这些.o文件打包在一起。(ar rcs libmycalc.a file1.o file2.o file3.o …)

4个文件add.c,sub.c,mul.c,div.c四个文件。和head.h.

源码

head.h内容为

/*************************************************************************
	> File Name: head.c
	> Author: 
	> Mail: 
	> Created Time: 2020年06月19日 星期五 19时26分44秒
 ************************************************************************/

#include<stdio.h>
int add(int a,int b);
int sub(int a,int b);
int mul(int a,int b);
int div(int a,int b);

4个.c文件的内容为

acat@acat-xx:mycode2$ cat *.c
/*************************************************************************
	> File Name: add.c
	> Author: 
	> Mail: 
	> Created Time: 2020年06月19日 星期五 19时21分44秒
 ************************************************************************/

#include "head.h"

int add(int a,int b)
{
    int result = a + b;
    return result;
}
/*************************************************************************
	> File Name: add.c
	> Author: 
	> Mail: 
	> Created Time: 2020年06月19日 星期五 19时21分44秒
 ************************************************************************/

#include "head.h"

int div(int a,int b)
{
    int result = a / b;
    return result;
}
/*************************************************************************
	> File Name: add.c
	> Author: 
	> Mail: 
	> Created Time: 2020年06月19日 星期五 19时21分44秒
 ************************************************************************/

#include "head.h"

int mul(int a,int b)
{
    int result = a * b;
    return result;
}
/*************************************************************************
	> File Name: add.c
	> Author: 
	> Mail: 
	> Created Time: 2020年06月19日 星期五 19时21分44秒
 ************************************************************************/

#include "head.h"

int sub(int a,int b)
{
    int result = a - b;
    return result;
}

编译

acat@acat-xx:mycode2$ ls
add.c add.o div.c include mul.c sub.c
acat@acat-xx:mycode2$ gcc -c add.c -I ./include/
acat@acat-xx:mycode2$ ls
add.c add.o div.c include mul.c sub.c
acat@acat-xx:mycode2$ gcc -c *.c -I ./include/
acat@acat-xx:mycode2$ ls
add.c add.o div.c div.o include mul.c mul.o sub.c sub.o
acat@acat-xx:mycode2$ ls -lrt
总用量 36
-rw-r–r-- 1 acat acat 341 6月 19 19:22 div.c
-rw-r–r-- 1 acat acat 341 6月 19 19:23 mul.c
-rw-r–r-- 1 acat acat 341 6月 19 19:23 sub.c
-rw-r–r-- 1 acat acat 341 6月 19 19:24 add.c
drwxr-xr-x 2 acat acat 4096 6月 19 19:27 include
-rw-r–r-- 1 acat acat 1240 6月 19 19:29 add.o
-rw-r–r-- 1 acat acat 1240 6月 19 19:29 div.o
-rw-r–r-- 1 acat acat 1240 6月 19 19:29 mul.o
-rw-r–r-- 1 acat acat 1240 6月 19 19:29 sub.o
acat@acat-xx:mycode2$ ar rcs libcalc.a *.o
acat@acat-xx:mycode2$ ls -lrt
总用量 44
-rw-r–r-- 1 acat acat 341 6月 19 19:22 div.c
-rw-r–r-- 1 acat acat 341 6月 19 19:23 mul.c
-rw-r–r-- 1 acat acat 341 6月 19 19:23 sub.c
-rw-r–r-- 1 acat acat 341 6月 19 19:24 add.c
drwxr-xr-x 2 acat acat 4096 6月 19 19:27 include
-rw-r–r-- 1 acat acat 1240 6月 19 19:29 add.o
-rw-r–r-- 1 acat acat 1240 6月 19 19:29 div.o
-rw-r–r-- 1 acat acat 1240 6月 19 19:29 mul.o
-rw-r–r-- 1 acat acat 1240 6月 19 19:29 sub.o
-rw-r–r-- 1 acat acat 5304 6月 19 19:30 libcalc.a

acat@acat-xx:mycode2$ nm libcalc.a

add.o:
0000000000000000 T add

div.o:
0000000000000000 T div

acat@acat-xx:mycode2$ bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty’.
1240 * 4
4960

发布

发布的时候需要发布头文件和库文件,即.h文件和.a文件。
在这里插入图片描述
main.c内容为

/*************************************************************************
	> File Name: main.c
	> Author: 
	> Mail: 
	> Created Time: 2020年06月19日 星期五 19时50分36秒
 ************************************************************************/

#include "head.h"
int main()
{
    int a = add(3,5);
    printf("a=%d\n",a);
    return 0;
}

在这里插入图片描述
使用gcc -o main main.c直接编译报错,找不到head.h文件。需要使用-I指定.h文件所在的文件夹。
在这里插入图片描述
然后使用gcc -o main main.c -I ./include/ 命令仍然报错,这是因为通过head.h文件找到了函数接口,但是没有找到函数的实现(函数的实现在我们编译的静态库libcalc.a文件当中)。
在这里插入图片描述
使用gcc -o main main.c -I ./include/ -L ./lib/ -lcalc命令成功编译。-L参数指明库文件所在的文件夹,-l参数指明对应的库文件(libcalc.a)。选取lib和.a之间的字符串,即calc作为-l参数的输入
在这里插入图片描述
此后,可以成功运行编译生成的main可执行文件。
在这里插入图片描述

制作动态库

代码的位置无关性。
在这里插入图片描述
静态库是直接把代码放在了代码段(上图中对应text区域)了。在编译的时候,静态库中的代码会和主体代码融合成一个完整的整体。而共享库不是。
在这里插入图片描述
动态库是使用的时候临时加载进来,用完了之后就不用了。(与位置无关)。如何编译与位置无关的代码,使用-fPIC这个关键参数。
①编译与位置无关的.o文件。即把刚刚编译静态库用到的.o文件删除,然后使用-fPIC参数编译与位置无关的.o文件。

在这里插入图片描述
gcc -c -fPIC *.c -I ./include/
在这里插入图片描述
②将上一步生成的.o文件打包,使用的是-shared选项。
gcc -o libCalc.so -shared *.o
在这里插入图片描述
将生成的libCalc.so移动到lib目录下。
在这里插入图片描述
使用gcc -o new_main -I ./include/ -L ./lib/ -lCalc命令进行编译。生成可执行文件:new_main
在这里插入图片描述
通过上图可以看出,直接调用可执行文件,会执行失败。
使用ldd命令进行查看:
在这里插入图片描述
发现libCalc.so => not fount.
找不到。
为什么编译成功了,但是运行失败了?
因为编译的时候我们使用-L指明了库的位置,使用-l指明了库名。但是可执行文件new_main运行的时候仍然需要进行寻找,这时就找不到了。要么找系统默认的库路径,要么找咱么指定的库路径。
所以,解决办法是把刚刚生成的.so动态库文件放入到/lib目录,或者放入到/usr/lib目录下。这时最直接后者暴力的方法。也可以使用建立软链接的方式。如下:
要使用绝对路径:
sudo ln -s ~/test/mycode2/lib/libCalc.so /lib/libCalc.so
在这里插入图片描述
再次使用ldd命令查看:
在这里插入图片描述
这次就可以执行了:
在这里插入图片描述
但是这种方式仍然不推荐,因为放在/lib目录下容易和别人的库文件名冲突。
法二:使用LD_LIBRARY_PATH

acat@acat-xx:mycode2$ export LD_LIBRARY_PATH=/home/acat/test/mycode2/lib/:$LD_LIBRARY_PATH

这种方式也不是特别推荐。因为通过export设置的环境变量,在中断退出的时候设置的环境变量就会失效。当然也可以写在.bashrc中,这样在中断退出的时候不会失效。但是一般使用下面的法三来设置。
法三:
在这里插入图片描述
在/etc/目录下创建文件:ld.so.conf

acat@acat-xx:mycode2$ sudo vi /etc/ld.so.conf

添加如下内容:

include /etc/ld.so.conf.d/*.conf
/home/acat/test/mycode2/lib

然后,让其生效,使用ldconfig命令,-v显示过程

acat@acat-xx:mycode2$ sudo ldconfig -v

即可。


动态库和静态库的对比

使用静态库的主程序相对于使用动态库的主程序,执行速度更快,因为使用动态库的主程序需要在调用动态库中函数的时候进行寻址。

一般静态库变更的时候,需要重新编译主程序。但是动态库变更的时候,一般不需要变更主程序(在动态库对应的头文件中的接口变更(如添加或者删除了函数,函数的参数个数的改变等)的时需要重新编译主程序)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值