Makefile:从零开始入门Makefile

news2024/12/24 22:13:46

目录

        1.前言

        2.Makefile的简单介绍

        3.Makefile中的指令规则

        4.Makefile的执行流程

        5.Makefile中的变量类型

        6.Makefile中的模式匹配

        7.Makefile中的函数

        8.Makefile补充知识


前言

        在Linux中编译CPP文件,我们能够使用GCC命令进行编译,但当项目文件多且繁杂的时候,使用GCC命令就会十分的麻烦。那么有没有一个脚本文件能直接处理我们编译的过程,按照我们设置好的编译流程进行文件的编译?这就是Makefile解决的问题。而为了执行Makefile文件,我们还需要使用make命令,用于解释Makefile中的指令的命令工具


Makefile的简单介绍

        Makefile是一个文件,通常没有扩展名,包含了一系列的指令和规则,用于指导make工具如何编译和链接程序。在Makefile文件中每个规则可以指定一系列的依赖项和要执行的命令,当你修改了源代码并希望重新编译项目时,make工具会根据Makefile中的规则来决定哪些部分需要重新构建。而Makefile带来的好处是能实现“自动化编译”,一旦写好Makefile,只需要一个make命令,整个项目完全自动编译,极大的提高了软件开发的效率

        Makefile文件有以下两种:

                1.makefile 

                2.Makefile

        在构建项目的时候在哪个目录下执行构建make命令,则这个目录下的makefile文件就会执行,因此在一个项目中可以存在多个makefile文件,分别位于不同的项目目录中


Makefile中的指令规则

        在描述Makefile文件中的规则时,我们先观察下面的图片:

图1.Makefile文件的简单命令

        观察上图,我们知道了一个简单的Makefile文件中的规则是由目标,依赖和命令组成的。这些标识具体意义如下:

                1.目标

                        1.目标和规则中的命令是一一对应的

                        2.通过执行规则中的命令,生成目标文件

                        3.规则中可以有多个命令,因此可以生成多个目标

                        4.伪目标:当执行规则后不生成任何文件

                2.依赖

                        1.在规则的命令中需要使用的依赖

                        2.规则的依赖为空,则代表命令不需要任何依赖

                        3.当前规则中的依赖可以是其他规则中的目标文件

                3.命令

                        1.当前规则的执行语句,一般情况下是一个shell命令
                        2.一个规则的命令可以是多个,每个命令前必须有一个Tab缩进并且独占占一行

        在了解到Makefile文件中的指令规则的具体组成后,我们还需要知道以下几点:

                1.目标与依赖之间以":"为间隔

                2.可以存在多个目标和依赖,具体的目标与依赖之间使用","分割或者空格分割

                3.每一条命令独占一行,以一个TAB键开头,且一个规则存在多条命令

        具体可参考以下Makefile文件示例:

//多个目标文件,多个依赖,多个命令
Demo1 Demo2 : main.cpp fun.cpp
	g++ main.cpp -o Demo1
	g++ fun.cpp -o Demo2

PS:在Makefile文件中存在自动推导功能,如果依赖没有指明的化,只要当前目录符合编译条件,那么使用make指令都能成功执行Makefile文件


Makefile的执行流程

        当我们编写好Makefile文件时,我们需要使用make命令执行当前目录下的Makefile文件,在我们于终端中输入make指令并回车时,会按照以下步骤进行执行:

                步骤1:在当前目录查找Makefile文件,存在则执行步骤2,不存在则不执行

                步骤2:查看Makefile文件的规则中的依赖文件是否存在,存在则执行命令,不存在则执行步骤3

                步骤3:当规则中的依赖文件不存在时,则会遍历Makefile文件中的其他规则,寻找能生成当前依赖文件的规则,并执行

        通过以上三个步骤,我们了解了Makefile的大致的执行流程,而当我们重复执行make指令时则不会再通过以上步骤进行执行,而是执行以下几个步骤:

                步骤1:查看当前规则的目标文件是否存在,不存在则执行命令,存在则执行步骤2

                步骤2:查看当前规则的目标文件和依赖文件的修改时间,如果目标文件修改时间晚于依赖文件则不执行操作,早于依赖文件则执行步骤3

                步骤3:当目标文件的修改时间早于依赖文件,即依赖文件在生成目标文件后被修改过,则执行命令更新目标文件

        以上便是具体的Makefile的执行流程,当我们执行make指令时,我们还可以指定执行对应的规则,具体示例如下:

//Makefile文件中的内容,存在多条规则
Demo1 : main.cpp
	g++ main.cpp -o Demo1
Demo2 :  fun.cpp
	g++ fun.cpp -o Demo2

//执行指定的生成Demo2目标文件的规则
make Demo2

图2.使用make命令执行指定的规则

PS:当规则中存在多个依赖文件时,只要有一个依赖文件被修改,则会执行命令。即如果命令是编译依赖文件生成目标文件的情况,那么执行make命令则会对所有的依赖执行编译,而不是对被修改的依赖文件执行编译,会导致编译时间长


Makefile中的变量类型

        在编写Makefile文件时,常常会遇到规则中的命令过于冗长,且重复语句过多的情况,为了解决这些问题,Makefile提供了变量类型。在Makefile中变量类型分为以下几种:

        1.自定义变量

                在Makefile中使用自定义变量时,需要对变量进行初始化,不能单独声明变量,在使用变量的时候可以使用$来对变量取值(类似于PHP),具体参考以下代码:

#普通写法
Demo : main.cpp
    g++  main.cpp -o Demo
        
#使用自定义变量写法
target = Demo
reliance = main.cpp
$(target) : $(reliance)
    g++  $(reliance) -o $(target)

        2.预定义变量

                Makefile中的预定义变量是指在Makefile中已经定义的变量,可以直接使用这些变量编写脚本。预定义变量如下表:

预定义变量备注默认值
AR生成静态库库文件的程序ar
AS汇编编译器as
ARFLAGS生成静态库库文件程序无默认值
ASFLAGS汇编语言编译器的编译无默认值
CCC 编译器cc
CPPC 预编译器$(CC) -E
CXXC++编译器g++
CFLAGSC编译器的编译选项
CPPFLAGSC预编译的编译选项
CXXFLAGS C++编译器
FCFORTRAN编译器f77
FFLAGSFORTRAN编译器
RM删除文件程序rm -f

表1.预定义变量表

#普通写法
Demo : main.cpp
    g++ main.cpp -o Demo
        
#使用预定义变量写法
Demo : main.cpp
    $(CXX)  main.cpp -o Demo 

        3.自动变量

                自动变量在规则执行时自动设置,通常与当前正在处理的目标和依赖项有关,且自动变量只能在规则的命令中使用。以下是几种Makefile中的自动变量:

自动变量备注
$@表示规则中的目标文件名
$<表示规则中的第一个依赖项
$?表示规则中所有比目标新的依赖项
$^表示规则中所有的依赖项,不包括重复的
$+与 $^ 相同,但是会包括重复的依赖项
$|表示规则中所有比目标新的依赖项,不包括目标自身
$*表示不包含后缀的依赖项或目标文件名
$(@D)表示目标文件的目录
$(@F)表示目标文件的文件名

表2.自动变量表

#普通写法
Demo : main.cpp
    g++  main.cpp -o Demo
        
#使用自动变量x写法
Demo : main.cpp
	g++ $^ -o $@

Makefile中的模式匹配

        当Makefile中的规则大多数都只是因为文件不同而添加不同的规则时,我们可以把这些类似的规则写成模板(类似于C++中的模板),以下对Makefile中的模板进行讲解:

        1.在Makefile中使用"%"对字符进行匹配(类似于*通配符) 

        2.以下是一个简单的Makefile文件:

Demo : fun.o  main.o
    g++  fun.o main.o -o Demo

fun.o : fun.cpp
    g++ fun.cpp -c

main.o : main.cpp
    g++ main.cpp -c

        3.在上述代码中,我们可以发现存在两条规则相似,具体如下如图:

图3.规则相似

        4.此时我们可以使用Makefile中的模式匹配,写一个规则对以上类似的规则进行匹配:

Demo : fun.o  main.o
    g++  fun.o main.o -o Demo

#模式匹配
%.o : %.cpp
    g++ $< -c

PS:一个Makefile文件中可以存在多个模板,当依赖文件不存在时,会对模板进行查询生成文件,当多个依赖符合同一个模板时,则该模板会被执行多次


Makefile中的函数

        Makefile中的函数用于在构建过程中执行一些命令,并根据命令执行结果返回相应的值。其中存在两种格式的函数:

                1.内置函数:是由 Make 工具提供的一些预定义函数,如shell函数、subst函数、patsubst函数等

                2.自定义函数:则是用户根据需要自行定义的函数,可以根据具体情况编写不同的函数来实现自己的需求

        具体的在Makefile中使用函数的语法如下:

$(FUNCTION_NAME arguments)
UNCTION_NAME为函数名,arguments 为函数的参数

        在了解了Makefile中的函数后,我们先学习Makefile中的内置函数:

                1.wildcard函数:用于展开指定的目录

$(wildcard PATH)
PATH代表指定展开的目录

图4.wildcard函数的使用

                2.notdir函数:用于去掉文件路径

$(notdir PATH)
PATH代表去掉路径的文件

图5.notdir函数的使用

                3.patsubst函数:用于替换文件后缀

$(patsubst 更改前的后缀, 更改后的后缀, $(文件)) 

Makefile补充知识

        在第二小节曾说过伪目标,其伪目标是指当执行规则后不生成任何文件。当我们的目标文件为最新的时候,再执行make指令则会提示目标文件为最新,而使用伪目标则可以不提示这警告继续执行make指令。要使用伪目标则需要对目标文件进行伪目标的声明,如下:

.PHONY:Demo     #使用.PHNOY将目标文件声明为伪目标
Demo : main.cpp
    g++  main.cpp -o Demo

        在执行Makefile脚本的时候,可以在规则中指定强制执行命令,如下:

Demo : main.cpp
    -g++  main.cpp -o Demo
#使用"-"号表示该命令强制执行

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

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

相关文章

OpenGauss数据库-5.数据更新

第1关&#xff1a;插入数据 gsql -d postgres -U gaussdb -W "passwd123123" create table student (id integer primary key,name char(20),age integer ); insert into student values(1,"lily",20),(2,lily,21),(3,marry,19); 第2关&#xff1a;删除数…

C51学习归纳9 --- I2C通讯学习(重点)

首先&#xff0c;我自己学习过以后的直观感觉&#xff0c;通信协议是单片机的灵魂之一&#xff0c;只有规定好了通信协议我们才能够正确的接收到信息&#xff0c;才能实现更加深入的研究。所以这一部分是需要好好学习的。 本节借助一个可存储的芯片AT24C02&#xff0c;进行在I2…

仿饿了么的谁去拿外卖游戏源码

源码介绍 喝酒 没有游戏玩&#xff1f; 懒得下床 不想出去 那么好 这个游戏会 满足你! 玩法 每人都选择一个序号 4 个人为例 张三选第 ① 李四选第 ② 王五选第 ③ 赵前选第 ④ 然后就按 4 下 其中最小的数对应的序号就是他输了就去拿外卖&#xff01; 源码下载 仿饿了么…

快速开始一个go程序(极简-快速入门)

一、 实验介绍 1.1 实验简介 为了能更高效地使用语言进行编码&#xff0c;Go 语言有自己的哲学和编程习惯。Go 语言的设计者们从编程效率出发设计了这门语言&#xff0c;但又不会丢掉访问底层程序结构的能力。设计者们通过一组最少的关键字、内置的方法和语法&#xff0c;最终…

IDEA创建SpringBoot项目的时候,如何使用Java8,怎么办?

在创建springboot项目的时候,IDEA提示&#xff0c;最低Java版本要求17&#xff0c;但是实际上我们可能不需要这么高的版本&#xff0c;怎么使用Java8呢&#xff1f; 解决办法 修改Server URL地址即可&#xff1a;https://start.aliyun.com

【PHP【实战训练】系统性学习】——最经典的web端头像上传,数据库内容安全精简

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

SpringBoot个人网盘系统-计算机毕业设计源码92922

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势或改善自身的缺点&#xff0c;互联网的发展文件管理带来了福音。个人网盘系统是以实际运用为开发背景&#xff0c;运用软件工程原理和…

算法——Floyd判圈算法

介绍 Floyd判圈算法用于判断一个链表中是否有环。 思想 使用快慢指针fast, slow&#xff0c;快指针每次走两步fast fast.next.next&#xff0c;慢指针每次走一步slow slow.next。当出现fast null || fast.next null时&#xff0c;说明链表不存在环&#xff0c;如果存在环…

【python报错】关于 xlrd.biffh.XLRDError: Excel xlsx file; not supported 解决方法【已解决】

【Python报错】关于xlrd.biffh.XLRDError: Excel xlsx file; not supported解决方法【已解决】 在使用Python进行数据分析时&#xff0c;经常需要处理Excel文件。xlrd库是一个流行的用于读取Excel文件的库&#xff0c;但如果你在使用xlrd打开.xlsx文件时遇到了xlrd.biffh.XLRDE…

欢乐打地鼠小游戏html源码

这是一款简单的js欢乐打地鼠游戏&#xff0c;挺好玩的&#xff0c;老鼠出来用鼠标点击锤它&#xff0c;击中老鼠获得一积分。 欢乐打地鼠小游戏html源码

信息系统项目管理师0150:工具与技术(9项目范围管理—9.4收集需求—9.4.2工具与技术)

点击查看专栏目录 文章目录 9.4.2 工具与技术9.4.2 工具与技术 专家判断 收集需求过程中,应征求具备如下领域相关专业知识或接受过相关培训的个人或小组的意见,涉及的领域包括:可行性研究与评估;需求获取;需求分析;需求文件;以往类似项目的项目需求;图解技术;引导;冲…

这个国际档案日,大比武放榜、直播预约、课件下载,一样都不能少!

关注我们 - 数字罗塞塔计划 - 2024年6月9日第十七个国际档案日来临&#xff0c;数字罗塞塔计划放大招&#xff1a;第二届大比武活动榜单揭晓、ARCHE-2024上海智慧档案高峰论坛直播预约、2024上半年度课件大礼包下载。如此大礼&#xff0c;岂能错过&#xff1f; PART.01 榜单…

通过 Python+Nacos实现微服务,细解微服务架构

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen 背景 一直以来的想法比较多&#xff0c;然后就用Python编写各种代码脚本。很多…

【线性代数】向量空间,子空间,向量空间的基和维数

向量空间 设V为n维向量的集合&#xff0c;如果V非空&#xff0c;且集合V对于向量的加法以及数乘两种运算封闭&#xff0c;那么就称集合V为向量空间 x&#xff0c;y是n维列向量。 x 向量组等价说明可以互相线性表示 向量组等价则生成的向量空间是一样的 子空间 例题18是三位向…

4.大模型微调技术LoRA

大模型低秩适配(LoRA)技术 现有PEFT 方法的局限与挑战 Adapter方法,通过增加模型深度而额外增加了模型推理延时。Prompt Tuning、Prefix Tuning、P-Tuning等方法中的提示较难训练,同时缩短了模型可用的序列长度。往往难以同时实现高效率和高质量,效果通常不及完全微调(f…

【每日算法】

算法第15天| (二叉树part02)层序遍历、226.翻转二叉树(优先掌握递归)、101. 对称二叉树(优先掌握递归) 文章目录 算法第15天| (二叉树part02)层序遍历、226.翻转二叉树(优先掌握递归)、101. 对称二叉树(优先掌握递归)一、层序遍历二、226. 翻转二叉树(优先掌握递归)三、101. 对…

小程序中实现自定义头部导航组件

在页面中实现自定义头部导航的组件&#xff0c;如果仅是单个页面中需要自定义可在页面的json文件中配置"navigationStyle": “custom”&#xff0c;如果是项目中所有页面都想使用自定义的组件&#xff0c;可在app.json的window中全局配置"navigationStyle"…

2024-6-9

今日安排&#xff1a; 学校的课程作业windows SEH 机制简单入门windows 用户态 pwn / 内核态入门 计网实验报告 && 网安实验报告继续审计 nf_tables 源码&#xff0c;主要看 active 相关逻辑。复现 CVE-2022-32250 这个漏洞【 && iptables 相关学习】♥♥♥♥…

【车载开发系列】MCU选型

【车载开发系列】MCU选型 【车载开发系列】MCU选型 【车载开发系列】MCU选型一. 重要概念二. MCU选型的风险风险1风险2 三. MCU选型要点四. MCU选型维度五. MCU 选型需要考虑的因素1&#xff09;ROM/RAM2&#xff09;速度/主频3&#xff09;分析外设需求4&#xff09;工作电压(…

idea编码问题:需要 <标识符> 非法的类型 、需要为 class、interface 或 enum 问题解决

目录 问题现象 问题解决 问题现象 今天在idea 使用中遇到的一个编码的问题就是&#xff0c;出现了这个&#xff1a; Error:(357, 28) java: /home/luya...........anageService.java:357: 需要 <标识符> Error:(357, 41) java: /home/luya............anageService.ja…