态库、静态库之间的相互嵌套

news2025/3/1 1:12:55

本文的目的是测试各种类型库的编译后的使用效果,包括库又链接其他库的编译方法,使用方法,依赖性等。

太长不看版:请跳至文章最后的总结对比表。

一、内容包含:

①静态库libbb.a依赖静态库libaa.a的测试;

②静态库libbb.a依赖动态库libaa.so的测试;

③动态库libbb.so依赖静态库libaa.a的测试;

④动态库libbb.so依赖动态库libaa.so的测试;

aalib.h

#ifndef AALIB_H
#define AALIB_H
#include "stdio.h"
void helloAA();

#endif

aalib.cpp

#include "aalib.h"

void helloAA()
{
    printf(" lib AAAAAAAAAAAAA\n ");
}

bblib.h

#ifndef BBLIB_H
#define BBLIB_H

void helloBB();
void helloAB();

#endif

bblib.cpp

#include "bblib.h"
#include "aalib.h"

void helloBB()
{
    printf(" lib BBBBBBBBBBBBBBBB \n");
}

void helloAB()
{
    printf(" *a*******************\n");
    helloAA();
    helloBB();
    printf(" *b*******************\n");
}

main.cpp

#include "bblib.h"

int main()
{
    helloBB();

    helloAB();
}

二、测试过程

①静态库libbb.a依赖静态库libaa.a的测试

在这里插入图片描述

现在生成了静态库libaa.a和libbb.a,可以通过nm命令来查看生产的.o文件和静态链接库的内容

└──╼ $nm libaa.a                                                                                                                         

libaa.o:
0000000000000000 T helloAA
                 U printf
┌─[zhaoky@zhaoky][~/Desktop/kaiyue]
└──╼ $nm libbb.a 

libbb.o:
                 U helloAA
0000000000000011 T helloAB
0000000000000000 T helloBB
                 U puts

下面测试静态库的使用方法:

在这里插入图片描述

可以看到链接静态库的话要指定静态库依赖的静态库,否则编译不过去!由此可见轻易不要链接静态库,因为你也许不知道你要用的静态库还依赖着哪些库…

那么将所依赖的静态库编译进静态库呢?试试

在这里插入图片描述

可以看到,使用命令ar rcs libbb.a bblib.o libaa.a并没有起到作用,亦即libaa.a并没有被编译进libbb.a,因此编译可执行程序时还需要链接libaa.a。

改用下面这种方式编译,可行:

在这里插入图片描述
即编译静态库libbb.a时不要链接libaa.a而是用aalib.o文件,亦即编译静态库链接静态库时不能直接链接静态库,而是用形成该静态库的那些.o文件,可以使用 ar -x libaa.a来获取静态库的所有.o文件(注意:所有.o文件的顺序要对,被依赖的要放后面)。

②静态库libbb.a依赖动态库libaa.so的测试

在这里插入图片描述
第一行命令:gcc -o libaa.so -shared -fPIC aalib.cpp

等价于:gcc -c -shared -fPIC aalib.cpp 加 gcc -o libaa.so -shared -fPIC aalib.o 这两条(注意编译.o时要加选项-shared -fPIC,否则无法生存.so)

可以看到,编译可执行程序时只链接静态库不链接动态库编译不过去!运行时也需要动态库libaa.so支持

那么将动态库编译进静态库中呢?

那么使用nm命令来进行查看其中的内容部分,结果如下,从静态库中可以看到其中是可以看到

└──╼ $nm libaa.so                                                                                                                        
0000000000004028 b completed.7325
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000001050 t deregister_tm_clones
00000000000010c0 t __do_global_dtors_aux
0000000000003e18 t __do_global_dtors_aux_fini_array_entry
0000000000004020 d __dso_handle
0000000000003e20 d _DYNAMIC
0000000000001120 t _fini
0000000000001100 t frame_dummy
0000000000003e10 t __frame_dummy_init_array_entry
00000000000020b8 r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000002018 r __GNU_EH_FRAME_HDR
0000000000001105 T helloAA
0000000000001000 t _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U printf@@GLIBC_2.2.5
0000000000001080 t register_tm_clones
0000000000004028 d __TMC_END__
┌─[zhaoky@zhaoky][~/Desktop/kaiyue]
└──╼ $nm libbb.a 

libbb.o:
                 U helloAA
0000000000000011 T helloAB
0000000000000000 T helloBB
                 U puts

在这里插入图片描述

解释:

[zhaoky@zhaoky][~/Desktop/kaiyue]
└──╼ $nm libbb.a                                                                                                                         

libbb.o:
                 U helloAA
0000000000000011 T helloAB
0000000000000000 T helloBB
                 U puts

libaa.so:
0000000000004028 b completed.7325
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000001050 t deregister_tm_clones
00000000000010c0 t __do_global_dtors_aux
0000000000003e18 t __do_global_dtors_aux_fini_array_entry
0000000000004020 d __dso_handle
0000000000003e20 d _DYNAMIC
0000000000001120 t _fini
0000000000001100 t frame_dummy
0000000000003e10 t __frame_dummy_init_array_entry
00000000000020b8 r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000002018 r __GNU_EH_FRAME_HDR
0000000000001105 T helloAA
0000000000001000 t _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U printf@@GLIBC_2.2.5
0000000000001080 t register_tm_clones
0000000000004028 d __TMC_END__

可以看到,虽然编译静态库libbb.a的时候链接了动态库libaa.so,编译可执行程序只链接静态库libbb.a也能编译过去,但是在执行时还是要libaa.so动态库支持。

③动态库libbb.so依赖静态库libaa.a的测试

在这里插入图片描述
可以看到编译libbb.so时链接静态库出错,提示静态库需要使用-fPIC选项来编译,那就按照提示的来修改编译命令:

在这里插入图片描述
静态库所需的.o文件使用-shared -fPIC编译,然后在编译动态库的时候链接静态库好用了。并且编译可执行文件时不用链接被依赖的静态库。

来看一下这个动态库libbb.so依赖哪些库:

在这里插入图片描述
可以看到没有依赖libaa.a这个静态库。

解释:

└──╼ $nm libaa.a 

a.o:
                 U _GLOBAL_OFFSET_TABLE_
0000000000000000 T helloAA
                 U printf
┌─[zhaoky@zhaoky][~/Desktop/kaiyue]
└──╼ $nm libbb.so                                                                                                                        
0000000000004040 b completed.7325
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000001080 t deregister_tm_clones
00000000000010f0 t __do_global_dtors_aux
0000000000003e18 t __do_global_dtors_aux_fini_array_entry
0000000000004038 d __dso_handle
0000000000003e20 d _DYNAMIC
0000000000001194 t _fini
0000000000001130 t frame_dummy
0000000000003e10 t __frame_dummy_init_array_entry
0000000000002148 r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
000000000000205c r __GNU_EH_FRAME_HDR
000000000000117b T helloAA
0000000000001148 T helloAB
0000000000001135 T helloBB
0000000000001000 t _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U printf@@GLIBC_2.2.5
                 U puts@@GLIBC_2.2.5
00000000000010b0 t register_tm_clones
0000000000004040 d __TMC_END__

从动态链接库中可以看到,在动态库中已经有静库的代码

④动态库libbb.so依赖动态库libaa.so的测试

在这里插入图片描述
动态库链接动态库成功,并且编译可执行文件时也不用链接被依赖的库,但是运行时还是要两个动态库支持。

解释:

──╼ $nm libaa.so                                                                                                                        
0000000000004028 b completed.7325
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000001050 t deregister_tm_clones
00000000000010c0 t __do_global_dtors_aux
0000000000003e18 t __do_global_dtors_aux_fini_array_entry
0000000000004020 d __dso_handle
0000000000003e20 d _DYNAMIC
0000000000001120 t _fini
0000000000001100 t frame_dummy
0000000000003e10 t __frame_dummy_init_array_entry
00000000000020b8 r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000002018 r __GNU_EH_FRAME_HDR
0000000000001105 T helloAA
0000000000001000 t _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U printf@@GLIBC_2.2.5
0000000000001080 t register_tm_clones
0000000000004028 d __TMC_END__
┌─[zhaoky@zhaoky][~/Desktop/kaiyue]
└──╼ $nm libbb.so 
0000000000004038 b completed.7325
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000001070 t deregister_tm_clones
00000000000010e0 t __do_global_dtors_aux
0000000000003e08 t __do_global_dtors_aux_fini_array_entry
0000000000004030 d __dso_handle
0000000000003e10 d _DYNAMIC
000000000000116c t _fini
0000000000001120 t frame_dummy
0000000000003e00 t __frame_dummy_init_array_entry
0000000000002110 r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000002048 r __GNU_EH_FRAME_HDR
                 U helloAA
0000000000001138 T helloAB
0000000000001125 T helloBB
0000000000001000 t _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U puts@@GLIBC_2.2.5
00000000000010a0 t register_tm_clones
0000000000004038 d __TMC_END__

从libbb.so中可以看到其中已经获得了两个函数

注意:
接库libbb.a的时候用到被依赖库的.o文件 ,注意些个.o文件的依赖顺序也很重要,不能错,被依赖的要放后面。另外:编译好的动态库要指定路径,否则运行时找不到动态库的位置。

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

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

相关文章

学会分享,学会生活,分享5款简单易用的软件。

分享是一种博爱的心境,学会分享,就学会了生活。 1.在线图片编辑工具——佐糖 佐糖是一款在线免费图片编辑工具,采用AI人工智能技术,自动识别图片,支持一键抠图,更换背景,移除水印等。另外还提…

【向每个应用View中增加子控件 Objective-C语言】

一、把刚才计算九宫格的思路再给大家过一遍 1.现在我们要计算九宫格坐标 1)先把每一个格子,每一个九宫格的大小,先确定了, 在这里先指定宽和高 CGFloat appW = 75; CGFloat appH = 90; 2)再去计算第一个格子的一些间距, 到上面的间距,marginTop = 30; 再计算出…

别再花钱买 Chatgpt 资源了,这里有免费的,2 分钟上手

最近无论是打开社交网站,还是朋友圈,就连中午吃个饭都能听到大家都在聊 ChatGPT,仿佛如果这一刻你不懂这是个啥玩意儿,你就会觉得自己完全搭不上他们的话... 那ChatGPT 是什么? 百度上是这样解释的: ChatG…

最全的免费录屏工具,这 19 款录屏软件绝对值得你收藏

屏幕录制软件可让您捕获屏幕以与他人共享,创建与产品相关的视频、教程、课程、演示、视频等。这些软件是您能够从网络摄像头和屏幕录制视频。以下是精选的顶级屏幕录像机列表。 适用于 PC 的19 款免费录屏屏幕录像机软件 1)奇客免费录屏 奇客免费录屏&am…

2023家用投影仪怎么选?极米H5值得推荐

如今不管是手机还是电视都在不断向大屏幕靠近,消费者也在追求越来越大的屏幕尺寸。同时作为提升生活幸福指数的重要家居用品,投影仪正逐渐取代电视,成为消费者的首选。随着国内智能投影行业的不断发展,市面上智能投影产品也越来越…

Allegro移动器件时附带的孔和线被同步更改的原因和解决办法

Allegro移动器件时附带的孔和线被同步更改的原因和解决办法 用Allegro做PCB设计的时候,移动器件的时候,会出现附带的孔和线也会被同步更改,有时并不是期望的效果,如下图 Allegro其实将这个功能关闭即可,具体操作如下 选择Edit点击Move命令

Vulnhub 渗透练习(二)—— BILLU: B0X

环境下载 下载链接 环境搭建 直接用 vmware 打开,设为 NAT 模式。 信息收集 nmap 扫描 主机扫描: nmap -sP 192.168.200.0/24端口扫描: nmap -sV 192.168.200.129 开了一个 80 端口 apache 服务,和 ssh 服务,后…

时间轮算法概念

概述 在一些中间件中我们经常见到时间轮控制并发和熔断。 那么这个时间轮具体是什么呢,又是怎么使用的呢。 简介 其实时间轮可以简单的理解成我们日常生活中的时钟。 时钟里的指针一直在不停的转动,利用这个我们可以实现定时任务,目前lin…

c入门数的编程 拆数,构造数,c语言字符找出数字拼接,水仙花数 将一个多位数各位拆分

学会构造数和拆分数 目录 学会构造数和拆分数 1:一个三位数,求其各位数字之和 补充:将一个多位数各位拆分求和,(不知道位数怎么求) 2:串中取数(字符转数字) 3&#…

大数据之-Nifi-Nifi的应用场景1_创建并配置getfile处理器---大数据之Nifi工作笔记0004

来说一下nifi的应用场景,首先添加一个GETFILE处理器 添加以后设置处理器名称 设置处理器属性 getfile处理器的属性解释 这个加黑的是必须要选择的,非加黑的可以先不进行选择 这里我们只是设置这个input directory就可以了

是面试官放水,还是公司实在是太缺人?这都没挂,华为原来这么容易进...

华为是大企业,是不是很难进去啊?” “在华为做软件测试,能得到很好的发展吗? 一进去就有9.5K,其实也没有想的那么难” 直到现在,心情都还是无比激动! 本人211非科班,之前在字节和腾…

PMP是不是要考第七版了?

现在确实已经到第七版了,但是第六版还是需要学习的,就是结合两个版本去备考,新考纲把很多内容都缩减了,增加了敏捷管理的内容,但是第六版有很多详细的解析,所以如果你想稳一点,那么两个版本都需…

win10本地连接Xftp7时,压缩文件命名乱码解决方案

win10本地连接Xftp7时,压缩文件命名乱码解决方案1.问题如下图所示:2.解决方案如下: (1)如上所展示的问题,是因为所默认选则的语言是中文,计算机直接编译返回。 (2)修改属性中的选项中的编码语言&#xff0c…

Spring的概述

Spring框架是为解决企业应用开发的复杂性而诞生,它简化了Java应用开发,提高了应用开发的可测试性和可重用性。 Spring的核心理念是控制反转(IoC),其通过依赖注入(DI)的方式来实现控制反转。 Ja…

XQuery 简介

XQuery 简介 解释 XQuery 最佳方式是这样讲:XQuery 相对于 XML 的关系,等同于 SQL 相对于数据库表的关系。 XQuery 被设计用来查询 XML 数据 - 不仅仅限于 XML 文件,还包括任何可以 XML 形态呈现的数据,包括数据库。 您应该具备的…

我用python疯狂爬取公司数据

我是半路从一个纯小白学过来的,学习途中也掉过许多坑,在这里建议新手要先把基础打扎实,然后再去学习自己需要的内容,不要想着全部学完再用,那样你是永远学不完的,用哪方面就学习哪方面的内容,不…

Vue常用的修饰符有哪些有什么应用场景

Vue常用的修饰符有哪些有什么应用场景Vue常用的修饰符有哪些有什么应用场景一、修饰符是什么二、修饰符的作用表单修饰符lazytrimnumber事件修饰符stoppreventselfoncecapturepassivenative鼠标按钮修饰符键盘修饰符v-bind修饰符asyncpropscamel三、应用场景参考文献Vue常用的修…

Linux多线程开发

一、线程 1、线程概述 与进程(process)类似,线程(thread)是允许应用程序并发执行多个任务的一种机制。一个进程可以包含多个线程。同一个程序中的所有线程均会独立执行相同程序,且共享同一份全局内存区域…

Power BI: NATURALINNERJOIN的使用

查看官方的文档&#xff0c;NATURALINNERJOIN描述是这样的&#xff1a;语法NATURALINNERJOIN(<LeftTable>, <RightTable>) 参数术语定义LeftTable用于定义联接左侧的表的表表达式。RightTable用于定义联接右侧的表的表表达式。返回值一个表&#xff0c;仅包含两个…

张俊林:由ChatGPT反思大语言模型(LLM)的技术精要

ChatGPT出现后惊喜或惊醒了很多人。惊喜是因为没想到大型语言模型&#xff08;LLM,Large Language Model&#xff09;效果能好成这样&#xff1b;惊醒是顿悟到我们对LLM的认知及发展理念&#xff0c;距离世界最先进的想法&#xff0c;差得有点远。我属于既惊喜又惊醒的那一批&a…