makefile:在每个配方中分配变量来存储步骤名称
makefile: Reassign variable in each recipie to store the step name
我有一个 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 =
之前的 "echo",我只会收到 shell 错误(找不到临时文件)。
如何设置我的变量以便打印出生成文件失败的步骤?
注意:您不应在食谱中使用 make
。请改用 $(MAKE)
。您可以在 GNU make manual.
中找到几个很好的理由
make变量和shell变量不同。当你写:
temp = "start"
是make语法,temp
是make变量。当你写:
step1:
temp = "step1"
temp
是一个 shell 变量,您会收到语法错误,因为 shell 变量赋值是 temp="step1"
(=
周围没有空格)。
但这还不是全部。配方的每一行都是 运行 由一个单独的 shell (除非特殊目标 .ONESHELL
出现在 makefile 中)并且不同的配方不能 运行 由相同的 shell 实例(不考虑 .ONESHELL
)。因此,您不能指望 run_failed
规则的配方能够访问与 step2
配方的一行分配的相同 shell 变量 temp
.
无论如何,当 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
如果出于任何原因无法做到这一点,您将不得不:
- 将失败信息从一个配方 (
step2
) 传递到另一个配方 (run
),
- 将失败信息从一个子 make 调用 (
run-all
) 传递到另一个 (run_failed
)。
所有这一切都将非常困难,除非您使用日志文件并告诉 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
我有一个 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 =
之前的 "echo",我只会收到 shell 错误(找不到临时文件)。
如何设置我的变量以便打印出生成文件失败的步骤?
注意:您不应在食谱中使用 make
。请改用 $(MAKE)
。您可以在 GNU make manual.
make变量和shell变量不同。当你写:
temp = "start"
是make语法,temp
是make变量。当你写:
step1:
temp = "step1"
temp
是一个 shell 变量,您会收到语法错误,因为 shell 变量赋值是 temp="step1"
(=
周围没有空格)。
但这还不是全部。配方的每一行都是 运行 由一个单独的 shell (除非特殊目标 .ONESHELL
出现在 makefile 中)并且不同的配方不能 运行 由相同的 shell 实例(不考虑 .ONESHELL
)。因此,您不能指望 run_failed
规则的配方能够访问与 step2
配方的一行分配的相同 shell 变量 temp
.
无论如何,当 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
如果出于任何原因无法做到这一点,您将不得不:
- 将失败信息从一个配方 (
step2
) 传递到另一个配方 (run
), - 将失败信息从一个子 make 调用 (
run-all
) 传递到另一个 (run_failed
)。
所有这一切都将非常困难,除非您使用日志文件并告诉 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