美文网首页c/c++
Makefile学习笔记——4.规则的命令

Makefile学习笔记——4.规则的命令

作者: tianyl | 来源:发表于2019-03-21 22:57 被阅读0次

1 前言

在前篇Makefile规则中,描述了Makefile是为了生成一个文件,该文件称为目标,而用什么命令生成这个目标,就是规则

1.1 shell命令

所以在Makefile中,规则一般都由一些shell命令行组成。规则中除了第一条命令可以紧着着依赖列表之后(使用分隔符隔开),其他的都是一行一条命令,以[Tab]字符开头,多行命令之间可以添加空行和注释

1.2 注释

执行所使用的shell决定了规则中命令和语法的处理机制,使用默认的”/bin/sh“命令行中出现的”#“是注释

2 命令回显

在make执行命令行之前,会把执行的命令行输出到标准输出设备上,即"回显",但是如果规则的命令以"@"符号开始,则make在执行命令时不会回显此命令,常见用法是使用"echo"命令

@echo 输出日志信息......
  1. 如果没有"@",那么输出的信息是
echo编译XXX模块...... 
编译XXX模块......

由于使用了"@",所以只会输出"编译XXX模块......"

  1. 如果使用参数"-n"或"-just print",那么执行时只会回显,而不执行命令(包括使用"@"开头的命令)
  2. 使用参数"-s"或"--slient"则会禁止所有执行命令的显示(等于所有命令使用"@")开头

3 命令的执行

在Makefile中,当目标需要重建时,对应规则所定义的命令将会被执行,如果是多行命令,那么每一行都在一个独立的子shell进程中执行,即多行命令相互独立,相互不存在依赖

  1. 由于每一行shell独立,所以命令行"cd"不会影响后面的命令执行,所以如果需要使用"cd"功能,那么命令就不能分行写,需要写在一行,用分号隔开,例如
foo : bar/lose
    cd bar; gobble lose > ../foo
  1. 如果实在要分行,那么用反斜线连接,例如
foo : bar/lose cd bar; \
    gobble lose > ../foo
  1. make对所有的规则命令解析使用环境变量"shell"所指定的那个程序,默认程序是"/bin/sh"

4 并发执行命令

make支持同时多命令的执行,但是通常同一时刻只有一条命令执行,不过可以通过"-j"或者"-job"来实现多命令同时执行。如果"-j"之后存在一个整数,那么表示同一时刻允许执行的命令数目(即"job slots"),如果没有数字,那么表示使用默认的"job slots",默认值为1(即串行)

并行的缺点

  1. 多命令同时执行和输出信息,错误不好定位
  2. 对应标准输入设备,同一时刻只能有一个进程访问,所以其他进程的标准输入流将无效,这话导致错误
  3. 导致make的递归调用出现问题(见7.递归执行)

在make执行过程中,如果某条命令执行失败且产生的错误不可忽略,那么其他重建同一目标的命令将终止。如果make没有使用"-k"或"--keep-going",make将停止执行且退出

make在执行时,如果由于某原因被中止,如果它的子进程正在运行,那么make将等所有子进程结束之后才退出

4.1 负荷限制

在执行make时,如果系统处于重负荷状态下,则需要减轻执行make时的负荷。通过使用"-l"可以限制make当前任务的数量。"-l"或"--max-load"选项一般跟一个浮点数
例如

-l 2.5

是指系统平均负荷高于2.5时,不再启动任何执行命令的子任务,不带浮点的"-l"用于取消前面"-l"给定的负荷限制

在每次make执行一项任务之前,make会检查当前系统的负荷,如果当前系统的负荷高于"-l"设定的值,那么make就不会在其他任务完成前启动任务

5 命令执行的错误

通常命令执行结束后,make会检查命令执行的返回状态,如果返回成功,就启动另外一个子shell来执行命令。如果某一个规则命令出错(返回非0),make会放弃当前规则的后续执行,也可能终止所有规则执行

一般情况,某一个命令的失败不代表规则执行错误,对于一些失败并不影响的命令,可以通过在命令前加"-"减号告诉make忽略执行失败的情况。

减号会在shell解析并执行之前被去掉,它是有make处理的,例如常见的

clean:
    -rm *.o

即使执行"rm"失败,也需要后续执行

当使用"-"来忽略命令执行的错误时,make会始终当做命令成功,但是会给出错误提示。使用"-k"或者"--keep-going"时,make错误不会立刻退出,这一般用在编译时确定被修改后的文件都是否能被编译通过

6 中断make的执行

如果在make执行命令时收到一个致命信号,那么make将会删除此过程中已经重建的那些规则目标。删除的原因是为了保证下一次make时目标文件能够被正确重建(因为那些已经重建的文件时间戳会更新,但是不能保证一定正确)

不过,如果目标文件是特殊目标“.PRECIOUS”的依赖,那么可以不被删除,不被删除的原因有

  1. 目标的重建动作是一个原子的不可被中断的过程;
  2. 目标文件的存在仅仅为了记录其重建时间(不关心其内容无)
  3. 这个目标文件必须一直存在来防止其它麻烦

7 递归执行

make的递归执行是:在Makefile中使用"make“命令执行本身或其他Makefile文件的过程,例如递归一个目录

subsystem:
    cd subdir && $(MAKE)

$(MAKE)是对变量"MAKE"的引用,改命令的意思是:进入子目录,然后执行make

7.1 CURDIR变量

在make递归调用时,变量"CURDIR"表示make的工作目录,当使用"-C"选项进入一个子目录后,此变量会被重新赋值,如果Makefile中没有对此变量显示赋值,那么它代表make的工作目录

7.2 MAKE变量

变量"make"的值是"make”,如果是"/bin/make",那么之前的递归命令等于"cd subdir&&/bin/make",如果使用其他版本的make程序,那么"MAKE"的值会改变

注意:当使用变量"MAKE"时,标志"-t","-n",-q"都不起作用

7.3 变量和递归

在make的递归过程中,上层make可以指明一些变量通过环境变量传递给子make,没有指明的变量将不会传递。使用环境变量传递上层定义的变量时,上层传递的变量不会覆盖子make过程中Makefile文件中的同名变量(同名变量以子Makefile变量为准)

  1. 传递使用的指示符是"export"
  2. 当一个变量用"export"声明后,变量和它的值都被加入当前工作的环境变量中,之后的make都可以使用这个变量
  3. 如果没有"export"声明,那么make只讲已经初始化的环境变量和使用命令行指定的变量传递给子make
  4. 这些变量由字符、数字和下划线组成(有些shell不能处理那些名字中包含除字母、数字、下划线以外的其他字符的变量)
  5. 特殊的变量“SHELL”和“MAKEFLAGS”,这两个变量除非使用指示符“unexport”对它们进行声明,否则默认会自动传递给所有的子make。变量“MAKEFILES”如果有值(不为空)也会被自动的传递给子make
  6. 如果"export"不带任何参数,那么此Makefile中定义的所有变量都传递给子make(新版本GNU make使用“.EXPORT_ALL_VARIABLES”代替)

8 定义命令包

在Makefile中,对于重复的命令,可以类似c语言函数一样封装,使用指示符"define"

8.1 定义

define run-yacc 
yacc $(firstword $^) 
mv y.tab.c $@ 
endef
  1. run-yacc就是命令包主体
  2. “define”和“endef”之间的命令就是命令包的主体
  3. “define”定义的命令包中,命令体中变量和函数的引用不会展开
  4. 命令体中所有的内容包括“$”、“(”、“)”等都是变量“run-yacc”的定义(类似c语言中的宏)

8.2 使用

命令包中所有命令中对其它变量的引用,在规则被执行时会被完全展开

foo.c : foo.y 
    $(run-yacc)

这里的具体含义在后续的变量相关章节中说明

9 空命令

对于只有目标文件,没有命令行的定义

target: ;

如果空命令使用独立命令行,那么必须使用[Tab]开始,所以一般不使用独立命令行

使用空命令的原因
空命令行可以防止make在执行时试图为重建这个目标去查找隐含命令(包括了使用隐含规则中的命令和“.DEFAULT”指定的命令

对于空命令最好不要指定依赖文件

相关文章

  • Makefile学习笔记——4.规则的命令

    1 前言 在前篇Makefile规则中,描述了Makefile是为了生成一个文件,该文件称为目标,而用什么命令生成...

  • Makefile自动化变量

    学习笔记,摘自陈皓的《跟我一起写 Makefile》 Makefile规则 Makefile文件由一系列规则构成。...

  • makefile编写(一)

    makefile或者Makefile 书写规则:命令就是用依赖来生成目标 目标:依赖 (tab) 命令 目录结构:...

  • meke 工具简介

    make是一个命令工具,它解释Makefile中的规则,Makefile描述了整个工程文件的编译规则和编译顺序。 ...

  • Makefile学习笔记

    Makefile学习笔记 学习Makefile的资料 《跟我一起写makefile》 《GUN make manu...

  • Makefile学习笔记——3.Makefile规则

    1.前言 在Makefile中,规则描述了用什么命令生成一个文件,该文件被称为规则的目标,生成"目标"的方式就是规...

  • makefile简述

    makefile 基本语法 目标文件:依赖文件[Tab] 命令 上述makefile语法被称为一组规则 目标文件是...

  • Shell脚本与Makefile的语法区别

    Makefile的规则是: 在Makefile中命令的部分可以调用shell脚本。但是他们的语法存在差异,很容易弄...

  • makefile写法

    makefile写法 规则 三要素: 目标 依赖 命令 语法:目标:依赖条件命令 例子: 改进: 只是编译修改的部...

  • Makefile学习

    Makefile学习 参考自《跟我一起写Makefile》陈皓 Makefile 的语法规则 基本语法 翻译成中文...

网友评论

    本文标题:Makefile学习笔记——4.规则的命令

    本文链接:https://www.haomeiwen.com/subject/iqtkvqtx.html