Linux---动静态库

前言

在初学Linux的时候,简单的提到过动静态库,但当时只是简单的讲述了一下什么是动态库,什么是静态库,我们可以在此基础上更进一步---制作库。在使用gcc编译器的时候,是默认使用动态链接的。

静态库

静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静
态库。

我们可以先自己设计一个库,只是制作一个简单的小程序,当作一个库,进行演示。

#pragma once

#include <iostream>

int add(int x, int y);
int mul(int x, int y);
int div(int x, int y);
#include "mymath.h"

int add(int x, int y)
{
    return x + y;
}

int mul (int x, int y)
{
    return x * y;
}

int div (int x,int y)
{
    if (y == 0) {
        std::perror("0");
        return -1;
    }
    return x / y;
}

一个简单的计算+*/的小程序。如果有人想用我写的这个小程序, 1. 把源文件直接给他 2. 把我们的源代码想办法打包成库。

我们采取第二种方法,想办法将源代码打包成库。

touch Makefile创建一个Makefile文件,然后将.c文件生成.o文件,如果.o文件特别多,可以将.o文件打个包命名为libXXX.a---所有.o文件的集合,在编译的时候,main.c变成.o的时候,与静态库一结合,就能运行了。

lib=libmymath.a

$(lib):mymath.o
	ar -rc $@ $^
mymath.o:mymath.cc
	g++ -c $^

.PHONY:clean
clean:
	rm -f *.h *.a

生成静态库:ar -rc libxxx.a xxx.o xxx.o | ar是gnu归档工具,rc表示(replace and create)


一个简单的静态库,我们已经制作完成了,那么怎么将他发布呢?

lib=libmymath.a

$(lib):mymath.o
	ar -rc $@ $^
mymath.o:mymath.cc
	g++ -c $^

.PHONY:clean
clean:
	rm -f *.h *.a lib

.PHONY:output
output:
	mkdir -p lib/include
	mkdir -p lib/mymathlib
	cp *.h lib/include
	cp *.a lib/mymathlib

这样就可以了。未来别人要是想用我的库,只需要把lib文件夹给他就行了。


#include "lib/include/mymath.h"

int main()
{
    std::cout << add(1, 1) << std::endl;
    return 0;
}

然后就可以使用自己所创建的静态库写代码了,但是在使用库的时候,头文件可不是这样写的,而是直接写mymath.h

#include "mymath.h"

int main()
{
    std::cout << add(1, 1) << std::endl;
    return 0;
}

但是,当你编译这个文件的时候,却会出现错误,这是因为在编译的时候,有一个预处理阶段,这个阶段会进行头文件展开这个工作,再展开的时候,会默认去系统指定的目录和当前目录进行搜索。

但是系统里并不存在我刚刚写的小程序。lib在我当前的目录中,

系统不会自动的去当前目录的lib中去搜索,所以在编译的时候,我们可以加一个 -I 选项(-I 头文件路径),告诉系统在编译的时候去指定的目录寻找。

此时还是有问题,但问题已经不再是头文件找不到了,而是main函数中的add函数没找到。根本原因是因为找不到add函数的实现。但是我们已经把add的实现放在了libmymath.a里面吗?报错是报找不到add的实现,这就是因为找不到静态库,这不跟上面的问题一样吗?系统搜索库,会去系统中和当前目录中搜索,我自己实现的这个库是找不到的,这个情况下可以在编译的时候加上 -L选项(-L 静态库路径)

还是没找到。这是因为 ./lib/mymathlib/ 下的静态库可能有多个,系统不会自动的去寻找对应的库。所以还需要一个 -l选项(-l库名字)

库的名字是:去掉lib,去掉.a之后才是库的名字。


在使用第三方库的时候,就需要使用这样的方法。

动态库

动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。

现在我创建了四个文件 mylog.h和myloc.cc,myprintf.h和myprintf.cc文件,这两个.cc文件中都提供了两个简单的函数。

// mylog.h
#pragma once

#include <cstdio>

void Log(const char* str);

#include "mylog.h"

void Log(const char* str)
{
    printf("mylog.cc :: %s\n", str);
}
// myprint.h
#pragma once

#include <cstdio>

void print();

#include "myprint.h"

void print()
{
	printf("hello world"\n);
}

上面就是新建的头文件和源文件的代码实现,现在将这几个文件创建成一个动态库,其实思路跟静态库非常相似,要制作库,得先把源文件编译成.o文件。然后再将.o文件打包就行了。


在我们编译的时候,要加上一个fPIC(产生位置无关码)选项,下面会说。

在编译静态库的时候,通过ar -rc将.o文件打包形成一个静态库,静态库在形成的时候,g++不需要加任何选项,在形成动态库的时候,要先把文件形成.o。

这样就把刚才新增的文件变成.o文件了。

下一步就可以把.o文件打包了,ar是专门用来打包静态库的。要形成动态库,我们继续使用g++,因为g++是默认使用动态库的。

通过 g++ -shared( shared: 表示生成共享库格式 ) -o libmymethod.so *.-o可以把所有.o文件打包形成一个名为libmymethod.so的静态库。

制作的这个动态库其实是有X权限的,因为动态库也是一个可执行文件,但是他不能单独执行,需要别人来调用他。

这就是手动打包的过程。


dy-lib=libmymethod.so
static-lib=libmymath.a

.PHONY:all
all:$(dy-lib) $(static-lib)

$(static-lib):mymath.o
	ar -rc $@ $^
mymath.o:mymath.cc
	g++ -c $^

$(dy-lib):mylog.o myprint.o
	g++ -shared -o $@ $^
mylog.o:mylog.cc
	g++ -fPIC -c $^
myprint.o:myprint.cc
	g++ -fPIC -c $^

.PHONY:clean
clean:
	rm -f *.a mylib *.so *.o

.PHONY:output
output:
	mkdir -p mylib/include
	mkdir -p mylib/lib
	cp *.h mylib/include
	cp *.a mtlib/lib
	cp *.so mylib/lib

这是一个makefile文件,带static的是静态库,带dy的是动态库。

这样就可以将我自己的库给别人用了。

但是,直接编译.cc文件的话,还是不能编译的,需要加上-I -L -l这三个选项。


解决加载找不到动态库的方法:

  1. 拷贝到系统默认的库路径 /lib64
  2. 在系统默认的库路径下建立软链接
  3. 将自己的库所在的路径,添加到系统的环境变量中 LD_LIBRARY_PATH中
  4. /etc/ld.so.conf.d 建立自己的动态库路径的配置文件,然后重新ldconfig即可

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构 08】红黑树

一、概述 红黑树,是一种二叉搜索树,每一个节点上有一个存储位表示节点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个节点着色方式的限制,红黑树确保没有一条路径会比其他路径长上两倍,因而是接进平衡的。 红黑树性质: 根节点是黑色红节点的两个孩子…

《Numpy 简易速速上手小册》第10章:Numpy案例研究和实践技巧(2024 最新版)

文章目录 10.1 实际案例分析10.1.1 基础知识10.1.2 完整案例&#xff1a;天气数据分析10.1.3 拓展案例 1&#xff1a;股票价格分析10.1.4 拓展案例 2&#xff1a;信号处理 10.2 Numpy 最佳实践10.2.1 基础知识10.2.2 完整案例&#xff1a;高效数组操作10.2.3 拓展案例 1&#x…

面试题 02.07. 链表相交(力扣LeetCode)

文章目录 面试题 02.07. 链表相交题目描述解题思路c代码优化后c代码 面试题 02.07. 链表相交 题目描述 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0c;返回 null 。 图示两个链表在节点 c1 …

【轮式平衡机器人】——TMS320F28069片内外设之ADC

一、ADC概述 这一部分不是我们的重点&#xff0c;原理分类啥的这里简要说明&#xff01; 步骤&#xff1a;采样、保持、量化、编码 将采样电平&#xff08;模拟值&#xff09;转换为数字值的方法&#xff1a;直接比较型&#xff08;并行ADC、逐次逼近型ADC&#xff09;&…

通俗易懂理解注意力机制(Attention Mechanism)

重要说明&#xff1a;本文从网上资料整理而来&#xff0c;仅记录博主学习相关知识点的过程&#xff0c;侵删。 一、参考资料 大话注意力机制&#xff08;Attention Mechanism&#xff09; 注意力机制(Attention Mechanism) 深度学习中的注意力机制 注意力机制 二、注意力…

关于最小系统板PCB设计后的一些反思

简介 趁着刚刚画完板子寄回来&#xff0c;在这里做一些记录。 板子状况 这里打烊了5块PCB&#xff0c;但是没有进行SMT贴片&#xff0c;后续如果有芯片可以焊接上去进行后续验证。 封装问题 这里可以看到&#xff0c;我这里两侧的排针都是焊盘&#xff0c;不是通孔&#…

【动态规划】【字符串】【前缀和】1639通过给定词典构造目标字符串的方案数

作者推荐 【动态规划】【字符串】【行程码】1531. 压缩字符串 本文涉及知识点 动态规划汇总 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 1639. 通过给定词典构造目标字符串的方案数 给你一个字符串列表 words 和一个目标字符串 tar…

编译Opencv3.3.1遇到的编译器无法识别的警告的问题解除:

问题描述&#xff1a; 本文&#xff0c;就是在一个硬件的SDK中用到了opencv3.3.1的版本&#xff0c;在笔者目前的VS2019,CUDA11版本下编译的问题和解决。在做Cmake的configure的时候&#xff0c;Cmake报了一个找不到编译器版本的错误, Selecting windows SDK version 10.0.1904…

TOP100 矩阵

1.73. 矩阵置零 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 提示&#xff1a; m matrix.lengthn matrix[0].length1 < m, n < 200-2^31 < matrix[i][j] < 2^31 - 1 思路&#xf…

EMQX 单机及集群搭建

目录 1. 通过 Yum 源安装&#xff08;CentOS7 单机安装&#xff09; 1.1. 通过以下命令配置 EMQX Yum 源&#xff1a; 1.2. 运行以下命令安装 EMQX&#xff1a; 1.3. 运行以下命令启动 EMQX&#xff1a; 1.4. 访问 http://192.168.88.130:18083&#xff0c;默认用户名: adm…

Java项目要不要部署在Docker里?

部署Java项目有很多种方式&#xff0c;传统的方式是直接在物理机或虚拟机上部署应用&#xff0c;但为什么现在容器化部署变得越来越流行&#xff0c; 个人觉得原因有以下几个&#xff1a; 1、 环境一致性&#xff1a;使用Docker可以确保开发、测试和生产环境的一致性&#xff…

如何使用保留可探测字段参数的方法解决视频监控管理平台EasyCVR无法启动的问题

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

飞桨paddlespeech语音唤醒推理C INT8 定点实现

前面的文章&#xff08;飞桨paddlespeech语音唤醒推理C定点实现&#xff09;讲了INT16的定点实现。因为目前商用的语音唤醒方案推理几乎都是INT8的定点实现&#xff0c;于是我又做了INT8的定点实现。 实现前做了一番调研。量化主要包括权重值量化和激活值量化。权重值由于较小且…

Log4j2-24-log4j2 相同的日志打印 2 次

现象 相同的日志打印了两次&#xff0c;且因为日志的配置不同&#xff0c;导致脱敏的情况不一致。 代码与配置 代码 package com.ryo.log4j2.cfg.additivity;import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger;public class SimpleDemo…

JNPF低代码平台与其他低代码工具功能有什么不同?

JNPF低代码平台是一种新兴的技术解决方案&#xff0c;它可以帮助开发者快速构建应用程序而无需编写大量的代码。本文将深入了解JNPF低代码平台的常见类型与功能特点&#xff0c;帮助读者更好地理解和应用这项技术。 JNPF低代码平台的功能特点。首先&#xff0c;JNPF低代码平台具…

day28 回溯算法part4

93. 复原 IP 地址 中等 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 ‘.’ 分隔。 例如&#xff1a;“0.1.2.201” 和 “192.168.1.1” 是 有效 IP 地址&#xff0c;但是 “0.011…

报错 Cannot read properties of undefined(reading‘addEventListener‘)如何解决

我在制作项目中遇到了一个问题&#xff0c;给大家分享一下&#xff0c;如下图&#xff1a; 问题&#xff1a;这是我给一个input输入框绑定的监听事件出现的报错 翻译&#xff1a;无法读取未定义的属性(读取 addEventListener ) 错误原因&#xff1a;js中操作的dom元素的函数方…

知识库是什么?为什么这么多企业都在用?

在信息化的时代&#xff0c;万物互联&#xff0c;企业获取、积累和应用知识的方式也因此发生了巨大的变化。有一项重要工具正是知识库&#xff0c;许多企业和组织都在广泛地使用它。那么&#xff0c;到底什么是知识库&#xff1f;为什么它能受到广泛的接纳和应用呢&#xff1f;…

MongoDB:从容器使用到 Mongosh、Python/Node.js 数据操作(结构清晰万字长文)

文章目录 1. 容器与应用之间的关系介绍2. 使用 Docker 容器安装 MongoDB3. Mongosh 操作3.1 Mongosh 连接到 MongoDB3.2 基础操作与 CRUD 4. Python 操作 MongoDB5. Nodejs 操作 MongoDB5.1 Mongodb 和 Mongoose5.2 推荐在项目中使用 Mongoose 参考文献 1. 容器与应用之间的关系…

数据质量和数据治理的关系 | 京东云技术团队

很多不太了解的人会认为&#xff1a;数据治理就是干数据清洗的。 近两年&#xff0c;在我们公司&#xff0c;数据治理团队在数据降本方面做的比较多&#xff0c;效果还不错&#xff0c;我们很多人可能以为&#xff1a;数据治理就是做数据清理的。 在京东科技集团数据治理工作…