【Linux】详细介绍自动化构建工具make/makefile以及动态库的理解

server/2024/11/18 16:37:48/

目录

一、链接阶段的动态库的理解

(一)、基本概念

(二)、动态链接方式访问动态库的过程

(三)、静态链接

(四)、动态库和静态库优缺点

(五)、使用静态链接生成可执行文件:-static选项

使用ldd指令查看文件所链接的库

二、Linux项目自动化构建工具-make/Makefile

(一)、快速认识使用

1、介绍:

2、使用

(二)、解释依赖关系和依赖方法

(三)、详细介绍

1、项目的自动化清理

2、make指令使用顺序说明:

3、更改源文件也可以继续执行make

4、认识文件的三个时间(ACM时间)(stat指令可查看)

5、touch拓展小知识:

6、makefile文件的新语法:伪目标

7、makefile中定义变量和其他小知识


一、链接阶段的动态库的理解

(一)、基本概念

1、动态库文件的后缀名为 .so ,链接动态库的操作就叫动态链接。

2、静态库文件的后缀名为 .a,链接静态库的操作就叫静态链接。

3、动静态库的本质就是文件

(二)、动态链接方式访问动态库的过程

首先编译器把内存中的相应位置告诉可执行程序,然后可执行程序开始一步一步执行代码,如果执行到某些标准库里面的内容(如库函数),就会去动态库中找到相应函数源码,然后记录源码的地址(这个过程叫做库调用),记录后又将函数源码地址返回到内存当前代码位置(这个过程叫做函数返回),然后继续运行代码。这个过程就是动态链接访问动态库的过程。

因为动态库是被多个使用者共享使用,一旦缺失(不如误删库或者一些配件的更改),所有程序都不可运行了。如下:

Linux中很多指令都链接了C动态库,若该库丢失了,那么这些指令都不可以用了。

(三)、静态链接

静态链接:在链接的时候,将库中的方法拷贝到自己的可执行程序里,以后程序都不再使用第三方库。(将自己需要的代码拷贝到自己的可执行程序中)。

注意:因为要将库中代码拷贝到自己的程序里面,就会使得自己的程序会占用很大的空间,这就会比较浪费资源(占用磁盘,进入内存后开辟的空间,使用网络下载时的开销)。

(四)、动态库和静态库优缺点

动态库:

(1)、优点:比较节省资源,不会出现太多重复的代码(资源指上面提到的磁盘,内存,网络等资源)。

(2)、缺点:对库的依赖性比较强,一旦库丢失,所有使用这个库的程序都无法运行。

静态库:

(1)、优点:不依赖库,同类型平台中(如centOS不同版本)都可以直接运行使用。

(2)、缺点:可执行程序体积比较大,比较浪费资源(资源指上面提到的磁盘,内存,网络等资源)。

(五)、使用静态链接生成可执行文件:-static选项

gcc默认使用的是动态链接,想要使用静态链接需要加入选项 -static

如图分别是两个链接所产生的可执行文件,同样的代码,还只是几句C语言代码

文件大小竟然相差6倍左右。

使用ldd指令查看文件所链接的库

如图,查看test.o会提示“不是一个动态文件”,查看test1.o就会显示所依赖的库

二、Linux项目自动化构建工具-make/Makefile

(一)、快速认识使用

1、介绍:

(1)、一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的 规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
(2)、makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
(3)、make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
(4)、make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建

2、使用

make是一条命令, makefile是一个文件,两者一个是依赖关系,一个是依赖方法。
首先需要在源文件 (.c/.cpp)的目录下,新建一个名为 makefile Makefile 的文件
然后打开该文件,写入两条代码:
第一条:是依赖关系,类似给目标文件起一个名字(你是谁,我为什么要帮你)
第二条:是依赖方法,即告诉他需要进行一个什么操作(怎么帮)
如上,将第一条代码将 mybin这个名字与源文件相依赖,第二条代码进行 gcc -o的操作
配置好后在命令行使用 make 指令,这样就可以进行 gcc -o 操作生成可执行文件,生成的可执行文件名就叫 mybin
该文件就是可执行文件,可以直接运行。
若将运行的操作也配置在文件里面:
make命令就会生成可执行文件后,并运行该文件:

(二)、解释依赖关系和依赖方法

依赖关系中有两个概念:
(1)、目标文件
(2)、依赖文件列表,注意,这里是一个一列表,已空格作为分隔符。
依赖方法有个语法: 需要以tab键开头(不是空格)

(三)、详细介绍

1、项目的自动化清理

我们发现一个现象:
makefile文件配置好后,第一次执行 make文件会生成 mybin文件,但第二次再使用 make指令就会报错“ mybin已存在”,因为不可能生成两个同名文件。这时就可以使用自动化清理操作,在 makefile文件中配置自动化清理命令,如下:
再加一个依赖关系: clean,只是该目标文件可以没有依赖文件列表,然后在依赖方法中配置删除目标文件的命令, -f 选项表示强制的意思,这样不管文件存不存在,都会执行删除操作,避免过度询问。
配置好后,使用方法如下:
make后面接上目标文件名,即可执行删除操作,这样就不用手动删除 mybin文件了,可以直接通过 make命令进行删除。
问题来了,为什么第一个依赖关系使用 make指令时,后面不需要加目标文件?解释如下:

2、make指令使用顺序说明:

为了解释上面问题,我们可以观察一个现象:
我们会发现两个现象:
(1)、 makemakefile形成目标文件的时候,默认是从上到下进行扫描 makefile文件的,并且默认形成的是第一个目标文件。
(2)、默认只能形成一个。

3、更改源文件也可以继续执行make

上述是为了解决多次使用 make指令的问题,除了使用项目自动化清理( clean),也可以使用以下方法:更改源文件后也可以继续使用 make指令,如下更改 test.c文件后可以继续使用 make指令:
所以我们可以知道:
问题makemakefile怎么知道可执行程序是比较新的呐(修改过)?
这个是通过对比文件的三个时间(ACM时间)比出来的,只要可执行程序的最近修改时间比所有源文件的最近修改时间新,说明他就是最新的(没有被修改过),反之则被修改过。
举例:例如vs编译器中的“重新生成解决方案”。

4、认识文件的三个时间(ACM时间)(stat指令可查看)

有了上面问题,现在我们来分析文件的三个时间,也叫 ACM时间
访问时间、修改时间、改变时间
通过 stat 指令可以查看这三个时间:
(1)、修改时间: Modify
修改时间是受文件内容的影响而变化,如上述的改变 test.c的内容,那么修改时间就会相应变化,所以修改时间的改变是可以继续使用 make指令的。
(2)、改变时间: Change
我们会发现,有时当修改时间变化时,改变时间也会跟着变化,原因是改变时间是受文件的属性的影响,而属性的变化有时会受文件内容的影响,例如当修改文件内容时,文件的大小会发生变化,也就是文件属性发生变化。所以说改变时间的改变,也是可以继续使用 make指令的。
(3)、访问时间: Access
access时间不会轻易更新,只有具体深入访问或修改了文件后才会更新,因为访问文件内容的次数是对文件操作中占比最大的,若访问一次文件就更改一次访问时间,操作系统就会频繁访问磁盘文件,对 access时间进行修改,这就加大了系统的负担。
最后得出结论,make指令主要是受修改时间的影响!!!

5、touch拓展小知识:

使用 touch指令后,若文件不存在,则创建文件;若文件存在,则刷新文件的 acm时间。

6、makefile文件的新语法:伪目标

上面我们知道, makefile总是默认执行第一个依赖关系,并且只执行一个,那么每次都需要手动 make clean一下是非常麻烦的,所以接下来就介绍新语法解决该问题:
由上图我们学到两个知识:
(1)、 makefile中的注释是 “  #+描述内容 ”;
(2)、使用 .PHONY:目标文件名,修饰目标文件 mybin,这样 mybin就成为一个为伪目标,总是可以被执行,这样就不用考虑上述的 ACM时间问题,可以一直使用 make,但是通常是将删除操作 clean 设置成伪目标,因为删除操作是必须一直可以执行的。

7、makefile中定义变量和其他小知识

(1)、在 makefile中:“ $ ”代表目标文件,“ ^ ”代表源文件:
(2)、定义变量和使用变量的规则:
8、关于make/makefile的语法推到的理解:类似于栈

http://www.ppmy.cn/server/142956.html

相关文章

《C陷阱与缺陷》

文章目录 1、【词法陷阱】1.1 符号与组成符号间的关系1.1 与 1.3 y x/*p 与 y x/(*p),a-1 与 a - 1 与 a -1, 老版本编译器的处理是不同的,严格的ANSI C则会报错1.4 十进制的 076,会被处理为八进制,ANSI C禁止这种用法&#x…

开源vs闭源:你更看好哪一方?

开源vs闭源:你更看好哪一方? 引言 你有没有想过,在当今人工智能(AI)蓬勃发展的时代,开源大模型与闭源大模型之间的竞争竟然如此激烈?这仿佛就像是两位骑士在同一片战场上,争夺你我…

Python——飞机大战

以下是一个简单的用Python编写的飞机大战游戏的源代码: import pygame import random# 初始化游戏 pygame.init()# 设置游戏窗口的尺寸 screen_width 480 screen_height 640 screen pygame.display.set_mode((screen_width, screen_height))# 设置游戏标题 pyga…

C# 如何动态加载程序集

程序集的加载,默认是从当前目录下查找,如果当前目录查找不到,然后再去系统目录中查找,依然查找不到就会从环境变量中查找,如果依然找不到,则会抛出一个异常 FileNotFoundException。 托管代码中&#xff0…

3356. 零数组变换 Ⅱ

3356、[中等] 零数组变换 Ⅱ 1、题目描述 给你一个长度为 n 的整数数组 nums 和一个二维数组 queries,其中 queries[i] [li, ri, vali]。 每个 queries[i] 表示在 nums 上执行以下操作: 将 nums 中 [li, ri] 范围内的每个下标对应元素的值 最多 减少…

解决Anaconda出现CondaHTTPError: HTTP 000 CONNECTION FAILED for url

解决Anaconda出现CondaHTTPError: HTTP 000 CONNECTION FAILED for url 第一类情况 在anaconda创建新环境时,使用如下代码 conda create -n charts python3.7 错误原因: 默认镜像源访问速度过慢,会导致超时从而导致更新和下载失败。 解决方…

基于Java的小区家政服务预约平台

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue、Element-ui 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA/eclipse 数据…

初识Linux · 信号处理

目录 前言: 捕捉信号 再谈地址空间 谈谈键盘输入数据 理解OS正常的运行 理解系统调用 OS如何运行的 前言: 按照信号学习的时间戳,从信号的预备知识,到信号的产生,到了信号的保存,终于,我…