本文详细解释了Make命令的基本用法,通过示例代码非常详细。对大家的学习或者工作都有一定的参考价值,有需要的朋友可以参考一下。
目录
一、Make II的概念。Makefile的格式2.1概述2.2目标)2.3先决条件)2.4命令III、Makefile的语法3.1注释3.2回显)3.3通配符3.4模式匹配3.5变量和赋值器3.6隐式变量)3.7自动变量)3.8判断和循环3.9函数IV .Makefile示例
一、Make的概念
Make这个词在英语中是“制造”的意思。Make命令直接用这个意思,就是制作某个文件。例如,要使文件成为a.txt,可以执行以下命令。
$ make a.txt
但是,如果您输入这个命令,它将不起作用。因为Make命令本身不知道如何制作a.txt,所以需要有人告诉它如何调用其他命令来完成这个目标。
例如,假设文件a.txt依赖于b.txt和c.txt,是后两个文件连接的产物(cat命令)。然后,make需要知道以下规则。
a.txt: b.txt c.txt
目录b.txt c.txt a.txt
也就是说,make a.txt命令的背后,其实有两步:第一步,确认b.txt和c.txt必须已经存在,第二步,使用cat命令,将这两个文件合并,作为新文件输出。
像这样的规则被写在一个名为Makefile的文件中,Make命令依赖这个文件来构建。Makefile文件也可以写成makefile,或者用命令行参数指定成其他文件名。
$ make -f rules.txt
#或者
$ make - file=rules.txt
上面的代码指定make命令是根据rules.txt文件中的规则构建的。
总之,make只是一个按照指定的Shell命令构建的工具。它的规则非常简单。您可以指定要构建的文件、它所依赖的源文件,以及当这些文件发生变化时如何重新构建它。
二、Makefile文件的格式
构建规则写在Makefile中。要学习如何制作命令,您必须学习如何编写Makefile。
2.1 概述
Makefile文件由一系列规则组成。每个规则的形式如下。
目标:先决条件
[tab]命令
上面第一行冒号前的部分叫‘target’,冒号后的部分叫‘prerequisites’;第二行必须以tab键开头,后跟“命令”。
“Target”是必需的,不能省略;“前提条件”和“命令”都是可选的,但必须至少存在其中之一。
每条规则都定义了两件事:建立目标的前提条件是什么,以及如何建立目标。下面是对每个规则的三个组成部分的详细解释。
2.2 目标(target)
目标构成了规则。目标通常是文件名,表示Make命令要构建的对象,比如上面的a.txt。目标可以是一个文件名或多个文件名,用空格分隔。
除了文件名,目标也可以是一个操作的名称,称为“假目标”。
清洁:
rm *。o
上面代码的目标是干净的。它不是文件名,而是一个操作的名称,属于‘伪目标’,用于删除目标文件。
$清洁
但是,如果当前目录中恰好有一个名为clean的文件,那么这个命令将不会被执行。因为Make发现clean文件已经存在,认为没有必要重新构建,所以不会执行指定的rm命令。
为了避免这种情况,您可以明确声明clean是一个“假目标”,如下所示。假的:干净
清洁:
rm *。o温度
clean被声明为'伪目标'后,make不会检查是否有名为clean的文件,而是在每次运行时执行相应的命令。有许多内置的目标名,如。假的。请检查手册。
如果Make命令运行时没有指定目标,默认情况下将执行Makefile的第一个目标。
$ make
上面的代码执行Makefile文件的第一个目标。
2.3 前置条件(prerequisites)
前提条件通常是一组由空格分隔的文件名。它规定了判断是否应该重建“目标”的标准:只要前文件不存在或者已经被更新(前文件的最后修改时间戳比目标的时间戳新),就需要重建“目标”。
结果. txt: source.txt
cp source.txt result.txt
在上面的代码中,构建result.txt的前提条件是source.txt如果source.txt已经存在于当前目录中,那么make result.txt可以正常运行,否则必须再写一个规则来生成source.txt。
source.txt:
echo '这是来源' source.txt
在上面的代码中,source.txt后面没有前置条件,也就是说和其他文件没有关系。只要这个文件还不存在,每次调用make source.txt都会生成。
$ make result.txt
$ make result.txt
上面的命令连续执行make result.txt两次。第一次执行会创建一个新的source.txt,然后第二次执行会创建一个新的result.txt,Make发现source.txt没有变化(时间戳晚于result.txt),所以不会执行任何操作,result.txt也不会重新生成。
如果需要生成多个文件,通常使用下面的方法。
来源:文件1文件2文件3
在上面的代码中,source是一个伪目标,只有三个前置文件,没有相应的命令。
$制作源
执行make source命令后,将同时生成三个文件:文件1、文件2和文件3。这比下面的写法方便多了。
$制作文件1
$制作文件2
$制作文件3
2.4 命令(commands)
命令指示如何更新目标文件,由一行或多行Shell命令组成。它是构建一个‘目标’的具体指令,其运行结果通常是生成一个目标文件。
每个命令行前面必须有一个tab键。如果想使用其他键,可以用内置变量声明它们。RECIPEPREFIX。RECIPEPREFIX=
全部:
回声你好,世界
上面的代码是用。RECIPEPREFIX,大于号()替换tab键。因此,每行命令的开头都变成了大于号,而不是tab键。
请注意,每行命令都是在单独的shell中执行的。这些外壳之间没有继承关系。
var-lost:
导出foo=bar
echo 'foo=[$$foo]'
上面的代码执行后(make var-lost),无法获得foo的值。因为这两行命令是在两个不同的进程中执行的。一种解决方案是在一行中写两行命令,用分号隔开。
var-keeped:
export foo=barecho 'foo=[$$foo]'
另一种解决方案是在换行符前用反斜杠进行转义。
var-keeped:
export foo=bar\
echo 'foo=[$$foo]'
最后一个方法是添加。ONESHELL:命令。ONESHELL:
var-keeped:
export foo=bar
echo 'foo=[$$foo]'
三、Makefile文件的语法
3.1 注释
井号(#)表示Makefile中的注释。
#这是评论。
结果. txt: source.txt
#这是评论。
Cp source.txt result.txt #这也是评论
3.2 回声(echoing)
正常情况下,make会打印每一条命令,然后执行,这就叫回显。
测试:
#这是一个测试
如果您执行上述规则,您将获得以下结果。
$进行测试
#这是一个测试
在命令前面添加@以关闭回显。
测试:
@ #这是一个测试
现在执行make test,将没有输出。
在构建的过程中,需要知道当前执行的是哪个命令,所以@通常只加在注释和纯echo命令的前面。
测试:
@ #这是一个测试
@echo TODO
3.3 通配符
通配符用于指定一组合格的文件名。Makefile的通配符与Bash一致,主要包括星号(*)和问号(?)和[.].比如,*。o表示后缀为o的所有文件。
清洁:
rm -f *。o
3.4 模式匹配
Make命令允许文件名通过类似的常规操作进行匹配,主要使用的匹配器是%。比如,假设当前目录下有两个源文件f1.c和f2.c,需要编译成对应的目标文件。
%.o: %。c
相当于下面的写法。
f1.o: f1.c
f2.o: f2.c
有了match%,大量相同类型的文件可以只用一个规则来构建。
3.5 变量和赋值符
Makefile允许您使用等号来自定义变量。
txt=Hello World
测试:
@echo $(txt)
在上面的代码中,变量txt等于Hello World。调用时,变量需要放在$()中。
要调用Shell变量,需要在美元符号前添加一个美元符号,因为Make命令对美元符号进行了转义。
测试:
@echo $$HOME
有时候,一个变量的值可能指向另一个变量。
v1=$(v2)
在上面的代码中,变量v1的值是另一个变量v2。这时就产生了一个问题,v1的值是在定义时扩展(静态扩展)还是在运行时扩展(动态扩展)?如果v2的值是动态的,这两种展开方法的结果可能会有很大的不同。
为了解决类似的问题,Makefile提供了四个赋值操作符(=,=,=,=),它们的区别见StackOverflow。
变量=值
#在执行时展开,允许递归展开。
变量:=值
#定义时展开。
变量?=值
#仅当变量为空时设置值。
变量=值
#将值追加到变量的末尾。
3.6 内置变量(Implicit Variables)
MAKE命令提供了一系列内置变量,比如$(CC)指向当前使用的编译器,$(MAKE)指向当前使用的Make工具。这主要是为了跨平台的兼容性。有关内置变量的详细列表,请参见手册。
输出:
$(CC) -o输出输入
3.7 自动变量(Automatic Variables)
Make命令还提供了一些值与当前规则相关的自动变量。主要有以下几种。
(1)$@
$ @指的是当前目标,即Make命令当前构建的目标。比如make foo的$ @就是指foo。
a.txt b.txt:
触摸$@
相当于下面的写法。
a.txt:
触摸a.txt
b.txt:
触摸b.txt
(2)$
$指的是第一个前提条件。例如,如果规则是t: p1 p2,那么$引用p1。
a.txt: b.txt c.txt
cp $ $@
相当于下面的写法。
a.txt: b.txt c.txt
中国石油天然气股份有限公司
(3)$?
$?指比目标更新的所有前提条件,用空格分隔。比如规则是t: p1 p2,其中p2的时间戳比T新,$?它指的是p2。
(4)$^
$表示所有前提条件,用空格分隔。例如,如果规则是t: p1 p2,那么$指的是p1 p2。
(5)$*
$ *指匹配%匹配的部分,如f1.txt中%匹配f1,$ *表示f1。
(6)$(@D) 和 $(@F)
$(@D)和$(@F)分别指向$ @的目录名和文件名。比如$ @是src/input.c,那么$(@D)的值就是src,$(@F)的值就是input.c。
(7)$(D) 和 $(F)
$(D)和$(F)分别指向$的目录名和文件名。
有关所有自动变量的列表,请参考手册。下面是一个自动变量的例子。
dest/%。txt: src/%。文本文件(textfile)
@[ -d dest ] || mkdir dest
cp $ $@
上面的代码将src目录下的txt文件复制到dest目录下。首先,确定dest目录是否存在,如果不存在,创建一个新目录。然后,$指的是前面的文件(src/%。txt),而$ @指的是目标文件(dest/%。txt)。
3.8 判断和循环
Makefile使用Bash语法完成判断和循环。
ifeq ($(CC),gcc)
libs=$(libs_for_gcc)
其他
libs=$(normal_libs)
endif
上面的代码确定当前编译器是否是gcc,然后指定一个不同的库文件。
列表=一二三
全部:
对于I以$(列表);做
echo $ $ I;\
完成的
#相当于
全部:
因为我在一二三;做
echo $ I;\
完成的
上面代码的运行结果。
一个
二
三
3.9 函数
Makefile也可以使用以下格式的函数。
$(函数参数)
#或者
$ {函数参数}
Makefile提供了许多可以调用的内置函数。下面是几个常用的内置函数。
(1)shell 函数
Shell函数用于执行shell命令。
srcfiles :=$(shell echo src/{00.99}.txt)
(2)wildcard 函数
通配符函数用于替换Makefile中Bash的通配符。
srcfiles :=$(通配符src/*。txt)
(3)subst 函数
Subst函数用于以下格式的文本替换。
$(subst from,to,text)
以下示例将字符串“felt on the street”替换为“felt on the street”。
$(subst ee,ee,街上的脚)
下面是一个稍微复杂的例子。
逗号:=,
空:=
# space变量使用两个空变量作为标识符,其中一个是空格。
空格:=$(空)$(空)
食物:=a b c
bar:=$(subst $(空格),$(逗号),$(foo))
# bar现在是` a,b,c '。
(4)patsubst函数
Patsubst函数用于替换模式匹配。格式如下。
$(patsubst模式,替换,文本)
以下示例将文件名“x.c.c bar.c”替换为“x.c.o bar.o”。
$(patsubst %)。c,%。o,x . c . c . bar . c)
(5)替换后缀名
替换后缀函数的写法如下:变量名冒号后缀的替换规则。它实际上是patsubst函数的简写形式。
最小值:$(输出:js=.min.js)
上面的代码意味着替换所有的后缀。用min.js输出变量中的js
四、Makefile 的实例
(1)执行多个目标。假的:cleanall cleanobj cleandiff
cleanall : cleanobj cleandiff
rm程序
cleanobj:
rm *。o
cleandiff:
rm *。差速器
上面的代码可以调用不同的目标删除不同后缀的文件,或者调用一个目标(cleanall)删除指定类型的所有文件。
(2)编译C语言项目
编辑:main.o kbd.o命令. o显示. o
cc -o edit main.o kbd.o命令. o显示. o
main.o : main.c defs.h
cc -c主
kbd.o : kbd.c defs.h命令
cc -c
command.o : command.c defs.h命令. h
cc -c命令
display.o : display.c defs.h
cc -c显示
清洁:
rm edit main.o kbd.o命令. o显示. o。假的:编辑干净
今天Make命令的介绍就到这里了。在下一篇文章中,我将介绍如何用Make构建Node.js项目。
这就是本文的全部内容。希望对大家的学习有帮助,支持我们。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。