shell`if`在makefile执行两个分支



我在用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

运行此操作时,真实和错误分支都将执行,从而导致以下输出:

kernel.bin: valid Multiboot Version 1 header
Makefile:24: *** kernel.bin: invalid Multiboot Version 1 header.  Stop.

为什么会发生这种情况?有更好的方法吗?

我尝试将其放入一行,甚至将IF语句减少到[ 0 -eq 0 ],并且仍然执行两个分支。

您的食谱等效于:

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不会像您写的那样订购线条,阅读此答案

残留食谱:

    if [ -eq 0 ]; then 
        ; 
    else 
        ; 
    fi

对于外壳而言是句法无效的,因为UNESCAPED $(grub2-file ...)将通过make而不是外壳扩展,并且将一无所有。你要它是外壳的扩展,因此您需要为make逃脱它:

$$(grub2-file...)

但是,尽管残留食谱会引起外壳语法错误,但您永远不要看到它,因为make评估:

    $(info $^: valid Multiboot Version 1 header)
    $(error $^: invalid Multiboot Version 1 header)

在运行食谱之前,$(error ...)指令终止make在尝试执行无效的食谱之前。

校正了壳膨胀,测试:

[ $$(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

最新更新