一、什么是库?
简单来说库就是现成的,可以复用的代码,在我们的Linux系统中默认安装了C语言库,这样我们才能在Linux上运行C语言的代码
二、静态库(.a)的创建
在当前self文件夹里,有我们自己实现的stdio.c,stdio.h,string.c,string.h文件
.h文件中保存了相应的方法名,.c文件里保存了方法的具体实现,假设我现在想让第三者使用我实现的方法但是却不想让他知道方法如何实现的,那么我们就可以通过创建静态库的方法,即让第三者能使用我的实现的函数,而且还不能看到我们.c文件里面的具体实现
第一步,通过对.c文件编译,使其变成.o文件
第二步,通过对两个.o文件链接打包形成静态库
libmystdio.a: lib前缀 + 库名(stdio) + (.a)后缀
ar -rc libmystdio.a my_stdio.o my_string.o
可见,对两个.o文件成功打包成静态库
静态库的使用方法一
在Linux系统里,C语言的头文件是在系统里的,库也是在系统里的,因此我们想使用我们的静态库,也可以模仿标准的C语言库,将我们自己的.h文件和静态库加到系统里,本质也是拷贝,windows下也一样
查看usr/include/目录下所有my_文件,可以看到我们的两个头文件已经被成功加载到系统里了
将我们的头文件加载到系统后,我们自己的静态库也以同样的方法加载到系统里
此时,如果第三方人员想使用我这个库中的函数,他创建了一个main.c文件,在VScode中我们也可以清楚看到,当前系统里面已经识别出来了我们自己的头文件
第三方人员完整的main.c文件如下
#include<my_stdio.h>
#include<my_string.h>
#include<stdio.h>int main()
{const char *s = "abcdefg";printf("%s: %d\n", s, my_strlen(s));mFILE *fp = mfopen("./log.txt", "a");if(fp == NULL) return 1;mfwrite(s, my_strlen(s), fp);mfwrite(s, my_strlen(s), fp);mfwrite(s, my_strlen(s), fp);mfclose(fp);return 0;
}
上面的代码看起来没有问题,按照平常理解来说应该也能成功运行,可真到了运行的时候,却发生了下面的报错
这是编译错误,我们可以肯定,我们自己的头文件和库明明已经安装到系统里面的,为什么还会发生编译错误?因为我们没有没有告诉gcc要链接那个库,因为gcc是默认找到C标准库的,我们即使自己的库和C语言标准库再像,也只不过是一个第三方库而已,所以如果我们想运行成功上面的代码,就需要告诉gcc该链接哪一个库
解决方法: gcc main.c -l 库名
注意:库名是去掉前缀(lib)和后缀(.a) 剩下的部分
静态库的使用方法二
假如我们不想把头文件 和自己的静态库加入到自己系统里,该怎么使用呢?
现在我们已经把原本加入到系统的头文件和静态库删除
将头文件和静态库打包给第三方,此时第三方手上的文件:
运行main.c文件,发现头文件报错,因为我们此时系统里面已经没有了这两个.h文件
修改main.c文件里面的头文件:
再次运行,发现出现了与方法一同样的错误
因为gcc默认找的是标准C语言库,那我们就告诉gcc找哪个库,但还是编译报错,告诉我们没有这个库,这是为什么呢?因为gcc默认是去/lib64/路径下去找的,可我们的库的位置与main.c一致
解决方法:告诉gcc在哪个路径下找静态库gcc main.c -L. -l mystdio-L:哪个路径查找
-l:查找的库名
静态库的使用方法三
使用makefile自动构建项目
makefile文件如下:
libmystdio.a:my_stdio.o my_string.o@ar -rc $@ $^@echo "build $^ to $@ ... done"
%.o:%.c@gcc -c $<@echo "compling $< to $@ ... done".PHONY:clean
clean:@rm -rf *.a *.o stdc*@echo "clean ... done".PHONY:output
output:@mkdir -p stdc/include@mkdir -p stdc/lib@cp -f *.h stdc/include@cp -f *.a stdc/lib@tar -czf stdc.tgz stdc@echo "output stdc ... done"
make,然后make output发布
第三方得到了一个含有头文件与静态库的文件夹
第三方如何使用
效仿法二使用静态库,可以看到,gcc告诉我们找不到头文件了
解决方法:
gcc main.c -I stdc/include/ -L stdc/lib -l mystdio
-I:去哪个路径找头文件
-L:去哪个路径找静态库
-l:找哪个静态库
至此,静态库的创建和使用完毕
三、动态库(.so)的创建
makefile文件如下:
libmystdio.so:my_stdio.o my_string.ogcc -o $@ $^ -shared
%.o:%.cgcc -fPIC -c $<.PHONY:clean
clean:@rm -rf *.so *.o stdc*@echo "clean ... done".PHONY:output
output:@mkdir -p stdc/include@mkdir -p stdc/lib@cp -f *.h stdc/include@cp -f *.so stdc/lib@tar -czf stdc.tgz stdc@echo "output stdc ... done"
动态库的使用方法一
与静态库一致,将头文件加载到系统里
与静态库一致,将动态库加载到系统里
第三方人员的main.c文件与静态库的使用方法一一致,运行后发现找不到库
指定gcc找哪个库后,就能正常运行
动态库的使用方法二
把原本加入到系统的头文件和动态库删除
第三方手上动态库和头文件
main.c文件里面的.h已经更改
与静态库的使用方法二一致,得指定gcc在哪个路径下找库,找哪个库
动态库的使用方法三
第三方手上已经有stdc文件夹,里面有头文件和动态库
指定路径找头文件,指定路径找动态库,找指定库名的动态库
此时可以看到,这种情况与静态库并不一样,虽然也能生存可执行文件,但是却无法运行,系统也告诉我们找不到动态库,这是为什么呢?
原因:因为动态库与静态库不同,对于动态库,OS是需要加载的,从哪里加载:/lib64/下加载,
你-L选项只是告诉gcc,并没有告诉OS,所有就会报错
解决方法:
1.像方法一一样,将动态库拷贝到/lib64/目录下
2.系统路径中,建立软链接
3.配置环境变量,但是这样每一次开机都会重置
4.进入bashrc(在根目录下),修改export,这里就不再演示