makefile 中竖线 “|” 管道符的作用

在makefile中,有时会在依赖关系中看到竖线“|”管道符,它是作用是用来指示命令前提目标 order-only prerequisites

1. makefile基本语法复习

这里,我们简单复习一下makefile基本语法。其中的[TAB]就是键盘上的Tab键,不可以用空格替代。

target : prerequisites  
[TAB]command1  
[TAB]command2  
[TAB]...  
[TAB]commandN  

其中,
target,称为生成目标。可以是Object File,也可以是执行文件,还可以是一个标签(Label)。
prerequisites ,称为前提目标。
command*,是make需要执行的命令,任意的Shell命令。

2. 命令前提目标 order-only prerequisites

在makefile中,有时会在依赖关系中看到竖线“|”管道符,它是作用是用来指示命令前提目标 order-only prerequisites

事实上make工具能理解两种类型的前提目标:
Type I: 正常前提目标(normal prerequisites)
正常前提目标能达成两个目的:
 i. 影响build command执行顺序,即:在生成目标(target)的命令被执行前,所有的需要生成的前提目标(prerequisites)的命令都需要被执行。
ii. 影响依赖关系,即:如果任何一个前提目标(prerequisites)比生成目标(target)新时,生成目标都将被认为太旧而需要被重新生成。
通常,上面的这两个目的正是你所需要的:当前提目标更新时,生成目标也需要更新。

Type II: 命令前提目标(order-only prerequisites)
偶尔的,我们会遇到这样的情况:我们需要执行某个或某些规则,但不能引起生成目标(target)被重新生成。此时你就需要使用命令前提目标。命令前提目标由一个管道符号即竖线“|”指示,位于前提目标列表中。竖线左边的目标就是正常前提目标,竖线右边的目标就是命令前提目标,形式如下:

target : normal-prerequisites | order-only-prerequisites

注1:竖线“|”左边的正常前提目标列表可以是空。
注2:如果前提目标中同时存在正常前提目标和命令前提目标,则正常前提目标(normal prerequisites)优先生成。
注3:规则依赖文件列表中如果一个文件同时出现在常规列表和“order-only”列表中,那么此文件被作为常规依赖处理。
注4:只有在生成目标文件不存在时,命令前提目标才会参与规则的执行。
         但是,当生成目标文件存在时,命令前提目标不会参与规则的执行。

3. 例子

3.1. 例子1:

LIBS = libtest.a
foo : foo.c | $(LIBS)
    $(CC) $(CFLAGS) $< -o $@ $(LIBS)

make在执行这个规则时,如果生成目标文件“foo”已经存在。当“foo.c”被修改以后,目标“foo”将会被重建。但是,当“libtest.a”被修改以后,将不执行规则的命令来重建目标“foo”。
就是说,规则中命令前提目标$(LIBS)只有在生成目标“foo”文件不存在的情况下,才会参与规则的执行。当目标文件存在时此依赖不会参与规则的执行过程。

3.1. 例子2:
创建如下三个文件
在这里插入图片描述
func.c,main.c内容随意,保证编译通过就行。
makefile内容如下:(makefile没有什么实际意义,仅仅为了演示命令前提目标的用法)

TEST_DIR=dirTest
all:main.o                                     //规则1
	@echo "this is all"
main.o : main.c func.o | ${TEST_DIR}           //规则2
	@echo "gcc process"
	gcc -c main.c -o $@
func.o : func.c                                //规则3
	@echo "func gcc process"
	gcc -c func.c -o $@
${TEST_DIR}:                                   //规则4
	@echo "creat the dirTest directory"
	mkdir -p dirTest

测试1:直接make all
在这里插入图片描述

从make命令的输出log可以看出,五个规则的执行顺序是:规则3 --> 规则4 --> 规则2 --> 规则1。这个顺序,刚刚好证明了第1节中“注2”的说明,正常前提目标(normal prerequisites)优先生成。
执行make all后,当前路径内容如下:
在这里插入图片描述
测试2:修改func.c的内容,然后再执行make all
在这里插入图片描述
因为func.o是常前提目标(normal prerequisites),则修改了func.c,规则3 --> 规则2 --> 规则1 又重新执行了一遍。

测试3:在dirTest文件夹里新建一个文件,然后再执行make all
在这里插入图片描述
因为dirTest是命令前提目标(order-only prerequisites),虽然修改了dirTest,但是只有规则1被执行了,规则2并没有被执行。
可以看出,dirTest的改动,并没有影响规则2的执行。

测试4:删掉main.o,然后再执行make all
在这里插入图片描述
删掉了main.o后,规则2被执行了。

  • 11
    点赞
  • 17
    收藏
  • 打赏
    打赏
  • 1
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论 1

打赏作者

_Modest_

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值