makefile(四):makefile规则中的命令

规则中的命令被传递给shell进行解析执行。除跟在依赖后面的第一条命令以外,其他命令必须与tab键开头。如下:

目标:依赖;命令1
    命令2

通常情况下也并不推荐这种写法,推荐的写法还是将命令1,另起一行,并以tab键开头,这样做的好处,就是便于观察,但是对于空命令除外,详见空命令一节

一.命令的回显

makefile在执行命令的时候,通常会将命令显示在标准输出中,如果不想显示在标准输出中,可以使用下面的方法
1.在每个命令的前面使用@字符串如下:

wanbiao:
    @echo $(name)

这样在执行命令的时候,就不会讲这个命令回显在标准输出中
2.使用命令行参数
在make执行的命令输入中,键入-s,–silent选项,既可,它表示所有的命令都不会回显在标准输出中。
具体使用哪一种方式,由具体是用来定,通常情况下@更加灵活
3.使用.SLIENT
给.SLIENT目标添加依赖,那么出现在依赖列表中的目标,重建的时候,将不会回显命令

二.命令的执行

由不同的tab键开始的命令符,将使用不同的shell线程,即第一行,和第二行使用的shell线程将不同,因此,第一行切换了目录之后,在第二行之后就不会再次在第一行切换的目录下,如果要在切换目录之后正常使用,则必须写在同一行中,如果想要换行,可以使用‘\’加换行符进行换行,举例如下:

all:
    cd prog
    cp -a * out

上例中,cd到prog目录之后,在第二行的cp命令执行时,并没有在prog目录下,因此如果想要达到在prog目录下,应该写在同一行中。如下

all:
    cd prog;cp -a * out

因为shell中以分号进行分割命令,因此第一个命令和第二个命令之间使用分号进行分割,如果想要写在多行中,可以使用反斜线,如下:

all:
    cd prog;\
cp -a * out

三.命令的错误

当make的命令执行错误的时候,会退出当前的执行环境,并报错。在某些时候,命令的执行错误并不影响终极目标的生成。如,rm命令,当要删除的文件已经存在,那么rm命令删除返回成功,当要删除的文件不存在,那么rm将会报错。但是对于这种错误并不影响终极目标的建立,因此我们可以忽略这种错误。makefile中忽略错误有三种方法
1.同使用@符号一样,我们使用符号-来忽略命令的错误。
2.同使用-s选项一样,我们使用-i选项和–igoner-errors来忽略所有的命令错误
3.使用.IGNORE目标来忽略后面命令执行的错误,具体用法同.SILENT类似
当遇到错误之后,make会退出,这样当遇到第一个错误就退出,后面没有执行的,就不知道是否还有错误,只有把第一个错误修改之后,才能知道后面是否有错误,这样做非常的麻烦。为了避免这种麻烦,我们可以使用在命令行中使用–keep-going,来告诉make遇到错误的时候,暂时不退出,继续执行后面的命令,直到无法继续执行后续目标的情况下才退出。这样就可以在一次修改多个源文件的情况下,最大限度的直到哪些修改还有问题。

注意:虽然使用–keep-going有好处,但是他生成的中间文件,已经被更新了时间,但是他的内容很有可能是不对的,因此在下一次make之前,请先删掉这些生成的中间文件。通常情况下,每个编译系统中,都会有一个clean的伪目标。可以直接make
clean,删除相应的中间文件。

四.定义命令包(makefile的自定义函数)

在大部分语言中,除了使用内置函数以外,还可以使用自定义函数。一个函数就是一些列执行语句的集合。在makefile中也可以定义执行语句的集合。它的格式如下:

define 变量名
执行语句
endef

注意:这里的叫做变量名,不叫做函数名,是因为在makefile的手册里面,这个语法的本质定义是定义多行变量,即上面的执行语句,是变量的值。

举例如下:

define name
wanbiao
zhangsan
lisi
endef

定义了一个变量name,它的值有三行,分别是

wanbiao
zhangsan
lisi

makefile的变量引用就相当于c语言的宏替换,因此,我们可以在这里将变量的值替换成各种执行语句,这样,配合自动化变量和内置的call函数,就实现,其他语言的函数功能了。举例如下

define catfunction
$(1)$(2).png
endef
$(warning $(call catfunction,wanbiao,20171016))

直接运行上面的代码,就能够得到如下的输出:

wanbiao20171016.png

关于call函数,和warning函数的详细描述,可以参考后面的内置函数一小节
此语法的高级特性,是配合call函数和,eval函数,实现更多具有模块化的功能。详细内容请参考后面的介绍

五.控制命令的执行

1.使用参数,进行命令的并行执行
make的选项参数中,提供了一个-j或者–job的参数选项,来控制命令的执行,使用几个线程。当没有使用这个参数的时候,默认使用一个线程。-j后面跟一个正整数,表示使用几个线程。多线程可以提高make的运行效率,但是这并不代表,线程数越多,效率越高。操作系统在线程上面的切换,需要消耗一定的资源。因此合理的分配线程数,是提供make编译效率的前提。
当我们,在编译一个项目的时候,可能需要消耗cpu和内存的很大部分资源。那么,当我们需要在同一台电脑上做其他事情,有可能非常的卡顿,因此,我们可以给make指定一个最大负载,当超过这个最大负载,make就算通过了-j指定了线程数,也不会重新创建新的线程。
使用参数-l或者–max-load加一个浮点数,来表示最大的负载。没有跟浮点数的这个参数,表示取消前面的负载限制。
2.取消命令的执行
在make执行的时候,可以按住ctrl+c键取消当前make的执行。make被中断之后,会自动的删除,创建的中间文件。这样就能保证在下一次执行的正确性。

六.make的递归执行

make的递归指的是:在命令行中使用make命令,调用其他的makefile文件。

注意:这里的递归和c语言里面的递归有些差别,c语言里面的递归是指,函数自己调用自己。

make的递归举例如下:

subsystem:
cd subdir && $(MAKE)

表示的是:进入subdir目录,然后运行make命令,其等价于下面的规则。

subsystem:
$(MAKE) -C subdir

注意:这里的变量MAKE是对make命令的一个引用,虽然这里可以直接使用make命令,但是并不推荐这种用法,有如下原因:
1.当我们在顶层make中指定了一个make程序之后,使用MAKE变量,在下层make中将会使用同一个make程序,如果不使用MAKE变量,则使用的是默认的make程序,有可以能与顶层的make程序不同。
2.当使用选项-t(–touch),-n(–just-print),-q(–question)的时候,所有的命令都不不会被执行,但是使用了MAKE变量的命令除外。一旦使用了make命令来替代MAKE变量,那么在下层makefile中,将不会被执行,对应的-t,-n,-q选项,这不是我们想要的效果。

六,变量的向下传递和截断

在顶层makefile中定义的变量,将不会被传递给底层的makefile文件中。因此完全可以命名同名的两个变量在不同层级的makefiile中。
一旦我们想要将顶层的makefile中变量传递给下层的makefile中,可以使用下面的方法:
使用export关键字,将需要传递给下一层的makefile的变量加入的环境变量中。如果下层的变量名和上层的变量名相同,并不会覆盖下层的变量名。如果想要覆盖下层的环境变量,可以使用-e(–environment-overrides)参数。

用法:export 变量

不带任何变量的export表示将所有的变量都变成环境变量,然后传递给下层makefile。如果不希望将某个变量传递给下层,可以使用unexport关键字

用法:unexport 变量

需要特别注意的是:1.通过命令行声明的变量也会传递给下层makefile中。2.MAKEFILES、MAKEFLAGS和SHELL变量始终会传递给下层makefile中,除非使用unexport关键字进行取消。
其实上面的注意中,第一项可以放置到第二项的MAKEFLAGS中,因为通过命令行参数指定的变量被存储在了MAKEOVRRIDES变量中,而MAKEOVRRIDES变量被MAKEFLAGS变量所引用。MAKEFLAGS变量的值为命令行里面的参数,但是有几个参数却不会赋值给MAKEFALGS,他们是 “-C”、“ -f”、“ -o” 和“ -W”。这几个参数的具体含义参见后面的makefile参数说明章节

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值