前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >库的制作 与 使用 (Linux下)

库的制作 与 使用 (Linux下)

作者头像
用户11039529
发布2024-06-17 08:45:21
650
发布2024-06-17 08:45:21
举报
文章被收录于专栏:算法学习日常算法学习日常

动静态库的制作

前置知识

要学会制作动态库,必须要有软硬链接知识的基础,大家可以移步至该文章:软链接和硬链接的详解 (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文件都生成后,我们要输入一下命令,来打包

代码语言:javascript
复制
ar -rc liboutput.a myprint.o mymath.o
  • 命令解析
    • ar:tar的缩写
    • r:replace
    • c:creat
    • liboutput.a:命名规范
      • lib:库文件前缀,这是命名要求
      • output:库文件名 ( ̄︶ ̄)↗敲重点
      • .a:静态库后缀,也是命名要求
    • .o:要被打包的.o文件列表
makefile参考

以上的各个步骤可以用makefile来完成,以下是makefile的参考

代码语言:javascript
复制
# 静态库
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的妙用

代码语言:javascript
复制
.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

大家将自己的头文件和库文件分别放入这两个路径就好啦

脑子不好的小菜鸟就不演示啦,因为这样子有弊端哦~( ̄▽ ̄)~*

弊端

放在系统路径下的文件都是经过了长时间的检验的,其可靠性非常强,但是我们自己的头文件和库文件并没有经过检验,如果我们在后续长期使用中发现这个文件有问题,那将是非常非常麻烦的,有如下原因

  • 库函数不止一个人使用,因为通常是整个小组甚至是整个公司使用,如果这个库函数出了问题,则将影响公司
  • 时间久了,你也搞不清楚是哪个文件的问题,这就需要运维人员去查找日志信息,这花费时间和精力

法二:放入环境变量

要输入以下命令:

代码语言:javascript
复制
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 使得该配置文件生效

这样子我们就可以直接使用这个库啦

使用库的命令

代码语言:javascript
复制
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

记得点个关注和收藏哦

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前置知识
  • 库的基本构造
    • 问题
      • 分析
      • 库的生成
        • 静态库的生成
          • 动态库的生成
          • 库的使用
            • 法一:放入系统路径
              • 弊端
            • 法二:放入环境变量
              • 弊端
            • 法三:放入配置文件
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档