动静态库的制作

news2025/1/18 16:56:27

目录

一.动静态库的原理

二.静态库

2.1制作静态库

 2.2使用静态库

三.动态库

3.1制作动态库

3.2动态库的使用 


一.动静态库的原理

首先要知道可执行程序的生成过程:1,预处理  2,编译 3,汇编  4 ,链接

1.预处理

头文件include的包含,删注释,#define定义符号的替换,条件编译等..形成XXX.i文件

2.编译 

编译: 完成词法分析、语法分析、语义分析、符号汇总等,形成XXX.x文件

3.汇编

 将汇编指令转换成二进制指令,形成符号表,最终形成XXX.o文件
 

4.链接 

合并段表,符号表的合并和重定位, 将生成的各个xxx.o文件进行链接,最终形成可执行程序。  

看下面很简单的代码:

add.cpp

#include"add.h"

int add(int a,int b)
{
  int sum=a+b;
  return sum;
}

add.h

#pragma once
#include<iostream>
using namespace std;

extern int add(int a,int b);

 test.cpp

#include"add.h"

int main()
{
  int a=10;
  int b=10;
  int sum=add(a,b);
  cout<<sum<<endl;
  return 0;
}

 结果:

包头文件用"",是在当前路径上找,<>是在系统目录下找。

test.cpp形成test.o时,之前只是将该头文件展开,只找到函数的声明,add 的符号表中的地址是无效的,链接时与add.o重定位后才有效,合并段表,形成可执行程序。

我们可以将函数的实现变为XXX.o文件,放在一起,并将该函数的声明(头文件)放入系统头文件中,就可以认为形成了一个库。后面要使用这个函数就可以配合那个库去使用。

1.静态库:Linux下静态库是以.a为后缀的文件。程序在编译链接时会将库里面的代码拷贝一份放入我们的可执行程序里面,程序运行的时候将不再需要静态库

2.动态库:在Linux下动态库是以.so为后缀的文件。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。

3.静态链接:将库里的代码拷贝到可执行程序的过程。

4.动态链接:在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)。

5.库名称的识别:例如:libc.so,只需要去掉前缀lib和后缀.so

6.链接的本质:链接.lib文件和.o文件

二.静态库

2.1制作静态库

例如:我们来实现一个加法函数与打印时间的函数,将它的方法打包成库。

add.h头文件:

#pragma once
#include<iostream>
using namespace std;

extern int add(int a,int b);

add.cpp文件:

#include"add.h"
int add(int a,int b)
{
  int sum=0;
  for(int i=a;i<=b;i++)
    sum+=i;
  return sum;
}

Print.h头文件:

#pragma once
#include<iostream>
#include<time.h>
using namespace std;

extern void Print();

print.cpp文件:

#include"Print.h"

void Print()
{
  cout<<time(nullptr)<<endl;
}

步骤:

1.让所有源文件生成对应的目标文件

2.使用ar命令将所有目标文件打包为静态库

  • -r(replace):若静态库文件当中的目标文件有更新,则用新的目标文件替换旧的目标文件。
  • -c(create):建立静态库文件。

3.将头文件和生成的动态库组织起来

 编写makefile:

libshow.a:add.o print.o
	ar -rc libshow.a add.o print.o
add.o:add.cpp
	g++ -c add.cpp -std=c++11
print.o:print.cpp
	g++ -c print.cpp -std=c++11


.PHONY:lib
lib:
	mkdir -p lib-static/lib   
	mkdir -p lib-static/include  
	cp *.a lib-static/lib        //将形成的静态库放入lib-static/lib目录下 
	cp *.h lib-static/include    //将对应的头文件放入lib-static/include目录下

.PHONY:clean
clean:
	rm -rf *.o *.a  lib-static
          

结果:

此外,我们可以用ar命令的-t选项和-v选项查看静态库当中的文件。

  • -t:列出静态库中的文件。
  • -v(verbose):显示详细的信息。

例如:

 2.2使用静态库

方法1:推荐使用

使用gcc编译main.c生成可执行程序时需要携带三个选项:

  • -I:指定头文件搜索路径。
  • -L:指定库文件搜索路径。
  • -l:指明需要链接库文件路径下的哪一个库。

例如:

test.cpp文件调用那两个方法:

#include"add.h"
#include"Print.h"

int main()
{
  int a=1;
  int b=10;
  int sum=add(a,b);
  cout<<sum<<endl;
  Print();
}

结果:

 注意:上面的路径用绝对与相对路径都可以,-I-L-l这三个选项后面可以加空格,也可以不加空格。库的名称是去掉前缀与后缀。

补充:

  1. 因为编译器不知道你所包含的头文件add.h在哪里,所以需要指定头文件的搜索路径。
  2. 因为头文件add.h当中只有my_add函数的声明,并没有该函数的定义,所以还需要指定所要链接库文件的搜索路径。

方法2:把头文件和库文件拷贝到系统路径下

头文件路径:/usr/include/

库的路径:/lib64/

例如:

 补充:使用g++编译的是.cpp,而g++就是用来编译C++程序的,所以g++编译的时候默认就找的是C++库,但此时我们要链接的是哪一个库编译器是不知道的,因此我们还是需要使用-l选项,指明需要链接库文件路径下的哪一个库.

三.动态库

3.1制作动态库

1.让所有源文件生成对应的目标文件

用源文件生成目标文件时需要携带-fPIC选项:产生与位置无关码。-fPIC作用于编译阶段,告诉编译器产生与位置无关的代码,此时产生的代码中没有绝对地址,全部都使用相对地址,从而代码可以被加载器加载到内存的任意位置都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

2.使用-shared选项将所有目标文件打包为动态库

3.将头文件和生成的动态库组织起来

编写makefile:

libshow.so:add.o print.o
	g++ -o libshow.so -shared add.o print.o -std=c++11
add.o:add.cpp
	g++ -c add.cpp -fPIC -std=c++11
print.o:print.cpp
	g++ -c print.cpp -fPIC -std=c++11
	
.PHONY:lib
lib:
	mkdir -p lib-dyl/lib
	mkdir -p lib-dyl/include
	cp *.so lib-dyl/lib
	cp *.h lib-dyl/include

.PHONY:clean
clean:
	rm -rf *.o *.a libshow.a libshow.so lib-static lib-dyl

结果:

3.2动态库的使用 

使用该动态库的方法与使用静态库的方法一样,可以使用 -I-L-l这三个选项来生成可执行程序,也可以先将头文件和库文件拷贝到系统目录下,然后再使用-l选项指明需要链接的库名字来生成可执行程序。

例如:生成的可执行程序的路径下不含要使用的库,发现该程序运行不起来。

 

方法1:拷贝.so文件到系统共享库路径下

 

方法二:更改LD_LIBRARY_PATH

LD_LIBRARY_PATH是程序运行动态查找库时所要搜索的路径,我们只需将动态库所在的目录路径添加到LD_LIBRARY_PATH环境变量当中即可。

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/LF/linux-l/lesson3/lib-dyl/lib

 

方法三:配置/etc/ld.so.conf.d/

/etc/ld.so.conf.d/路径下存放的是以.conf为后缀的配置文件,这些配置文件当中存放的都是路径,系统会自动在/etc/ld.so.conf.d/路径下找所有配置文件里面的路径,之后就会在每个路径下找你所需要的库。若将自己库文件的路径也放到该路径下,那么当可执行程序运行时,系统就能够找到我们的库文件了。再使用ldconfig命令将配置文件更新一下,更新之后系统就可以找到该可执行程序所依赖的动态库了。

例如:

[LF@ecs-100710 lesson3]$ echo /home/LF?linux-l/lesson3/lib-dyl/lib > xx.conf
[LF@ecs-100710 lesson3]$ sudo cp xx.conf /etc/ld.so.conf.d/
[LF@ecs-100710 lesson3]$ sudo ldconfig
[LF@ecs-100710 lesson3]$ ./test
55
1669019703

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/23641.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

03 LaTex之标题页摘要

1.标题页 \title{{ABC}\footnote{explain}}%生成标题和标题的脚注\author{\small $^a$lay \qquad $^b$winter \footnote{super star}\\%换行符 %作者信息 \small $^a$ lays brief\\ \small lays address, 710021\\%换行 \small $^b$ winters introduction \\ \small winters …

0101 蓝桥杯真题04

/* * 马虎的算式 * 小明是个急性子&#xff0c;上小学的时候经常把老师写在黑板上的题目抄错了。 * 有一次&#xff0c;老师出的题目是&#xff1a;36 x 495 ? * 他却给抄成了&#xff1a;396 x 45 ? * 但结果却很戏剧性&#xff0c;他的答案竟然是对的&#xff01;&a…

同花顺_代码解析_技术指标_Z_3

本文通过对同花顺中现成代码进行解析&#xff0c;用以了解同花顺相关策略设计的思想 目录 ZNZ_DPCYC1 ZNZ_DPCYR ZNZ_HLD ZNZ_HUO ZNZ_MYL1 ZNZ_MYP1 ZNZ_PAS ZNZ_PAS1 ZNZ_RPY1 ZNZ_RPY2 ZNZ_SDR ZNZ_TAO ZNZ_YHBOL1 ZNZ_YHCBB ZX ZNZ_DPCYC1 大盘成本均线 行…

python 给图片添加噪声

import numpy as np import cv2 import matplotlib.pyplot as plt import skimage from skimage import io import randomdef addGaussNoise(origin,var0.0005):#添加高斯噪声函数var random.uniform(0.0001, 0.04)noisy skimage.util.random_noise(origin, modegaussian, va…

idea iu 2021 Mac版本的使用,如何创建java web项目,包括tomcat和web包

Java web系列文章目录 第一章 前端学习入门之idea iu 2021版本的使用 目录Java web系列文章目录前言一、Java web是什么&#xff1f;二、配置步骤1.下载Tomcat服务器2.idea iu 2021版本界面总结前言 随着前端的学习路径&#xff0c;java web项目不可避免要学习使用&#xff0…

YUV与RGB 以及之间的转换

目录 一、RGB 二、YUV 三、YUV类型和存储方式 1、类型 2、存储方式 四、分析YUV 4:2:0 1、YU12(I420&#xff0c;YUV420P) 2、YV12 3、NV12(YUV420SP) 4、NV21(YUV420SP) 5、占用空间大小比较 五、RGB与YUV之间的转换 1、转换标准 2、Color Range 3、计算公式 在…

【ArcGIS】属性表导出及乱码问题

这玩意其实说难不难&#xff0c;但是乱码有时候还是烦人 直接复制到EXCEL 部分表细节被我删掉了 直接点击全选&#xff0c;然后复制&#xff0c;再到EXCEL里粘贴。我有时候就是这么干的。而且量大概是二十万行左右。 Table to Table 如果你的属性文件大于65533行&#xff…

十一、组合API(1)

本章概要 为什么要引入组合APIsetup() 函数 组合&#xff08;Composition&#xff09;API 是在 Vue 3.0 中引入的&#xff0c;它是一组附加的、基于函数的 API &#xff0c;允许灵活地组合组件逻辑。 组合 API 并没有引入新的概念&#xff0c;更多地是将 Vue 的核心功能&…

项目相互依赖调用解决方法两种方法

Bmodel依赖于Amodel&#xff0c;但是Amodel又需要BModel的信息。原来是在Amodel创建一块内存&#xff0c;在Bmodel中将内存地址赋给这块内存&#xff0c;然后在Amodel去做其他操作。 方法一&#xff1a;采用静态变量static链接&#xff1a;C开发中一个解决方案里&#xff0c;两…

LeetCode 0808. 分汤:好题【感叹号】

【LetMeFly】808.分汤&#xff1a;好题&#xff01; 力扣题目链接&#xff1a;https://leetcode.cn/problems/soup-servings/ 有 A 和 B 两种类型 的汤。一开始每种类型的汤有 n 毫升。有四种分配操作&#xff1a; 提供 100ml 的 汤A 和 0ml 的 汤B 。提供 75ml 的 汤A 和 2…

Google Earth Engine(GEE)—— 各矿区时序NDVI变化图(包含具体的运行函数)

函数: ee.Filter.eq(name, value) Filter to metadata equal to the given value. Returns the constructed filter. Arguments: name (String): The property name to filter on. value (Object): The value to compare against. Returns: Filter ui.Chart.image.s…

7、Jedis测试

文章目录7、Jedis测试7.1. Jedis所需要的jar包7.2. 连接Redis注意事项7.3. Jedis常用操作7.3.1. 创建动态的工程7.3.2. 创建测试程序7.4. 测试相关数据类型7.4.1. Jedis-API&#xff1a;Key7.4.2. Jedis-API&#xff1a;String7.4.3. Jedis-API&#xff1a;List7.4.4. Jedis-AP…

葡萄糖-聚乙二醇-6-羧甲基荧光素 Glucose-PEG-6-FAM

葡萄糖-聚乙二醇-6-羧甲基荧光素 Glucose-PEG-6-FAM 中文名称&#xff1a;葡萄糖-6-羧甲基荧光素 英文名称&#xff1a;Glucose-6-FAM 别称&#xff1a;6-羧甲基荧光素标记葡萄糖&#xff0c;6-羧甲基荧光素-葡萄糖 PEG接枝修饰葡萄糖 Glucose-PEG-6-FAM 葡萄糖-聚乙二醇…

需求收集方法工具,以及进行需求分析的6大要素

通过本文你将了解&#xff1a;1、需求管理流程包括哪四个步骤&#xff1b;2、如何进行需求收集&#xff1b;3、如何进行需求分析&#xff1f;4、如何进行需求分发&#xff1b;5、如何进行需求验证&#xff1b;6、有哪些辅助软件需求管理的工具系统&#xff1f;一、需求管理包括…

MyBatis核心配置文件

1.environments 注 : environments下面可以配置多个环境 , 需要使用哪个环境default里面的参数就对应哪个Id. 2.properties 配置连接 方法一 :(直接配置参数) 方法二 :(使用properties配置文件) (1)创建一个 properties 文件 , 在里面配置连接 (2)在核心配置文件中配置使用p…

41.朴素贝叶斯Naive Bayes公式推导与理解+求解公园凉鞋问题(借助文氏图)

朴素贝叶斯是基于概率论统计学的分类算法。 贝叶斯理论是指根据一个已发生事件的概率&#xff0c;计算另一个事件的发生概率。 目录 1.相关概念 1.1先验概率 应用举例 1.2条件概率 应用举例 1.3全概率公式 应用举例 1.4后验概率 应用举例 2.课堂笔记 ​ 3.文…

ubuntu16.04+cuda10.0+cudnn7.6+tensorflow_gpu-1.11.0环境安装

为了搭深度学习环境,又装了一遍各种库,在此记录安装版本和流程. ubuntu16.04cuda10.0cudnn7.6tensorflow_gpu-1.11.0环境安装1 安装NVIDIA显卡2 安装CUDA10.03 安装CUDNN4 安装tensorflow_gpu-1.11.01 安装NVIDIA显卡 查看自己的显卡型号: lspci |grep -i nvidianvidia官网:h…

linux安装Zookeeper3.5.7详解

官网下载链接&#xff1a;Apache ZooKeeper 如下图可以下载历史版本 然后找到3.5.7版本&#xff0c;直接下载即可然后将Zookeeper拷贝到一个文件夹下&#xff0c;这里我选择的是/opt/software文件夹 然后将其解压到指定目录下 tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz -C …

让你全方位了解tftp协议,学tftp协议不再难

TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议&#xff0c;端口号为69&#xff0c;是一种高效的文件传输方式。 其目标是在UDP之上建立一个类似于FTP的但仅支持文件上传和下载功能的传输协议&a…

【Jmeter基础篇】06:HTTP信息头管理器的使用 | 梯度加压性能测试

一、什么是信息头&#xff1f; 其实就是请求头&#xff0c;它会随着我们的HTTP请求一起发送到服务器。 二、使用场景 需要传输cookie&#xff0c;token或其他某些信息&#xff0c;或是需要伪造请求头的时候。 三、实际案例 比如我在使用Apache Jmeter发送请求的时候&#…