GNU Make中define内注释的$(info)为何仍被执行?
为什么GNU Make的define块内注释的$(info)会执行?
先看你提供的Makefile代码:
define tmpl $(info info inside define, not commented, parameter is: $(1)) # $(info info inside define, commented, parameter is: $(1)) endef $(eval $(call tmpl,make context)) $(info info outside, not commented) # $(info info outside, commented) all: @echo echo target $@ $(info info receipt target $@ not commented) # $(info info receipt target $@ commented) $(eval $(call tmpl,receipt context))
运行后输出里,define块内被#注释的$(info)居然也执行了,而顶层注释的$(info)却没执行,核心原因在于define块里的#不是真正的Makefile注释:
define的作用是定义递归展开变量,块内的所有内容都是变量的字面值——包括#字符,它只是变量内容的一部分,不会被Make当作注释处理。- 当用
$(call)展开这个变量时,Make会优先解析变量内容里的所有内嵌函数(比如$(info)),不管函数前面有没有#。因为变量展开的逻辑是先求值所有Make函数,再输出最终文本,所以$(info)会直接执行并输出内容,之后$(eval)处理展开后的文本时,才会把#开头的行当作注释,但此时$(info)已经跑完了。 - 而Makefile顶层的
# $(info ...)不会执行,是因为Make在解析顶层代码时,只要看到行首非空白字符是#,就会直接忽略整行,根本不会去解析里面的$(info)函数。
如果要在define块内真正“注释”掉$(info)这类Make函数,不能用#,可以用以下两种方法:
转义
$符号:把$(info)改成$$(info),这样变量展开时不会执行函数,而是保留$$(info ...)的文本,后续不会触发执行:define tmpl $(info info inside define, not commented, parameter is: $(1)) # $$(info info inside define, commented, parameter is: $(1)) endef用条件判断包裹:用永远不成立的条件(比如
ifeq (0,1))把要注释的代码包起来,让Make直接跳过这部分的解析和展开:define tmpl $(info info inside define, not commented, parameter is: $(1)) ifeq (0,1) $(info info inside define, commented, parameter is: $(1)) endif endef
内容的提问来源于stack exchange,提问作者stefan
相关产品推荐
相关产品推荐

