欢迎来到小林的博客!!
️博客主页:✈️林 子
️博客专栏:✈️ Linux
️社区 :✈️ 进步学堂
️欢迎关注:点赞收藏✍️留言
- 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静 态库
- 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
- 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文 件的整个机器码
- 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个 过程称为动态链接(dynamic linking)
- 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚 拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。
生成静态库,我们只需要把要打包的.o目标文件打包在一起生成静态库即可。
首先,我们要先有4几个.c和.h的文件。
add.c
#include "add.h"
int add(int x,int y)
{
return x+y;
}
add.h
int add(int x,int y);
sub.c
#include"sub.h"
int sub(int x,int y)
{
return x- y;
}
sub.h
int sub(int x,int y);
然后我们编写一个Makefile自动化构建工具。
libmymath.a:sub.o add.o
ar -rc $@ $^
%.o:%.c
gcc -c $<
.PHONY:clean
clean:
rm -rf libmymath.a *.o output
.PHONY:output
output:
mkdir output
cp *.h output
cp libmymath.a output
libmymath.a:sub.o add.o
:libmymath.a 这个静态库是依赖于sub.o,add.o。
ar -rc $@ $^
:生成静态库。
%.o:%.c
:当前目录下所有的.o文件都依赖于.c文件。
gcc -c $<
: 生成所有可生成的.o文件。
.PHONY:clean
: 清除所有生成的文件。
.PHONY:output
:把.h和静态库打包进一个文件夹。
然后我们make一下,就可以生成静态库了。
我们会发现,先生成.o文件,再通过.o目标文件打包成静态库libmymath.a。
然后我们使用output,把头文件和静态库打包进同一个文件夹。并且进入output文件夹。
要使用静态库,我们要先有一个主函数。我们创建一个test.c的主文件。
#include
#include"add.h"
#include"sub.h"
int main()
{
int x = 10;
int y = 20;
int r1 = add(x,y);
int r2 = sub(x,y);
printf("%d + %d = %d",x,y,r1);
printf("%d - %d = %d",x,y,r2);
return 0;
}
那么我们还需要编译这个test.c文件,我们需要在编译的时候。指定它的库路径,和库名。
gcc test.c -L. -lmymath
编译
-L
要链接的静态库路径,.为当前路径
-l
要链接的静态库名,静态库名不包含开头的lib和结尾的.a/.so
编译完之后会生成一个可执行文件。
执行结果。
这里忘记换行了。但不影响。
生成动态库就简单多了。我们还是使用Makefile来自动化生成。
libmymath.so:add.o sub.o #libmymath.so 依赖于add.o sub.o
gcc -shared -o $@ $^
#产生.o目标文件,程序内部的地址方案是: 与位置无关,库文件可以在内存的任何位置加载,而且不影响和其他程序的关联性
%.o:%.c
gcc -fPIC -c $<
.PHONY:clean
clean:
rm -r -f libmymath.so *.o lib
.PHONY:output
output:
mkdir lib
cp *.h lib
cp libmymath.so lib
- shared: 表示生成共享库格式
- fPIC:产生位置无关码(position independent code)
- 库名规则:libxxx.so
这样我们就生成了.so的动态库。
然后我们output打包一下。
和刚才一样,我们创建一个.c的主文件。
test.c:
#include
#include"add.h"
#include"sub.h"
int main()
{
int x = 10;
int y = 20;
int r1 = add(x,y);
int r2 = sub(x,y);
printf("%d + %d = %d",x,y,r1);
printf("%d - %d = %d",x,y,r2);
return 0;
}
然后我们使用makefile来生成自动化编译。
makefile:
test:test.c
gcc -o $@ $^ -I. -L. -lmymath
.PHONY:clean
clean:
rm -f test
然后编译,执行。
这是在同一目录下可以直接执行,如果在不同目录下。则会报错。
与动态库不再同一目录
此时我的动态库在lib目录下,源文件与lib在同一目录下。这时我们要稍微修改一下Makefile。
test:test.c
gcc -o $@ $^ -I./lib -L./lib -lmymath
.PHONY:clean
clean:
rm -f test
然后编译
提示我们编译失败,这是因为不在同一目录下。加载器无法找到动态库并把它加载到内存,这时候我们把动态库添加进环境变量即可。
格式:
export LD_LIBRARY_PATH= lib文件目录