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

相关推荐
sun03221 小时前
Jenkins的Pipline中有哪些区块,以及其它知识点整理
运维·jenkins
西阳未落1 小时前
Linux(7)——进程(概念篇)
linux·运维·服务器
苒苒鸭1 小时前
nginx 基于IP和用户的访问
linux
领世达检测V133529092492 小时前
智能门锁为什么需要做欧盟网络安全 EN18031 标准检测认证
运维·服务器·网络
樂5022 小时前
Web 服务、 Nfs 服务器以及 Dns 服务器综合实验
运维·服务器
莱茵不哈哈2 小时前
Docker:容器化技术
运维·docker·容器
luckyext3 小时前
SQL SERVER常用聚合函数整理及示例
运维·服务器·数据库·sql·mysql·sqlserver·mssql
滴水之功3 小时前
C语言数据结构-链式栈
linux·c语言·数据结构
liulilittle3 小时前
Ubuntu 18.04 升级内核到 5.X(< 5.10)
linux·运维·服务器·ubuntu
老攀呀3 小时前
CentOS系统上挂载磁盘
linux·运维·centos