我在使用GNU make 4.1编译的Makefile中有以下规则:
multiboot_check: kernel.bin
if [ $(grub2-file --is-x86-multiboot $^) -eq 0 ]; then \
$(info $^: valid Multiboot Version 1 header); \
else \
$(error $^: invalid Multiboot Version 1 header); \
fi
当我运行它时,执行true和false分支,产生以下输出:
kernel.bin: valid Multiboot Version 1 header
Makefile:24: *** kernel.bin: invalid Multiboot Version 1 header. Stop.
为什么会这样?还有更好的方法吗?
我尝试将它放在一行中,甚至将if语句缩减为[ 0 -eq 0 ]
,它仍然执行两个分支。
答案 0 :(得分:1)
您的食谱相当于:
multiboot_check: kernel.bin
# `make` directives evaluated for this target are not part of the recipe
$(info $^: valid Multiboot Version 1 header)
$(error $^: invalid Multiboot Version 1 header)
# The recipe is...
if [ -eq 0 ]; then \
; \
else \
; \
fi
首先要了解为什么make
没有按照你编写的顺序对行进行排序,
阅读this answer
剩余食谱:
if [ -eq 0 ]; then \
; \
else \
; \
fi
在语法上对shell无效,因为未转义的$(grub2-file ...)
将由make
扩展,而不是shell,并将扩展为空。你要
它是一个shell扩展,所以你需要为make
转义它:
$$(grub2-file...)
但是,虽然剩余的配方会引发shell语法错误,但是
永远不会看到它,因为make
评估:
$(info $^: valid Multiboot Version 1 header)
$(error $^: invalid Multiboot Version 1 header)
在配方运行之前,$(error ...)
指令终止make
在它尝试执行无效食谱之前。
更正了shell扩展,测试:
[ $$(grub2-file --is-x86-multiboot $^) -eq 0 ]
仍然无法达到您显然想要的效果。这个测试会
确定命令grub2-file --is-x86-multiboot kernel.bin
的标准输出
是一个等于0
的字符串。据推测,它永远不会是你真正的
想确定命令的退出代码是否为0。
鉴于这一切,更好的方法是:
multiboot_check: kernel.bin
grub2-file --is-x86-multiboot $^; \
if [ $$? -eq 0 ]; then \
echo "$^: valid Multiboot Version 1 header"; \
else \
echo "$^: invalid Multiboot Version 1 header"; exit 1; \
fi