文章目录
- 简要概念
- 静态库
- 生成
- 使用
- 动态库
- 生成
- 使用
简要概念
库一般分为两种:
- 静态库
- 动态库
在 Linux 中:
- 如果是动态库,库文件是以 .so 作后缀的
- 如果是静态库,库文件是以 .a 作后缀的
库文件的命名:
libXXX.so / libXXX.a …
库的真实名称:去掉 lib前缀 ,去掉.a- .so-(且包含)后缀,剩余的为库名称
静态库
生成
- 这里创建一个主文件夹
library
在文件夹内部创建一个my_lib
文件夹,用来放所写的库函数,这里用add, sub
两个函数
库文件的命名:
add,sub分别是两个简单的加减函数:
- 在
library
进行其余代码的编写:
编写makefile文件
src=mytest.c ./my_lib/add.c ./my_lib/sub.c
obj=mytest.o ./my_lib/add.o ./my_lib/sub.o
mytest:$(obj)
gcc -o $@ $~
%.o:%.c
gcc -c $<
.PHONY:clean
clean:
rm -f *.o mytest
此时我们有以下文件
- 通过将
.o
文件打包形成静态库
进入my_lib
文件夹写Makefile
lib_mymath.a:add.o sub.o
ar -rc $@ $^
%.o:%.c
gcc -c $<
此时
lib_mymath.a
就是一个 静态库
静态库的本质:将所有的.o文件打包形成库
- 为了保证库的保密性:
再次完善Makefile:
lib_mymath.a:add.o sub.o
ar -rc $@ $^
%.o:%.c
gcc -c $<
.PHONY:clean
clean:
rm -f *.o lib_mymath.a output
.PHONY:output
output:
mkdir output
cp -rf *.h output
cp lib_mymath.a output
重新make,再进行output操作
此时查看output中的文件:
使用
创建一个 caller
文件夹(在my_lib
中,与output
同级目录),为调用库的调用者:
将 output
给调用者(移动到caller文件夹里),更名为caller_lib
caller下写一段测试代码:
#include "add.h"
#include "sub.h"
void test()
{
int x = 20;
int y = 10;
int r1 = my_add(x, y);
int r2 = my_sub(x, y);
printf("add : %d\n", r1);
printf("sub : %d\n", r2);
}
int main()
{
test();
return 0;
}
运行后会发现:
报错,程序找不到 add.h
,因为系统默认只在统计目录下找头文件,而 add.h / sub.h
都在 caller_lib
文件夹中,所以找不到,这里引入一个指令:
gcc test.c -I./caller_lib -L./caller_lib -l_mymath
这里进行解释:
为什么库名称为
_mymath
?
注意 这里指定的是库的真实名称,及去掉前后缀的名称。
此时执行操作,运行a.out文件,发现正常生成结果,则库的使用没有问题。
可以将该指令写入caller 的 makefile文件中
不再进行后续演示
动态库
生成
- 先执行 make clean 命令,清除之前的部分文件
更改 my_lib
中的 Makefile
文件
# 动态库实现
# 形成一个动态链接的共享库
lib_mymath.o:add.o sub.o
gcc -shared -o $@ $^
#产生 .o 目标文件,程序内部的地址方案:与位置无关,库文件可以在内存的任何位置加载,而且不影响和其他程序的关联性
%.o:%.c
gcc -fPIC -c $<
.PHONY:clean
clean:
rm -f lib_mymath.so *.o
.PHONY: lib
lib:
mkdir lib
cp *.h lib
cp lib_mymath.so lib
并 更改 caller
的 makefile
文件
mytest:test.c
gcc -o $@ $^ -I./caller_lib -L./caller_lib -l_mymath
.PHONY:clean
clean:
rm -f mytest
使用
执行 caller
中的 makefile
文件 发现报错
原因如下:
- 静态库编译时需要,运行时直接拷贝
- 动态库编译和运行时都需要
这里引入一个新指令
LIBRARY_PATH
可以用于指定非标准位置的库文件,以便编译器能够正确地链接程序。
解释:
- 这个命令将环境变量
LD_LIBRARY_PATH
设置为/home/aiyimu/myLinux/libiary/static/my_lib/caller/caller_lib
,并将其导出,使得在当前终端中启动的所有子进程都能够访问这个环境变量。 LD_LIBRARY_PATH
环境变量用于指定系统动态链接库查找的路径。
此时再次执行 make
命令
执行生成的 mytest
: