『Linux项目自动化构建工具』make/Makefile

news2024/9/28 17:04:21

前言

如题可知,make/Makefile为在Linux下的项目自动化构建工具;
在上一篇文章『Linux - gcc / g++』c程序翻译过程 中讲解了C/C++程序的翻译过程;
而make/Makefile即可以看成,是Makefile在使用gcc/g++使在Linux环境下能够更好的高效率的进行项目构建;
在此之前首先要对make/Makefile进行说明:

  • make
    首先,make是一条命令,也可以说通过make命令可以解析Makefile文件;
  • Makefile
    而Makefile是一个文件,是用来告诉make命令该如何编译工程,生成可执行程序;

当然,必须要现有Makefile文件才能使用make命令解析Makefile文件从而达到自动化构建项目的作用;


编写Makefile

假设存在一个.cpp文件,代码为:

#include<iostream>
//测试代码 用来测试make
int main()
{
	std::cout<<"it's a test file!"<<std::endl;
}

若是需要使该文件生成对应可执行文件即可使用命令:

g++ -o mytest test.cpp   #将程序进行翻译直到链接结束生成可执行程序为止

而现在需要一个对应的Makefile文件来使其可以自动化构建项目;
先用命令touch来建立一个Makefile文件;

touch Makefile

建立完Makefile文件后使用vim进行编辑;

mytest:test.cpp 
	g++ -o mytest test.cpp 

.PHONY:clean  
clean: 		  
	rm -rf mytest  

拥有该Makefile文件后即可使用make命令对Makefile文件进行解析从而达到构建项目的的效果;
在这里插入图片描述
当然对应的也可以进行项目的清理;
由于Makefile文件中拥有一个用来清理项目的伪目标clean,在调用时使用命令:

make clean

即可对项目进行清理,当然会根据我们在Makefile文件中所指定的规则进行清理;

在这里插入图片描述

既然如此那么在Makefile文件中的每一行分别是什么?
由上到下每一行依次分别为:

  • 第1行 - 依赖关系
mytest:test.cpp 

#以冒号:作为分界,冒号的左侧为目标文件,冒号的右侧为依赖文件列表;
目标文件即为目标生成的文件,依赖文件列表即为所生成的文件依赖的文件,在这里可以表示为,这里的可执行文件mytest是由test.cpp翻译生成的,所以依赖于test.cpp文件;
同时在Makefiel的语法中,目标文件必须在顶格,且必须跟冒号:


  • 第2行 - 依赖方法
	g++ -o mytest test.cpp #依赖方法 该行必须紧挨着第一行,不能空行,且该行必须以table键开头

#可以理解为,生成mytest可执行程序时需要依靠命令g++ -o mytest test.cpp
同时在语法中,依赖方法所在行前必须有其他依赖方法或者是紧跟依赖关系行;


  • 第4行 - .PHONY伪目标修饰
.PHONY:clean  

该关键字.PHONY的作用即为修饰 : 后的目标文件为伪目标;


  • 第5,6行
    与第1,2行相同,不同的是在这里的依赖关系中,目标文件clean不需要依赖文件;
    此处是用作清除,而在大多数的开源中所使用的清除都是用的clean;
    也可以使用其他名;
clean: 		  #该行与第一行相同,冒号左边为目标文件,右侧为依赖文件列表,不同的是该目标文件不需要依赖文件
	rm -rf mytest  #依赖方法
	#该处的四五六行是用来清理的
	#有了四五六行即可以在Makefile文件所对应的文件夹中使用 make clean 进行对应文件的清理;

在执行make命令时 , 默认使用Makefile文件中的第一对依赖关系与依赖方法;(自顶向下扫描会形成第一个遇到的目标文件)

此处若是将 形成对应文件的依赖关系依赖方法清理对应文件的依赖关系依赖方法 调换再执行make命令时;

首先将会执行 清理对应文件的依赖关系与方法 ;


.PHONY:所修饰的伪目标

在很多教材之中,对于伪目标的描述是这样的:“伪目标是总是被执行的”

但是这里的总是被执行是什么意思?
在这里插入图片描述
若是多次进行make,则只有第一次会被执行;

而后面的几次将不会被执行;

而若是执行make clean时则不同;
在这里插入图片描述
每一次的make clean都会被执行;

这个原因就是因为clean被修饰成为了伪目标;

这里的 “ 伪目标总是被执行的 ” 这句话的意思即为,伪目标总是会根据依赖关系,执行此依赖方法;

在一般的习惯中,都会将clean设置为伪目标;

若是希望其他的目标文件同样可以总是被执行,可以将其修饰为伪目标;


编译器和Makefile是如何得知可执行程序是最新的

在这里插入图片描述
在我们make了一次之后,在没有修改源文件之前再次make时都会显示一个类似于 “当前的可执行程序为最新” 的提示;
但若是在该处修改了源文件,并再次进行make指令时又会重新生成相应的可执行程序;
既然如此,那么编译器或者Makefile是如何知道当前可执行程序是最新的呢?

在Linux中有一条为 stat 的命令,该命令可以查看一个文件中最重要的三个时间;

 stat mytest

请添加图片描述
这三个时间分别为:

时间内容
(Access)访问时间访问文件的修改已经在Linux内核中进行了改动,在原先的Linux版本中,对于文件的访问(cat,ls等操作)都是会进行修改的,而这种,由于对文件的访问是一个高频操作;而文件是存在磁盘当中,若是每次访问文件都对Access进行改动的话,说明这个高频操作将会大量的去对磁盘进行访问,而高频的磁盘访问定会降低访问程序的效率;故在Linux的内核中修改为,当对文件进行一段时间的访问(累计)过后才会修改该属性;
(Modify)修改(内容)时间文件内容的修改时间;
(Change)修改(属性)时间文件属性的修改时间

回归正题,为什么编译器和Makefile能够知道当前的可执行程序是最新的;

真正来说,在使用make指令来对Makefile进行操作时,若是当前已经拥有一个可执行程序;

则会将各个源文件与当前的可执行程序进行Modify时间的比较,若是当前可执行文件的修改时间晚于各个源文件,则代表当前可执行程序为最新;

在这里插入图片描述


多文件使用Makefile

假设当前有三个文件(不包括Makefile文件),分别为两个源文件(test.cpp main.cpp)与一个头文件(test.hpp);请添加图片描述
若是用指令编译则为:

g++ main.cpp test.cpp -o test

在Makefile文件中也可以使用该指令;在这里插入图片描述

mytest:test.cpp main.cpp
	g++ main.cpp test.cpp -o mytest
	
.PHONY:clean #修饰为伪目标
clean:
	rm -f mytest

但是一般多文件进行Makefile操作时习惯使用.o进行连接;
在这里插入图片描述

mytest:test.o main.o #所生成的文件依赖test.o与main.o文件
	g++  test.o main.o -o mytest #需要生成mytest文件需要对两个.o文件进行链接(头文件被#include展开后可以不用再管)

main.o:main.cpp #make首先会看到上面第一对依赖关系与依赖方法,但是上面的依赖文件列表并没有.o文件 将会继续往下找第二对依赖关系与方法
	g++ -c main.cpp -o main.o 
test.o:test.cpp #以此类推
	g++ -c test.cpp -o test.o

.PHONY:clean
clean:
	rm -f *.o mytest    #此处删除所有的.o文件同时删除mytest文件    

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

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

相关文章

Http请求响应 Ajax 过滤器

10/10/2023 近期总结&#xff1a; 最近学的后端部署&#xff0c;web服务器运行&#xff0c;各种请求响应&#xff0c;内容很多&#xff0c;学的很乱&#xff0c;还是需要好好整理&#xff0c;前面JavaSE内容还没有完全掌握&#xff0c;再加上一边刷题&#xff0c;感觉压力很大哈…

归纳所猜半结论推出完整结论:CF1592F1

https://www.luogu.com.cn/problem/CF1592F1 场上猜了个结论&#xff0c;感觉只会操作1。然后被样例1hack了。然后就猜如果 ( n , m ) (n,m) (n,m) 为1则翻转4操作&#xff0c;被#14hack了。然后就猜4操作只会进行一次&#xff0c;然后就不知道怎么做下去了。 上面猜的结论都…

Multi-Grade Deep Learning for Partial Differential Equations

论文阅读&#xff1a;Multi-Grade Deep Learning for Partial Differential Equations with Applications to the Burgers Equation Multi-Grade Deep Learning for Partial Differential Equations with Applications to the Burgers Equation符号定义偏微分方程定义FNN定义PI…

iceberg简介004_iceberg和其他数据湖框架的对比---​​数据湖Apache Iceberg工作笔记0004

然后来看一下iceberg和其他数据湖框架的对比这里可以看到hudi支持的多一点对吧,但是 iceberg有自己的优势,并且他们都支持timeline 也就是时间旅行对吧. 然后这个图是显示了,数据湖三剑客的开源时间,以及火热程度,可以对比一下看看.

复旦管院启动科创战略,培养科技研发人才,引领未来发展!

今年夏天&#xff0c;600多位优秀的企业家成为复旦大学EMBA 2023级新生。在疫情结束后&#xff0c;他们选择百战归来再读书&#xff0c;重新回到久违的课堂&#xff0c;共同探索科创大时代下企业的商业本质&#xff0c;开启新的学习与人生旅程。复旦大学管理学院院长陆雄文教授…

只会 Windows 也能轻松搭建远程桌面 RustDesk 自用服务器

网管小贾 / sysadm.cc “哥&#xff0c;你啥时候回来啊&#xff1f;XX业务系统又出问题了&#xff01;” “情况紧急&#xff0c;老大说让你远程处理&#xff0c;总之尽快解决&#xff01;” 虽说我常年出差在外总能收到这样的消息&#xff0c;似乎早已习惯&#xff0c;但是公…

Go 语言切片扩容规则是扩容2倍?1.25倍?到底几倍

本次主要来聊聊关于切片的扩容是如何扩的&#xff0c;还请大佬们不吝赐教 切片&#xff0c;相信大家用了 Go 语言那么久这这种数据类型并不陌生&#xff0c;但是平日里聊到关于切片是如何扩容的&#xff0c;很多人可能会张口就来&#xff0c;切片扩容的时候&#xff0c;如果老…

基于安卓android微信小程序音乐播放器

运行环境 小程序前端框架&#xff1a;uniapp 小程序运行软件&#xff1a;微信开发者 后端技术:javaSsm(SpringSpringMVCMyBatis)vue.js 后端开发环境:idea/eclipse 数据库:mysql 项目介绍 音乐播放器小程序的设计主要是对系统所要实现的功能进行详细考虑&#xff0c;确定所要…

唐老师讲电赛

dc-dc电源布局要点

计算机网络 面试题

PART1 1.TCP和UDP的区别是什么&#xff1f; 2.TCP报文首部格式是什么&#xff1f; 3.TCP三次握手的过程 4.为什么TCP要三次握手&#xff1f; 5.TCP三次握手的数据报可以携带数据吗&#xff1f; 6.半连接队列是什么&#xff1f; 7.SYN 洪泛攻击是什么&#xff1f; 8.TCP…

数据库sql查询成绩第二高

select * from propro; #查询成绩第二高 select max(id) from propro where id <(select max(id) from propro); #查询成绩第二高的第二种方式 select * from (select * from propro order by id desc limit 2) as b order by id asc limit 1;

尚硅谷CSS学习笔记

什么是css css&#xff08;层叠样式表&#xff09; 它是一种标记语言&#xff0c;用于给HTML结构设置样式。简单理解css可以美化html&#xff0c;实现结构与样式的分离。 <link rel"shortcut icon" href"favicon.ico" type"image/x-icon"&g…

【SpringCloud】Nacos的安装、Nacos注册、Nacos服务多级存储模型

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 Redis 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 Nacos 一、 Nacos安装&#xff08;基于Wind…

35.树与二叉树练习(1)(王道第5章综合练习)

【所用的树&#xff0c;队列&#xff0c;栈的基本操作详见上一节代码】 试题1&#xff08;王道5.3.3节第3题&#xff09;&#xff1a; 编写后序遍历二叉树的非递归算法。 参考&#xff1a;34.二叉链树的C语言实现_北京地铁1号线的博客-CSDN博客https://blog.csdn.net/qq_547…

【【萌新的SOC学习之重新起航SOC】】

萌新的SOC学习之重新起航SOC ZYNQ PL 部分等价于 Xilinx 7 系列 FPGA PS端&#xff1a;Zynq 实际上是一个以处理器为核心的系统&#xff0c;PL 部分可以看作是它的一个外设。 我们可以通过使用AXI(Advanced eXtensible Interface)接口的方式调用 IP 核&#xff0c;系统通过 AX…

四维曲面如何画?matlab

clc; clear all [theta,phi]meshgrid(linspace(0,pi,50),linspace(0,2*pi,50)); zcos(theta); xsin(theta).*cos(phi); ysin(theta).*sin(phi); f-1*((x.*y).2(y.*z).2(z.*x).^2); surf(sin(theta).*cos(phi).*f,sin(theta).*sin(phi).*f,cos(theta).*f,f) 结果

第九天!玩转langchain!回调处理器!一篇学会日志+监控+流式传输!9/10

原文&#xff1a;第九天&#xff01;玩转langchain&#xff01;回调处理器&#xff01;一篇学会日志监控流式传输&#xff01;9/10 - 知乎 在第九篇&#xff01;跟着雄哥学langchain中的回调处理器&#xff01; 时间飞快呀~已经第九课了&#xff0c;在更新的这10天时间&#x…

电脑出现msvcp110.dll丢失的解决方法,快速解决msvcp110.dll丢失

电脑中经常会出现msvcp110.dll文件丢失的情况&#xff0c;所以如果电脑中缺失msvcp110.dll文件会让大家很苦恼&#xff0c;那么msvcp110.dll丢失有什么解决办法呢&#xff1f;今天就给大家介绍几种msvcp110.dll丢失的解决办法。 一.msvcp110.dll常出现的问题 1.当您尝试打开某…

Springcloud笔记(2)-Eureka服务注册

Eureka服务注册 服务注册&#xff0c;发现。 在Spring Cloud框架中&#xff0c;Eureka的核心作用是服务的注册和发现&#xff0c;并实现服务治理。 Eureka包含两个组件&#xff1a;Eureka Server和Eureka Client。 Eureka Server提供服务注册服务&#xff0c;各个节点启动后…

Spring AOP的失效场景

首先&#xff0c;Spring的AOP其实是通过动态代理实现的&#xff0c;所以&#xff0c;想要让AOP生效&#xff0c;前提必须是动态代理生效&#xff0c;并且可以调用到代理对象的方法什么情况下会不走代理对象的调用呢&#xff1f;首先就是类内部的调用&#xff0c;比如一些私有方…