【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>:
cpp 复制代码
#pragma once    
#include<stdio.h>    
    
extern int addToTarget(int start, int end);//声明函数
  • 2.mymath.c
cpp 复制代码
  #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
cpp 复制代码
#pragma once     
    
#include<stdio.h>    
#include<time.h>    
    
extern void Print(const char* str);  
  • 4.myprint.c
cpp 复制代码
#include "myprint.h"                                                            
 
//这段函数功能是输出传入的字符串,后面加上时间戳                                                                    
void Print(const char* str)                                                          
{
  printf("%s[%d]\n",str,(int)(time(NULL)));
}       

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

cpp 复制代码
#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】选项,代码如下:

cpp 复制代码
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,中间可以随便起名字.

执行代码:

cpp 复制代码
ar -rc libhello.a main.o myprint.o mymath.o

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

使用makefile文件自动化构建

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

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

所以最后的Makefile编写如下:

cpp 复制代码
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代码如下

cpp 复制代码
.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 ;但是这样做会污染原来别人已经写好的库。不建议使用

方法二:指定路径搜索

我们可以直接在编译的时候加上头文件和库文件的路径.

对于上面的代码我们执行:

cpp 复制代码
gcc main.c -I ./hello/include/ -L ./hello/lib/ -lhello

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

选项:-I(i的大写)表示头文件的搜索路径

-L表示库文件的搜索路径

-l(小写的L)表示在特定路径下,要使用哪一个库.

相关推荐
sun00770023 分钟前
ubuntu dpkg 删除安装包
运维·服务器·ubuntu
海岛日记25 分钟前
centos一键卸载docker脚本
linux·docker·centos
oi771 小时前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
AttackingLin1 小时前
2024强网杯--babyheap house of apple2解法
linux·开发语言·python
吃肉不能购2 小时前
Label-studio-ml-backend 和YOLOV8 YOLO11自动化标注,目标检测,实例分割,图像分类,关键点估计,视频跟踪
运维·yolo·自动化
学Linux的语莫2 小时前
Ansible使用简介和基础使用
linux·运维·服务器·nginx·云计算·ansible
qq_312920112 小时前
docker 部署 kvm 图形化管理工具 WebVirtMgr
运维·docker·容器
踏雪Vernon2 小时前
[OpenHarmony5.0][Docker][环境]OpenHarmony5.0 Docker编译环境镜像下载以及使用方式
linux·docker·容器·harmonyos