我花了一些时间阅读 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 是 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。