【Linux】自动化构建工具-make/Makefile
个人主页 : zxctscl
如有转载请先通知
文章目录
- 1. 前言
- 2. 认识make/Makefile
- 3. 了解make/Makefile原理
- 3.1 依赖关系和依赖方法
- 3.2 make检测的顺序
- 3.3 PHONY:XXX
- 4. makefile内置符号
1. 前言
在上一篇中已经了解了【Linux】编译器-gcc/g++使用,这次来一起看看make/Makefile。
2. 认识make/Makefile
make是一个命令
makefile是一个文件。
先touch一个makefile/Makefile(m大小写都可以)文件:
然后进入makefile写一段代码:
未来形成的可执行程序是mytest,依赖的是test.c。就是将test.c编译形成mytest的可执行程序。
直接make编译一下:
因为版本比较低,这里提示要加上-std=c99。重新打开makefile加上就行:
此时在重新make一下就有了:
会自动形成我们要的可执行程序mytest
如果想要清理编译产生的临时文件怎么办?
再次打开makefile:
退出后直接用命令清理一下
make clean
发现mytest已经没有了:
-
makefile文件中,保存了编译器和链接器的参数选项,并且描述了所有源文件之间的关系。
-
- make程序会读取makefile文件中的数据,然后根据规则调用编译器,汇编器,链接器产生最后的输出。
-
Makefile里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释。
显式规则说明了,如何生成一个或多个目标文件。 -
make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写makefile,比如源文件与目标文件之间的时间关系判断之类
-
在makefile中可以定义变量,当makefile被执行时,其中的变量都会被扩展到相应的引用位置上,通常使用 $(var) 表示引用变量文件指示。包含在一个makefile中引用另一个makefile,类似C语言中的include;
-
注释,makefile中可以使用 # 在行首表示行注释
-
默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件,
3. 了解make/Makefile原理
打开Makefile,来看看前面两行:
写好Makefile后,当我们实际是在运行make时候:对应的程序就会在当前程序找makefile,然后读取makefile里面的内容,根据依赖关系,知道test.c形成mytest这样的可执行程序,根据gcc写的依赖方法来执行。
make会根据makefile的内容,完成编译或者清理工作。
3.1 依赖关系和依赖方法
怎么理解依赖关系和依赖方法呢?
举个例子:在现实生活中求人办事,就先得和他们产生某种关系,然后才会有后面的方法。就像小明没有生活费了,向他父亲打电话,就说一句:我是你儿子。这个就表明了依赖关系。表明了依赖关系然后,小明想要做什么?所以小明重新打电话说:我是你儿子,没钱了,打点钱。就有了依赖方法。
计算机要形成某种可执行程序,就得先表明依赖关系,然后怎么具体形成可执行程序,这就要有具体依赖方法。
依赖关系和依赖方法是完成一件事情的必然要素,并非makefile特有的。
这里clean:是一种特殊的依赖关系,这个clean不依赖任何一个文件,是一种特殊情况。
所以说依赖文件列表可以为空。
3.2 make检测的顺序
在形成可执行程序的时候直接make就可以直接形成mytest,而不是执行clean?
要执行clean,就必须这样写make clean
也可以用make mytest
这样去运行:
makefile它的运行推导规则是:默认从上到下,对makefile文件进行扫描,默认形成第一个目标文件。也就是只有make的时候,默认形成第一个目标文件。
如果把clean放在前面,那么默认先执行的就是clean:
发现直接make的时候先执行的clean:
默认将执行的可执行程序放在前面,这样make的时候就能直接形成了。
所以make检测的顺序是从上往下的。
3.3 PHONY:XXX
当我们在程序里面不加上:
来make一下后,在make一下,发现就不行了:
在程序不被修改时,make后,默认就不会在形成新的可执行程序,它认为没有必要。
如果想要makefile里面的操作总是被执行,不要因为是最新的就拦截,就加上:.PHONY:mytest
make多少次都会执行,没有拦截。
.PHONY:XXX
XXX对应的方法,总是要被执行。
一般可执行程序不需要.PHONY:修饰,但是我们总是希望clean重新清理。
默认将clean用.PHONY:修饰:
要然清理工作总是被执行。
为什么makefile对最新的可执行程序,默认不重新形成呢?
如果在一个项目里面存在上千个源文件,每次改代码时候,可能就修改一小部分。做了改动之后,如果每一次都把所以的源文件重新编译一遍,就会带来效率的延缓。还有可能出现在没有修改情况下,一编译就重新执行,上千个文件,在编译的时候又得重新编译,又得花费很长时间。既然形成的可执行程序都是新的,那么就不需要再重新编译。
就是为了提高编译效率。
那么是怎么做到不重新执行的呢?换句话说makefile怎么知道我的程序需要被编译呢?
这里有一个Modify:文件的最新修改时间:
源代码和可执行程序最近一次形成或者修改的时间一定是不一样的。
每一次都是先写源代码再形成可执行程序。
最终要判断程序是否被编译:只要对比,可执行文件最近修改的时间和源文件最近修改的时间,谁更新。
可执行程序最新就不需要再编了,源文件最新就重新编译一下。
这里源文件没有更新,就不能再编译:
来修改一下test.c的Modify时间:
touch test.c
make一下就又可以编了:
4. makefile内置符号
$:相当于取内容。
^:代表整个依赖文件列表,就是这里的code.c
@:代表目标文件,就是这里的code.exe
在编译的时候makefile会自动进行符号替换,把@替换为目标文件,^替换为code.c:
make之后,执行一下code.exe:
在把它清理掉:
把makefile如果要把它写全,就是这样的:
实际上编译器可以直接一步到位。
上面有4组依赖关系,就有依赖方法:
1 code.exe:code.o2 gcc code.o -o code.exe -std=c993 code.o:code.s4 gcc -c code.s -o code.o -std=c995 code.s:code.i6 gcc -S code.i -o code.s -std=c997 code.i:code.c8 gcc -E code.c -o code.i -std=c99
在make后,在makefile里面写的代码重新编译了,编译后,依此形成了临时文件,并且形成了最终的可执行程序:
运行一下:
重新进入makefile:
1 code.exe:code.o2 gcc code.o -o code.exe -std=c993 code.o:code.s4 gcc -c code.s -o code.o -std=c995 code.s:code.i6 gcc -S code.i -o code.s -std=c997 code.i:code.c8 gcc -E code.c -o code.i -std=c999 .PHONY:clean10 clean:11 rm -f code.i code.s code.o code.exe
此时code.i code.o code.s code.exe都被清理了:
发现执行的顺序和makefile里面代码顺序是相反的。
当make
拿到makefile
文件时候,从上往下扫描,先看到的文件是code.exe
,先识别的依赖关系是code.exe:code.o
,但是发现code.o并不存在,所以 gcc code.o -o code.exe -std=c99
是不执行的。
然后继续找下一组依赖关系:code.o:code.s
,发现code.s
并不存在,所以不执行这个依赖方法。
一直这样找,直到code.i:code.c
,这个code.c
是存在的,那么就会执行这一组依赖关系的依赖方法: gcc -E code.c -o code.i -std=c99
。那么就形成了code.i
。code.i
形成了,再回到code.s:code.i
执行他的依赖方法gcc -S code.i -o code.s -std=c99
。一直像这样,直到形成code.exe
。
makefile/make 会自动根据文件中的依赖关系,进行自动推导,帮助我们执行所有相关的依赖方法。
这些依赖关系就像栈一样,出栈执行方法:
如果注释调最后一组依赖关系:
就会出现没有规则去制作code.i
,code.i
不存在,那么code.s
也就不存在。
如果乱序排这些依赖关系:
能正常执行:
那么如果让第一个依赖关系放在后面呢:
此时make就不能执行:
因为makefile必须把最重要的文件放在前面,总的有个开头。一定要保证最终实现的目标文件是第一个。
那么之后我们写makefile就要这样写吗?
其实没有必要这样写。直接这样写就行:
1 bin=code.exe2 src=code.c34 $(bin):$(src)5 gcc -o $@ $^ -std=c996 .PHONY:clean7 clean:8 rm -f $(bin)
这样也是可以执行的:
这里定义的变量就相当于宏。要改形成的可执行程序,就只改前面这两行的文件名就行。
举个例子:
重新make一下:
如果不想在执行命令的时候出现提示出像下面这样的命令的内容:
不想显示出这些命令,那么就在这些命令前面加上@:
此时发现已经不显示了:
一般我们所使用不仅仅只有一个依赖方法,可以继续往后跟:
有问题请指出,大家一起进步!!!
相关文章:

【Linux】自动化构建工具-make/Makefile
个人主页 : zxctscl 如有转载请先通知 文章目录 1. 前言2. 认识make/Makefile3. 了解make/Makefile原理3.1 依赖关系和依赖方法3.2 make检测的顺序3.3 PHONY:XXX 4. makefile内置符号 1. 前言 在上一篇中已经了解了【Linux】编译器-gcc/g使用,这次来一起…...
week07day03(power bi dax公式 零售数据业务分析)
一. 切片器(筛选)相关的三个函数 1.all (all后面的数据意思是 不受其影响) #ALL 筛选的是 筛选器 或 切片器#计算 销售金额 ,并且 不受到 门店ID 控制 计算金额 CALCULATE(SUM(销售表[金额]),ALL(销售表[门店ID]))#计算 销售金额 &#x…...

rembg报错onnxruntime_providers_tensorrt.dll
报错: 2024-03-16 04:16:59.4413827 [E:onnxruntime:Default, provider_bridge_ort.cc:1534 onnxruntime::TryGetProviderInfo_TensorRT] D:\a_work\1\s\onnxruntime\core\session\provider_bridge_ort.cc:1209 onnxruntime::ProviderLibrary::Get [ONNXRuntimeErro…...

精酿啤酒:一口啤酒,一份享受
在繁华的都市生活中,我们总是匆匆忙忙,追求着各种目标和成就。然而,在这个过程中,我们往往忽略了生活的本质,那就是享受。而Fendi Club 啤酒,正是为那些追求品质生活的都市精英们量身打造的。 Fendi Club啤…...

git报: “fatal: detected dubious ownership in repository“
“fatal: detected dubious ownership in repository”的中文翻译是:“致命错误:检测到仓库中存在可疑的所有权问题”。 这句话意味着 Git 在检查代码仓库时发现所有权存在问题,可能是由于文件或目录的所有权与 Git 仓库预期的所有权不匹配。…...

代码随想录算法训练营第27天|93.复原IP地址、78.子集、90.子集二
目录 一、力扣93.复原IP地址1.1 题目1.2 思路1.3 代码1.4 总结 二、力扣78.子集2.1 题目2.2 思路2.3 代码2.4 总结 三、力扣90.子集二3.1 题目3.2 思路3.3 代码3.4 总结 一、力扣93.复原IP地址 (比较困难,做起来很吃力) 1.1 题目 1.2 思路 …...

Java微服务轻松部署服务器
我们在日常开发微服务之后需要再服务器上面部署,那么如何进行部署呢,先把微服务的各个服务和中间件以及对应的端口列举出来,都打包成镜像,以及前端代码部署的nginx,使用docker-compose启动,访问服务器nginx…...

Wordpress站点通过修改.htaccess 设置重定向实现强制 https 访问
要在WordPress站点上通过修改.htaccess文件实现强制HTTPS访问,您可以按照以下步骤进行操作: 登录到WordPress站点管理后台。 在文件管理器或通过FTP访问网站根目录,找到并打开名为 .htaccess 的文件。 在打开的文件中添加以下代码…...

人大金仓助力国家电网调度中心培养国产数据库专家人才
近日,为进一步提升调度自动化安全可靠水平,提高电网数据应用效能,人大金仓助力国家电网调度中心培养国产数据库专家人才。 调度自动化系统拥有海量电网数据资源,是支撑电网安全经济优质运行的重要保障。数据库是调度自动化系统稳定运行的基石之一,其结构严谨、运行稳定、扩展灵…...

什么是增强型SSL证书?购买一张需要多少钱?
增强型SSL证书是一种提供更高级别安全验证与用户信任度的网络安全工具,也被称为EV证书。相较于DV(域名验证)和OV(组织验证)证书,它通过严格的身份核实流程确保网站所有者的合法性和真实性。 首先࿰…...

C++:函数传参到函数执行结束发生了什么
首先要明确两个概念 函数实参的入栈从右向左栈区从高地址向低地址偏移 接下来看下面一段代码 void fun(int a,int b,int c){std::cout<<&a<<" "<<&b<<" "<<&c<<std::endl; } int main(){fun(1,2,3); }…...

QT中dumpcpp以及dumpdoc使用
qt中调用COM的方式方法有四种,参考解释在 Qt 中使用 ActiveX 控件和 COM (runebook.dev) 介绍dumpcpp的使用方法Qt - dumpcpp 工具 (ActiveQt) (runebook.dev): 在安装好了的qt电脑上,通过powershell窗口来实现,powershell比cmd要…...

RPM与DNF的操作实践
这几课有三个目标: 第一步:先配置软件源 跳转到yum.repos.d目录,用vim创建一个openeuler_x84_64.repo文件。这个文件就是我们将会用到的软件源。 我们在里面添加这些东西,保存并退出即可。 然后,我们用yum list all就…...

车道线检测之LaneNet
论文:Towards End-to-End Lane Detection: an Instance Segmentation Approach Github:https://github.com/MaybeShewill-CV/lanenet-lane-detection?tabreadme-ov-file 论文提出一种车道线检测网络LaneNet,该网络以enet为主干网络结构&…...

MySQL连接数不足导致服务异常GetConnectionTimeoutException
文章目录 场景复现解决方案一、调整连接数二、优化程序 场景复现 已经上线正常运行的项目突然很多功能无法使用,查看程序日志发现MySQL报错,异常信息: Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.Ge…...

软考76-上午题-【面向对象技术3-设计模式】-创建型设计模式01
一、创建型设计模式一览 二、创建型设计模式 2-1、创建型设计模式的概念 一个类创建型模式使用继承改变被实例化的类; 一个对象创建型模式将实例化委托给另一个对象。 对应java的new一个对象。 2-2、简单工厂模式(静态工厂方法) 简单工厂…...

Matlab 双目相机标定(内置函数)
文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 相机标定的目的就是要找到从世界坐标转换为图像坐标所用到的投影P矩阵各个系数(即相机的内参与外参)。具体过程如下所述: 1、首先我们需要获取一个已知图形的图像(这里我们使用MATLAB所提供的数据)。 2、找到同…...

【博客7.4】缤果Qt5_TWS串口调试助手V2.0 (高级篇)
超级好用的Qt5_TWS耳机串口调试助手 开发工具: qt-opensource-windows-x86-5.14.2 (编程语言C) 目录 前言 一、软件概要: 二、软件界面: 1.App演示 三、获取 >> 源码以及Git记录: 总结 前言 串口调试助手支持常用的50bps - 10M…...

CSS案例-4.padding导航栏练习
效果 相关数据: 上边框:3px,颜色#ff8500 下边框:1px,颜色#edeef0 背景颜色:#fcfcfc 高度:41px 内边距20px 字体颜色#4c4c4c 知识点 盒子边框border 属性 作用 border-width 定义边框粗细,单位px border-style 边框的样式 border-color 边框颜色 边框样式...
5.1.4.2、【AI技术新纪元:Spring AI解码】Llama2 Chat
Llama2 Chat Meta 的 Llama 2 Chat 是 Llama 2 系列大型语言模型的一部分。它在基于对话的应用程序中表现出色,参数规模范围从 70 亿到 700 亿不等。利用公共数据集和超过 100 万次人类注释,Llama Chat 提供了上下文感知的对话。 通过从公共数据源获取的 2 万亿标记进行训练…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...

PydanticAI快速入门示例
参考链接:https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...

VASP软件在第一性原理计算中的应用-测试GO
VASP软件在第一性原理计算中的应用 VASP是由维也纳大学Hafner小组开发的一款功能强大的第一性原理计算软件,广泛应用于材料科学、凝聚态物理、化学和纳米技术等领域。 VASP的核心功能与应用 1. 电子结构计算 VASP最突出的功能是进行高精度的电子结构计算ÿ…...

Modbus转Ethernet IP深度解析:磨粉设备效率跃升的底层技术密码
在建材矿粉磨系统中,开疆智能Modbus转Ethernet IP网关KJ-EIP-101的应用案例是一个重要的技术革新。这个转换过程涉及到两种主要的通信协议:Modbus和Ethernet IP。Modbus是一种串行通信协议,广泛应用于工业控制系统中。它简单、易于部署和维护…...
结合PDE反应扩散方程与物理信息神经网络(PINN)进行稀疏数据预测的技术方案
以下是一个结合PDE反应扩散方程与物理信息神经网络(PINN)进行稀疏数据预测的技术方案,包含完整数学推导、PyTorch/TensorFlow双框架实现代码及对比实验分析。 基于PINN的反应扩散方程稀疏数据预测与大规模数据泛化能力研究 1. 问题定义与数学模型 1.1 反应扩散方程 考虑标…...

成工fpga(知识星球号)——精品来袭
(如需要相关的工程文件请关注知识星球:成工fpga,https://t.zsxq.com/DMeqH,关注即送200GB学习资料,链接已置顶!) 《孩子都能学会的FPGA》系列是成工完成的第一个系列,也有一年多的时…...

CKA考试知识点分享(2)---ingress
CKA 版本:1.32 第二题是涉及ingress相关。本文不是题目,只是为了学习相关知识点做的实验。 1. 环境准备 需要准备一套K8S集群。 1.1 安装ingress-nginx 下载deploy文件: wget -O controller-v1.12.2.yaml https://raw.githubusercontent…...