【Linux】静态库的制作和使用详解

在这里插入图片描述

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤
📃个人主页 阿然成长日记 👈点击可跳转
📆 个人专栏: 🔹数据结构与算法🔹C语言进阶🔹C++🔹Liunx
🚩 不能则学,不知则问,耻于问人,决无长进
🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍

前言:

本篇博客讲解两个类型的库:动态库(.so) 和 静态库(.a).的制作。

一、库的基础知识

库的作用:提升开发效率。隐藏源代码

库的本质:将所有的[.o]结尾的可执行目标二进制文件打包形成一个文件夹。

二、如何编写静态库

1.原理简述

你编写了好几个文件,给别人使用,但是又不想让使用者看到内部源代码,此时有没有什么办法呢。

本质就是隐藏.c源文件。

  • 第一步:将所有.c的文件形成.o文件

  • 第二步:将所有的.o使用ar指令打包成一个库文件。

  • 具体流程如下图:

在这里插入图片描述

这样做的好出有:
(1)将所有的源文件打包好,防止使用者再拷贝时丢失原文件。提高了使用效率。
(2)使用者无法查看源码,提高了安全性

2.实际操作

分别创建了4个文件:mymath.h mymath.c myprint.h myprint.c.

  • 1.<mymath.h>:
#pragma once    
#include<stdio.h>    
    
extern int addToTarget(int start, int end);//声明函数
  • 2.mymath.c
  #include "mymath.h"                                             #             
                                                                                     
  //这段函数的作用是计算start-end之间的和
  int addToTarget(int start, int end)                               
  {                                                                
    int sum = 0;                                                   
    int i = start;                                                 
    for(i; i <= end; i++)
    {                                                                                                                                 
      sum += i;                                                    
    }                                                              
    return sum;                                                    
  }  
  • 3.myprint.h
#pragma once     
    
#include<stdio.h>    
#include<time.h>    
    
extern void Print(const char* str);  
  • 4.myprint.c
#include "myprint.h"                                                            
 
//这段函数功能是输出传入的字符串,后面加上时间戳                                                                    
void Print(const char* str)                                                          
{
  printf("%s[%d]\n",str,(int)(time(NULL)));
}       

有了上面四个文件后,还需要写一个main方法使用这些函数。

#include "myprint.h"    
#include "mymath.h"    
    
int main()    
{    
  Print("hello,world");                                                                                                               
  int res = addToTarget(1,100);    
    
  printf("res: %d\n",res);    
    
  return 0;    
}    

开始制作静态库:
第一步:将所有的.c文件–>.o文件
使用gcc的【-c】选项,代码如下:

gcc -o myprint.o -c myprint.c
gcc -o mymath.o -c mymath.c

注意:main函数不用参与,每个使用者都会有自己的main方法去调用库文件。

第二步:o文件打包成名字叫hello的静态库
知识补充:

【ar】指令:
ar -[选项] + lib+库文件名.a + 所有.o文件
选项这里只说r(replace替换),c(create创建)就可以了,就足以让我们创建静态库了.
注意: 格式一定是lib+库文件名.a。也就是说要形成的静态库的名字 前缀必须是lib,后缀必须是.a,中间可以随便起名字.

执行代码:

ar -rc libhello.a main.o myprint.o mymath.o

在这里插入图片描述

可以发现,此时目录下面就会存在刚打包好的库文件了,但是,还需要结合对应的头文件才能正确的使用库文件中的函数。往下学!

3.使用makefile文件自动化构建

理清楚一个文件形成静态库的过程后 总结来说: .c文件 —> .o文件 —>
打包形成静态库

既然是这么一套固定的流程,那么我们完全可以用Makefile来完成这些工作。需要注意的是搞清各个文件的依赖关系,然后再进行编写。

所以最后的Makefile编写如下:

libhello.a: mymath.o myprint.o                                                                                                        
  ar -rc libhello.a mymath.o myprint.o    
mymath.o : mymath.c    
  gcc -o mymath.o -c mymath.c    
myprint.o: myprint.c    
  gcc -o myprint.o -c myprint.c    
    
.PHONY:clean    
clean:    
  rm -rf *.o libhello.a    

在这里插入图片描述

这样还没有结束:还有对应的许多头文件呢。一般都是.h声明,然后从.o打包形成的库里面找。

  • 所以我们还需要做一件工作:将.h和.a文件规整到一起.在Makefile加入以内容:就是将头文件和库文件规整在一起,逻辑如下 在这里插入图片描述

  • 在这里插入图片描述

  • makefile代码如下

.PHONY:hello    
hello:    
  mkdir -p hello/lib    
  mkdir -p hello/include    
  cp -rf *.h hello/include    
  cp -rf *.a hello/lib  
  • 总结来说: .c文件 —> .o文件 —> 打包形成静态库–>最后将.h和.a文件规整到一起

这样就制作好了一个静态库!如何去使用呢?

四、静态库的使用

方法一:直接拷贝到系统路径

头文件gcc系统默认搜索路径是:/usr/include
库文件gcc系统默认搜索路径是:/lib64 或者 /usr/lib64

  • 可以将你编写的静态库拷贝进/usr/lib64。头文件拷贝进/usr/include ;但是这样做会污染原来别人已经写好的库。不建议使用

方法二:指定路径搜索

我们可以直接在编译的时候加上头文件和库文件的路径.
对于上面的代码我们执行:

gcc main.c -I ./hello/include/ -L ./hello/lib/ -lhello

就可以指定路径进行查找。

选项:-I(i的大写)表示头文件的搜索路径
-L表示库文件的搜索路径
-l(小写的L)表示在特定路径下,要使用哪一个库.

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-11 20:42:01       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-11 20:42:01       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-11 20:42:01       58 阅读
  4. Python语言-面向对象

    2024-07-11 20:42:01       69 阅读

热门阅读

  1. 【面试题】Golang (第一篇)

    2024-07-11 20:42:01       23 阅读
  2. vue2 使用 Socket.io 实现 WebSocket

    2024-07-11 20:42:01       24 阅读
  3. flink 大数据处理资源分配

    2024-07-11 20:42:01       19 阅读
  4. LiteOS GPIO中断处理

    2024-07-11 20:42:01       20 阅读
  5. python如何与前端交互

    2024-07-11 20:42:01       16 阅读
  6. 模型需要从txt中长文本中精准提炼出来文字

    2024-07-11 20:42:01       22 阅读