代码之家  ›  专栏  ›  技术社区  ›  code_fodder

makefile:在每个recipie中重新分配变量以存储步骤名

  •  0
  • code_fodder  · 技术社区  · 7 年前

    我有一个makefile,它在规则失败时运行规则。我在下面写了一个小例子:

    temp = "start"
    
    run:
        make run_all || make run_failed
    
    run_all: step1
    run_all: step2
    run_all: step3
    run_all: ;
    
    step1:
        echo temp = "step1"
    
    step2:
        echo temp = "step2"
        $(error fail test)
    
    step3:
        echo temp = "step3"
    
    run_failed:
        @echo "failed on step ${temp}"
    

    我用$(error…)命令强制这个小例子在步骤2中失败。 我的问题是我想在每一步设置我的可变温度。但我不知道怎么做。

    如果它在 temp = 在每个步骤中,我都会得到一个shell错误(找不到temp)。

    如何设置变量以便打印生成文件失败的步骤?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Renaud Pacalet    7 年前

    注意:你不应该使用 make 在你的食谱里。使用 $(MAKE) 相反。有几个很好的理由,你可以在 GNU make manual .

    Make变量和shell变量不同。当你写作时:

    temp = "start"
    

    它使语法和 temp 是make变量。当你写作时:

    step1:
        temp = "step1"
    

    临时雇员 是一个shell变量,您会得到一个语法错误,因为shell变量赋值是 temp="step1" (周围没有空格 = ).

    但这不是全部。配方的每一行都由一个单独的shell运行(除非特殊目标 .ONESHELL 出现在makefile中)并且不同的配方不能由同一个shell实例运行(不管 .单壳 ). 所以,你不能指望 run_failed 访问同一shell变量的规则 临时雇员 作为您的 step2 食谱。

    不管怎样,当make在菜谱上失败时,它会告诉你出了什么问题,包括什么规则失败了。如果这还不够,最好的选择是在每个配方上设置一条错误消息:

    $ cat fail
    #!/usr/bin/env bash
    exit 1
    
    $ cat Makefile
    run: step1 step2 step3
    
    step1 step3:
        @echo "doing $@" || echo "$@ failed"
    
    step2:
        @./fail || echo "$@ failed"
    
    $ make step1
    doing step1
    
    $ make run
    doing step1
    step2 failed
    doing step3
    

    如果出于任何原因,这是不可能的,您将不得不:

    1. 从一个配方传递故障信息( 第二步 )对另一个人( run ),
    2. 从一个子make调用传递失败信息( run-all )对另一个人( 运行失败 ).

    除非使用日志文件并告诉make不要以并行模式运行,否则所有这些都将非常困难:

    $ cat Makefile
    .NOTPARALLEL:
    
    FAILED  := failed.txt
    
    run:
        @{ rm -f $(FAILED) && $(MAKE) run_all; } || $(MAKE) run_failed
    
    run_all: step1 step2 step3
    
    step1 step3:
        @echo "doing $@" || { echo "$@ failed" >> $(FAILED) && exit 1; }
    
    step2:
        @./fail || { echo "$@ failed" >> $(FAILED) && exit 1; }
    
    run_failed:
        @cat $(FAILED)
    
    $ make --no-print-directory
    doing step1
    Makefile:14: recipe for target 'step2' failed
    make[1]: *** [step2] Error 1
    step2 failed