【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)表示在特定路径下,要使用哪一个库.

相关推荐
xinyu39115 分钟前
旧版Ubuntu Docker镜像 apt 失败
linux·ubuntu·docker
JZC_xiaozhong27 分钟前
OA调价审批后,采购调价单如何自动同步到ERP?解决漏录错价难题
大数据·linux·服务器·前端·数据库·数据孤岛解决方案·数据集成与应用集成
ljs64827395129 分钟前
Linux 实用命令:环境变量、文件传输、压缩解压、跨服务器传文件
linux·运维·服务器
AliCloudROS42 分钟前
一次真实录屏:我只说每月别超过 200 块,小程序后端就搭好了
运维·人工智能·云计算
__Witheart__1 小时前
lunch选择的版型与版型对应的配置文件
android·linux
A小调的码农1 小时前
给垃圾平板“一生E本” 装新系统—————Armbian 编译 KYX T7Y (RK3326) 踩坑全记录
linux·嵌入式硬件
ljs6482739511 小时前
Linux 网络常用命令与端口基础详解
linux·网络·php
蓝狐社1 小时前
一张被低估的芯片版图——中兴通讯
运维·服务器
网络小白不怕黑1 小时前
13.SSH服务相关配置
服务器·网络·ssh
Jtti1 小时前
站群服务器多IP能不能分散DDoS攻击流量?
服务器·tcp/ip·ddos