目录
动静态库的制作
前置知识
要学会制作动态库,必须要有软硬链接 知识的基础,大家可以移步至该文章:软链接和硬链接的详解 (Linux系统下)-CSDN博客
库的基本构造
问题
问题:
我们都知道代码有源文件,头文件,那么请问我们要将自己实现的代码给他人使用时,应该给哪些文件给他们呢?🤨🤔
分析
要给什么文件
1、头文件要给别人吗
- 答:肯定要,我们使用库里面的函数,一定需要包含头文件才能使用🙂😲
2、源文件要给别人吗?
-
答:情况分两种🤔😯
-
愿意开源 ,和别人一起进步:可以😆
-
保护自己的知识产权(暂不开源 ):不要😶
-
3、源文件不给别人的时候,应该怎么做呢?
-
答:给编译后的文件 (别人看不了你的代码实现)ψ(`∇´)ψ
- 也就是
gcc -c 源文件名 -o 编译后的文件名.o
后形成的文件,这样的文件属于二进制文件,别人看不了你的代码实现,但是计算机看得懂
- 也就是
如何更好的让别人使用
我们通常不会只有一个头文件和源文件,因此生成的.h
文件和编译后生成的.o
文件不止一个,因此需要对各个文件++分类++进行打包压缩,我们通常采用如下处理办法:
头文件:
放入一个名为
include
的文件夹
.o
文件:打包成库 ,分为静态库和动态库 ,静态库以
.a
结尾,动态库以.so
结尾
库的生成
静态库的生成
-
问题:
若我们有如下文件:
myprint.c
,mymath.c
,myprint.h
,mymath.h
,请问我们要干什么呢🤔,想想前面讲的哦😶
答案:
头文件放入一个include文件夹下
库文件:
先都
gcc -c 源文件名 -o 编译后的文件名.o
生成.o
文件再将所有
.o
文件打包为.a
文件 ,也就是静态库
下面的问题就是:
怎么打包生成
.a
文件??
答:当我们的
.o
文件都生成后,我们要输入一下命令,来打包
cs
ar -rc liboutput.a myprint.o mymath.o
-
命令解析
-
ar
:tar的缩写 -
r
:replace -
c
:creat -
liboutput.a
:命名规范-
lib
:库文件前缀,这是命名要求 -
output
:库文件名 ( ̄︶ ̄)↗敲重点 -
.a
:静态库后缀,也是命名要求
-
-
.o
:要被打包的.o
文件列表
-
makefile参考
以上的各个步骤可以用makefile
来完成,以下是makefile
的参考
cpp
# 静态库
liboutput.a:myprint.o mymath.o
# .a:静态库后缀
ar -rc liboutput.a myprint.o mymath.o
# ar:归档
# -rc:
# r:replace
# c:creat
myprint.o:myprint.c
gcc -c myprint.c -o myprint.o
# -c:编译
mymath.o:mymath.c
gcc -c mymath.c -o mymath.o
.PHONY:output
output:
mkdir -p output/lib
mkdir -p output/include
cp *.h output/include
cp *.a output/lib
.PHONY:clean
clean:
rm -f *.o *.a
- 起始
- 输入
make
后会生成.o
文件和.a
文件
-
输入
make output
后会生成output
文件夹,下面是-
include
文件夹存放
.h
文件
-
lib
文件夹存放
.a
文件
-
- 输入
make clean
就会清除那些不需要的文件啦
我们发布库给别人用的时候,只需要将output给别人就好啦
动态库的生成
同样,我们也是要将.o
文件打包,但是动态库是打包为.so
文件
-
生成
.o
命令gcc -fPIC -c 源文件名 -o 要生成的.o文件名
-
打包
.o
文件gcc -shared .o文件列表 lib库文件名.so
-
用上面的的
myprint.c
,mymath.c
举例- 生成
.o
文件
myprint_d.o:myprint.c gcc -fPIC -c myprint.c -o myprint_d.o # -c:编译 # -fPIC:生成与位置无关的二进制文件 mymath_d.o:mymath.c gcc -fPIC -c mymath.c -o mymath_d.o
- 打包
.o
文件为.so
文件
liboutput.so:myprint_d.o mymath_d.o gcc -shared -o liboutput.so myprint_d.o mymath_d.o
- 生成
makefile参考(包含动态库和静态库生成)
注意里面的all
的妙用
bash
.PHONY:all
all:liboutput.a liboutput.so
# 静态库
liboutput.a:myprint.o mymath.o
# .a:静态库后缀
ar -rc liboutput.a myprint.o mymath.o
# ar:归档
# -rc:
# r:replace
# c:creat
myprint.o:myprint.c
gcc -c myprint.c -o myprint.o
# -c:编译
mymath.o:mymath.c
gcc -c mymath.c -o mymath.o
# 动态库
liboutput.so:myprint_d.o mymath_d.o
gcc -shared -o liboutput.so myprint_d.o mymath_d.o
myprint_d.o:myprint.c
gcc -fPIC -c myprint.c -o myprint_d.o
# -c:编译
# -fPIC:生成与位置无关的二进制文件
mymath_d.o:mymath.c
gcc -fPIC -c mymath.c -o mymath_d.o
.PHONY:output
output:
mkdir -p output/lib
mkdir -p output/include
cp *.h output/include
cp *.a output/lib
cp *.so output/lib
.PHONY:clean
clean:
rm -f *.o *.a *.so
现在我们的库就可以拿给别人去使用啦(还没有完哦)😉
库的使用
我们直接将刚刚制作的output
文件夹给用户使用就好啦~~~
自己制作的库的使用有三种办法
放进系统查找库函数的路径下(静态库)
导入环境变量(动态库)
放入
/etc/ld.so.conf.d/
的配置文件中
法一:放入系统路径
编译器编译时默认去以下路径查找文件
头文件:
/usr/include
库文件:
/lib64
或/usr/lib64
大家将自己的头文件和库文件分别放入这两个路径就好啦
脑子不好的小菜鸟就不演示啦,因为这样子有弊端哦~( ̄▽ ̄)~*
弊端
放在系统路径下的文件都是经过了长时间的检验的,其可靠性非常强,但是我们自己的头文件和库文件并没有经过检验,如果我们在后续长期使用中发现这个文件有问题,那将是非常非常麻烦的,有如下原因
库函数不止一个人使用,因为通常是整个小组甚至是整个公司使用,如果这个库函数出了问题,则将影响公司
时间久了,你也搞不清楚是哪个文件的问题,这就需要运维人员去查找日志信息,这花费时间和精力
法二:放入环境变量
要输入以下命令:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:该动态库的路径
-
注意:(o゚v゚)ノ
要的是路径 ,不需要带上该动态库文件名 (´▽`ʃ♡ƪ)
弊端
xshell退出后这个环境变量中就没有 我们加的路径了 ,因为这是内存级环境变量,所以这种方法不适用于长期使用的库
法三:放入配置文件
这种方法是推荐 的,Linux中有一个专门让我们放置配置文件的,/etc/ld.so.conf.d/这个路径是保存自定义配置搜索库路径的解决方案
步骤
进入该目录下
cd /etc/ld.so.conf.d/
创建一个后缀为
.conf
的文件(需要sudo
权限)
sudo touch zi_ji_de_ku.conf
vim
该文件(要sudo
权限)
sudo vim zi_ji_de_ku.conf
将动态库的路径放入该文件中,保存退出
退出后,
ldconfig
使得该配置文件生效
这样子我们就可以直接使用这个库啦
使用库的命令
gcc main.c -I 自己的库的头文件的路径 -L 自己的库的库文件路径 -l库文件名
命令解析
-I
:表示包含头文件
-L
:表示链接库注意:
- 后面跟的都是路径,路径是不带文件名的 ,实在搞不清楚,可以先进入
lib
文件夹下,再用pwd
命令显示路径😉( •̀ ω •́ )✧
-l库文件名
:注意
- 是库文件名,去掉了库中的
lib
前缀和.a
或者.so
后缀 ------- 再次敲重点(●ˇ∀ˇ●)
将之前的文件进行演示:
-
输入
gcc main.c -I ./output/include -L ./output/lib -loutput -o main
-
注意这里的
-I
和-L
后面都是路径哦,路径是不带文件名的哦~ -
-l
后面是库文件名哦,并不是图片中的liboutput.so
,去掉了lib
前缀和.so
后缀哦
-
-
这样就会生成
main
这个可执行程序啦
完结撒花~~~~ ♪(^∇^*) ヾ(≧ ▽ ≦)ゝ你太棒啦~~~~,给你大大的赞 d=====( ̄▽ ̄*)b
记得点个关注和收藏哦