告别繁琐编译!make和makefile的便捷之道

Linux系列


``

文章目录

  • Linux系列
  • 前言
  • 一、make/makefile是什么?
  • 二、make/makefile的使用
    • 2.1、语法规则
    • 2.2、依赖关系和依赖方法
    • 2.3、清理可执行文件
    • 2.4、执行依据
  • 三、循环依赖问题
  • 总结


前言

上一篇博客给大家分享了在Linux下编译源代码的两个工具,gcc和g++的使用。每次编译源代码,都要输入一串很长的指令,这个过程显然是十分复杂,且容易出错的,尤其是在一些大型的项目中,源代码可能有多个,此时编译起来就会更费劲。为了解决上面的问题,今天就给大家分享一个,Linux环境下的项目自动化构建工具——make/makefile。


一、make/makefile是什么?

一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,而make是一个命令工具,是一个解释makefile中指令的命令工具。
简单来说make是一条命令,makefile是一个当前路径的文件,两个搭配使用,完成项目自动化构建
使用make/makefile带来的好处:类似于在Windows下使用编译软件,使我们编译程序不需要再写一大串指令,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

二、make/makefile的使用

要想使用这个自动化构建工具,我们首先需要在自己工作路径下创建一个依makefile命名的文件。(文件名makefile首字母忽略大小写,所以你可能会 看到Makefile)

2.1、语法规则

下面为makefile文件内部信息

目标文件:源文件               --------依赖关系
【Tab键】 命令...             --------依赖方法

首先我们编写一个简单的程序(test.c文件),方便我们讲解、测试,下面为文件内容:

#include<stdio.h>
int main()
{
   printf("Hello Linux\n");
   printf("一个简单的c程序\n");
   return 0;
}

进入新建的makefile文件,建立依赖关系、依赖方法:
在这里插入图片描述
当我们作完这些准备工作,就可以使用make命令快速编译程序了:


这是如何实现的呢?首先我们要清楚,我们的目的是使用源文件(test.c文件),编译形成一个可执行文件(my_test.exe文件),而当我们做完makefile文件的搭配后,再使用make命令,它就会自动在当前目录下找makefile文件,根据文件中的依赖关系,执行依赖方法来形成目标文件。

这样我们就完成了快速编译的操作

2.2、依赖关系和依赖方法

将一个源文件编译得到可执行文件,这是一件具体的事情。举个例子:月底,你的生活费用完了,于是你就要给你的老爸打电话,告诉他:“老爸,我是你儿子,我没钱啦”。这个过程中,你的老爸打电话,说你是他儿子,就叫做表明依赖关系。打了电话,如果什么都没说,把电话挂了,那打电话不就没什么意义,所以让老爸给你打钱,就叫做依赖方法。因此,只有依赖关系加上依赖方法,才能完成打钱这件事情,而在这在这个例子中,你给老爸打电话就好比是make指令,钱就是目标文件,你爸就相当于源文件,打钱的过程(支付宝、微信)就是依赖方法。

依赖关系: my_test.exe : test.c
对标上面的故事,我们的目的是根据源文件的到一个可执行文件。首先我们要告诉make,要得到my_test.exe这个可执行程序,需要依赖于test.c文件。

依赖方法: my_test.exe : test.c
告诉编译器,要完成这件事情,需要对依赖的文件,执行什么操作。
这只是完成了一键编译的操作,当我们要删除不需要的可执行文件时,依然需要一点但删除,要想是编译效率更高,我们就需要不断完善makefile工具

2.3、清理可执行文件

在这里插入图片描述
对于上面的目标(clean)来说,它没有任何的依赖关系,要使用它只需要像图中所示就可以达到目的:在这里插入图片描述
这时可能你会有疑问:为什么生成可执行文件只需要make命令,而删除可执行文件需要make clean的方式呢?
其实我们也可以使用像删除可执行文件一样的方式,生成可执行文件:
在这里插入图片描述
而我们可以直接make的原因是因为,对于make来说,如果后面没有跟目标他会默认查找makefile文件中第一个依赖关系,并执行对应的依赖方法,大家可将上面两个调换一下,进行测试。

2.4、执行依据

大家在使用make对文件进行编译时,会出现编译一次后,需要更改文件内容才可再次编译的情况,这是为什么呢?
会出现下面这种情况:
在这里插入图片描述这时我们需要更改文件内容才可进行再次编译:

#include<stdio.h>
int main()
{
   printf("Hello Linux\n");
   printf("一个简单的c程序\n");
   printf("更改文件\n");
   return 0;
}

在这里插入图片描述
这是因为当我们没有更改代码时,再次编译是没有意义的,系统不会执行,这样可以提高编译效率,而这就是make编译高效的另一种方式,那么他是如何判断是否执行编译的呢?

实现高效编译的原理其实就是通过比较源文件和可执行文件的修改时间,来判断是否可以再次执行,从而避免无效的执行,具体点来说就是源文件的修改时间新于可执行文件的修改时间时,就能够再次执行make命令,生成新的可执行文件我们可以用stat指令来查看文件的时间的相关的信息:
在这里插入图片描述
上面三种时间:

  1. Access:最近访问的时间
  2. Modify:最近对文件内容做修改的时间
  3. Change:最近对文件属性做修改的时间

make的判段方式就是,将源文件的Modify时间和已存在的可执行文件的Modify时间转化为时间戳进行比较,仅当已存在的可执行文件早于源文件时make才会执行编译。
大家可以更改源文件,配合stat命令查看文件信息比较、测试。
如果想达成,不更改文件也可以一直编译的行为,我们可以采用设置伪目标的方法来实现:.PHONY:目标文件,如图:
在这里插入图片描述
这样就可以一直编译了,而’.PHONY‘的作用就是告诉make,他所修饰的目标一直被执行,不需要再做判断。
在这里插入图片描述
这样就会是我们编译不那么高效,所以我们一般不这样使用。

三、循环依赖问题

上篇文章中我们介绍过了程序编译会经历的四个过程,以及在这个过程中会生成的三个临时文件gcc的对应选项,下面我们就以这个为例,讲解循环依赖问题。
在这里插入图片描述
在这里插入图片描述我们上面说过,直接使用’make’系统会从上至下扫描‘makefile文件’并且默认执行第一个目标的依赖关系所对应的依赖方法,从上图中我们看到,当我们直接使用’make’他并‘没有’执行第一个依赖关系“my_test.exe:my_test.o”对应的依赖方法“gcc my_test.o -o my_test.exe”,这是因为make在执行第一个依赖关系是会先查找依赖文件列表是否已存在,如果存在则执行该依赖关系对应的依赖方法,否则递归进入源文件的依赖关系,先执行源文件的依赖关系生成源文件,再执行目标文件的依赖关系,生成目标文件。这就类似于栈结构,系统会帮我们自动化推导。

总结

这部分知识理解起来比较抽象,多次尝试才能深刻理解,makefile还有很多特殊符号没有介绍,大家感兴趣自行搜索。

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

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

相关文章

【鸿蒙】0x02-LiteOS-M基于Qemu RISC-V运行

OpenHarmony LiteOS-M基于Qemu RISC-V运行 系列文章目录更新日志OpenHarmony技术架构OH技术架构OH支持系统类型轻量系统&#xff08;mini system&#xff09;小型系统&#xff08;small system&#xff09;标准系统&#xff08;standard system&#xff09; 简介环境准备安装QE…

C语言初阶习题【29】杨氏矩阵

1. 题目描述——杨氏矩阵 有一个数字矩阵&#xff0c;矩阵的每行从左到右是递增的&#xff0c;矩阵从上到下是递增的&#xff0c;请编写程序在这样的矩阵中查找某个数字是否存在。 要求&#xff1a;时间复杂度小于O(N); 2. 思路 3. 代码实现1 #include<stdio.h>void fin…

Cloud Foundry,K8S,Mesos Marathon弹性扩缩容特性对比

一、Cloud Foundry 使用Scaling an Application Using App Autoscaler插件&#xff0c;基于资源使用情况触发简单扩缩容 CPU、内存、Http带宽、延时等 监控这些资源的使用情况决定扩缩容策略&#xff1a;实例是增加还是减少 Instance Limits 限制实例数量范围&#xff0c;定义…

中职网络建设与运维ansible服务

ansible服务 填写hosts指定主机范围和控制节点后创建一个脚本&#xff0c;可以利用简化脚本 1. 在linux1上安装系统自带的ansible-core,作为ansible控制节点,linux2-linux7作为ansible的受控节点 Linux1 Linux1-7 Yum install ansible-core -y Vi /etc/ansible/hosts 添加…

【BUUCTF】[GXYCTF2019]BabySQli

进入页面如下 尝试万能密码注入 显示这个&#xff08;qyq&#xff09; 用burp suite抓包试试 发现注释处是某种编码像是base编码格式 MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5 可以使用下面这个网页在线工具很方便…

迅为瑞芯微RK3562开发板/核心板应用于人脸跟踪、身体跟踪、视频监控、自动语音识别(ASR)、图像分类驾驶员辅助系统(ADAS)...

可应用于人脸跟踪、身体跟踪、视频监控、自动语音识别(ASR)、图像分类驾驶员辅助系统(ADAS)、车牌识别、物体识别等。iTOP-3562开发板/核心板采用瑞芯微RK3562处理器&#xff0c;内部集成了四核A53Mali G52架构&#xff0c;主频2GHZ&#xff0c;内置1TOPSNPU算力&#xff0c;RK…

蓝桥杯单片机基础部分——5、DS18B20温度传感器

前言 好久没有更新关于蓝桥杯单片机相关的模块了&#xff0c;今天更新一下数字温度传感器DS18B20的相关应用 单线数字温度计DS1820介绍 DS1820数字温度计提供9位(二进制)温度读数&#xff0c;指示器件的温度。信息经过单线接口送入DS1820 或从 DS1820 送出&#xff0c;因此从…

python爬虫入门(实践)

python爬虫入门&#xff08;实践&#xff09; 一、对目标网站进行分析 二、博客爬取 获取博客所有h2标题的路由 确定目标&#xff0c;查看源码 代码实现 """ 获取博客所有h2标题的路由 """url "http://www.crazyant.net"import re…

nginx 配置代理,根据 不同的请求头进行转发至不同的代理

解决场景&#xff1a;下载发票的版式文件&#xff0c;第三方返回的是url链接地址&#xff0c;但是服务是部署在内网环境&#xff0c;无法访问互联网进行下载。此时需要进行走反向代理出去&#xff0c;如果按照已有套路&#xff0c;就是根据不同的访问前缀&#xff0c;跳转不同的…

EI Scopus双检索 | 2025年第四届信息与通信工程国际会议(JCICE 2025)

会议简介 Brief Introduction 2025年第四届信息与通信工程国际会议(JCICE 2025) 会议时间&#xff1a;2025年7月25日-27日 召开地点&#xff1a;中国哈尔滨 大会官网&#xff1a;www.jcice.org 由黑龙江大学和成都信息工程大学主办&#xff0c;江苏科技大学协办的2025年第四届信…

软考高级5个资格、中级常考4个资格简介及难易程度排序

一、软考高级5个资格 01、网络规划设计师 资格简介&#xff1a;网络规划设计师要求考生具备全面的网络规划、设计、部署和管理能力&#xff1b;该资格考试适合那些在网络规划和设计方面具有较好理论基础和较丰富从业经验的人员参加。 02、系统分析师 资格简介&#xff1a;系统分…

STM32 FreeRTOS 任务挂起和恢复---实验

实验目标 学会vTaskSuspend( )、vTaskResume( ) 任务挂起与恢复相关API函数使用&#xff1a; start_task:用来创建其他的三个任务。 task1&#xff1a;实现LED1每500ms闪烁一次。 task2&#xff1a;实现LED2每500ms闪烁一次。 task3&#xff1a;判断按键按下逻辑&#xff0c;KE…

YOLO系列代码

Test-Time Augmentation TTA (Test Time Augmentation)是指在test过程中进行数据增强。其思想非常简单&#xff0c;就是在评测阶段&#xff0c;给每个输入进行多种数据增广变换&#xff0c;将一个输入变成多个输入&#xff0c;然后再merge起来一起输出&#xff0c;形成一种ens…

《自动驾驶与机器人中的SLAM技术》ch4:基于预积分和图优化的 GINS

前言&#xff1a;预积分图优化的结构 1 预积分的图优化顶点 这里使用 《自动驾驶与机器人中的SLAM技术》ch4&#xff1a;预积分学 中提到的散装的形式来实现预积分的顶点部分&#xff0c;所以每个状态被分为位姿&#xff08;&#xff09;、速度、陀螺零偏、加计零偏四种顶点&am…

docker 部署confluence

1.安装docker的过程就不说了。 2.下载镜像。 docker pull cptactionhank/atlassian-confluence:7.4.0 docker images 3.下载pojie 包。 https://download.csdn.net/download/liudongyang123/90285042https://download.csdn.net/download/liudongyang123/90285042https://do…

前端实习第二个月小结

时间飞快&#xff0c;第一次实习已经过去两个多月&#xff0c;作一些简单的总结和分享。 注&#xff1a;文章整体会比较轻松&#xff0c;提及的经历、经验仅作参考。 一、关于实习/工作内容 1、工作内容 近期做的是管理后台方面的业务&#xff0c;技术栈&#xff1a;前端re…

搭建一个基于Spring Boot的书籍学习平台

搭建一个基于Spring Boot的书籍学习平台可以涵盖多个功能模块&#xff0c;例如用户管理、书籍管理、学习进度跟踪、笔记管理、评论和评分等。以下是一个简化的步骤指南&#xff0c;帮助你快速搭建一个基础的书籍学习平台。 — 1. 项目初始化 使用 Spring Initializr 生成一个…

dl学习笔记:(4)简单神经网络

&#xff08;1&#xff09;单层正向回归网络 bx1x2z100-0.2110-0.05101-0.051110.1 接下来我们用代码实现这组线性回归数据 import torch x torch.tensor([[1,0,0],[1,1,0],[1,0,1],[1,1,1]], dtype torch.float32) z torch.tensor([-0.2, -0.05, -0.05, 0.1]) w torch.…

OpenHarmony-7.IDL工具

IDL 工具 1.openharmony IDL工具 在OpenHarmony中&#xff0c;当应用/系统服务的客户端和服务端进行IPC&#xff08;Inter-Process Communication&#xff09;跨线程通信时&#xff0c;需要定义双方都认可的接口&#xff0c;以保障双方可以成功通信&#xff0c;OpenHarmony ID…

openssl s_server源码剥离

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…