使用变量在 makefile 中创建自定义错误

问题描述 投票:0回答:1

我花了一些时间阅读 GNU make 手册页,但似乎无法弄清楚我想要实现的目标是否实际上是可能的。

基本上我只是想将变量传递给 info( 或 error( - 但到目前为止我尝试过的一切似乎都没有达到我的预期

当前版本的 makefile,我还尝试了多种变体来尝试让变量出现在信息和错误调用中,但到目前为止都没有成功。

error_prefix=ERROR:
info_prefix=INFO:

define print_error
  final_error="$(error_prefix) $1 $2"
  echo $(error fe:$(final_error))
  $(error fe:$(final_error))
endef

define print_info
  final_info="$(error_prefix) $1 $2"
  echo $(info fi:$(final_error))
  $(info fi:$(final_error))
endef

.PHONY: test

test:
        response=$$(eval curl -s -o /dev/null -w "%{http_code}" www.google.com); \
        echo $$response; \
        $(call print_info, $(value $response), A); \
        $(call print_error, $(value $response), B);


makefile custom-error-handling
1个回答
0
投票

您的 Makefile 是 shell 和 make 结构的奇怪组合。如果你是新手,你可能应该在配方中只使用 shell 结构,再加上变量扩展 (

$(VARIABLE)
)。但是让我们尝试看看当你用它运行 make 时会发生什么。

首先,重要的是要了解 make 在将配方传递到 shell 之前会扩展它们。当它扩展你的食谱时,它会发现

$(error ...)
。因此它会打印错误消息并在 shell 运行之前停止。

所以,让我们用

$(error ...)
替换这个
$(info error ...)
以避免这种情况:

define print_error
  final_error="$(error_prefix) $1 $2"
  echo $(info error fe:$(final_error))
  $(info error fe:$(final_error))
endef

Make 解析你的 Makefile 并发现它必须运行虚假目标的配方

test
。在将配方传递到 shell 之前,它会扩展它们。

当 make 扩展食谱的前 2 行时,它只是将

$$
替换为
$
。没关系。当它展开最后 2 行时,它首先展开
value
的参数:
$response
。由于您没有名为
r
的 make 变量,因此
$r
会扩展为空字符串,并且
value
的参数变为
esponse
。由于您没有名为
esponse
的 make 变量,因此
$(value esponse)
会扩展为空字符串。您可以写
$(call print_info, , A)
,它会做同样的事情(注意两个逗号之间和
A
之前的空格)。

当 make 展开时

$(call print_info, , A)
它会将其替换为(前导制表符和空格未显示):

final_info="$(error_prefix)   A"
echo $(info fi:$(final_error))
$(info fi:$(final_error)); \

注意:

A
前有3个空格。你明白为什么吗?

扩展继续递归进行。我们首先展开 make 变量

error_prefix
final_error
。由于您没有名为
final_error
的 make 变量(您有一个具有此名称的 shell 变量,但它与 make 变量不同),它会再次扩展为空字符串。这给出:

final_info="ERROR:   A"
echo $(info fi:)
$(info fi:); \

info
的扩展打印信息消息并扩展为空字符串。所以你看:

fi:
fi:

在标准输出上,配方变为:

final_info="ERROR:   A"
echo 
; \

本次扩展至此结束。最后一行的展开类似地变成:

final_error="ERROR:   B"
echo 
;

标准输出上又打印了两行,现在应该如下所示:

fi:
fi:
error fe:
error fe:

此时您的食谱是(同样,未显示前导制表符和空格):

response=$(eval curl -s -o /dev/null -w "%{http_code}" www.google.com); \
echo $response; \
final_info="ERROR:   A"
echo
; \
final_error="ERROR:   B"
echo 
;

这是 4 种不同的食谱:

食谱1:

response=$(eval curl -s -o /dev/null -w "%{http_code}" www.google.com); \
echo $response; \
final_info="ERROR:   A"

食谱2:

echo

食谱3:

; \
final_error="ERROR:   B"

食谱4:

echo 
;

第一个回显配方 1,你的标准输出现在看起来像:

fi:
fi:
error fe:
error fe:
response=$(eval curl -s -o /dev/null -w "%{http_code}" www.google.com); \
echo $response; \
  final_info="ERROR:    A"

然后 make 将配方 1 传递到运行

eval curl ...
的 shell(为什么是
eval
?),将输出
200
存储在 shell 变量
response
中,回显它,并将
ERROR:    A
存储在 shell 变量
final_info
中。您的标准输出现在是:

fi:
fi:
error fe:
error fe:
response=$(eval curl -s -o /dev/null -w "%{http_code}" www.google.com); \
echo $response; \
  final_info="ERROR:    A"
200

Make 然后回显方法 2 并将其传递给 shell,仅添加换行符:

fi:
fi:
error fe:
error fe:
response=$(eval curl -s -o /dev/null -w "%{http_code}" www.google.com); \
echo $response; \
  final_info="ERROR:    A"
200
echo

终于呼应食谱3了:

fi:
fi:
error fe:
error fe:
response=$(eval curl -s -o /dev/null -w "%{http_code}" www.google.com); \
echo $response; \
  final_info="ERROR:    A"
200
echo

; \
  final_error="ERROR:    B"

将配方 3 传递到 shell 时出现错误:

/bin/sh: -c: line 0: syntax error near unexpected token `;'
/bin/sh: -c: line 0: `; \'
make: *** [Makefile:19: test] Error 2

因为 shell 命令列表的开头不能有这样的分号。停止,并且不会回显或执行配方 4。

© www.soinside.com 2019 - 2024. All rights reserved.