makefile 中的 $(eval ) 导致配方在第一个目标错误之前开始
$(eval ) in makefile causing recipe commences before first target error
CFormat:
define Format_File :=
@echo Formatting
ifneq ("$(wildcard $(1))","")
@echo if1
# The default extensions for intermediate files are not used,
# to avoid collisions with backup files open in the editor, etc.
# Save the original source file with an '_X' suffix on the extension.
ifneq("$(wildcard $(1)_X)","")
@echo if2
else
@echo else2
endif
@ren $(1) $(1)_X
# C-Comment is invoked separately, due to pathing limitations
# The redirection is a means to suppress blabbering.
@echo Formatting $(1) . . .
$(CFORMAT_PATH)\Cformat -h$(CFORMAT_PATH) $(1)_X -o$[Base, $(1)].tmp -ino >temp.tmp;
$(CFORMAT_PATH)\Ccomment -h$(CFORMAT_PATH) $[Base, $(1)].tmp -o$(1) >temp.tmp;
else
@echo else1
endif
endef
FormatAll: CFormat
$(foreach loopFile,$(ALL_S_SOURCES),$(eval $(call Format_File,$(loopFile))))
.PHONY: FormatAll
当我用 info 替换 eval 时,它正确地打印出了函数调用,但每次我尝试实际 eval 格式化程序时,它都会给我标题中的错误。
编辑:这个问题到处都是语法错误,但在@MadScientist 的建议下,我最终能够使用 shell 循环让它工作。
错误消息非常清楚:foreach
循环吐出目标配方定义的配方命令 before/outside。
您可以尝试类似的方法:
all:
$(foreach loopFile,$(ALL_S_SOURCES),$(eval $(call Format_File,$(loopFile))))
.PHONY: all
最简短的回答是,你不能那样做。像 $(foreach ...)
这样的单个函数或单个变量扩展 永远不会 扩展到 makefile 中的多个逻辑行。这不是 make 解析器的工作方式。
此外,$(eval ...)
可以用来构建一个完整的规则,但你不能用它来构建规则的一部分:在 make 开始解析评估的输出之前,它会 "close" 当前正在定义的任何规则(就像你不能在一个文件中引入规则,在另一个文件中引入配方,然后使用 include
来包含配方)。
您还没有真正解释为什么要以这种方式做事。一个简单的答案是使用 shell 循环,而不是 makefile 循环,如下所示:
FormatAll: CFormat
@for f in $(ALL_S_SOURCES); do \
echo Formatting; \
if [ -f $$f ]; then \
echo if1; \
if [ -f $${f}_X ]; then \
echo if2; \
else \
echo else2; \
fi; \
ren $$f $${f}_X; \
echo Formatting $$f . . .; \
$(CFORMAT_PATH)\Cformat -h$(CFORMAT_PATH) $F{f}_X -o$[Base, $$f].tmp -ino >temp.tmp; \
$(CFORMAT_PATH)\Ccomment -h$(CFORMAT_PATH) $[Base, $$f].tmp -o$$f >temp.tmp; \
else \
echo else1; \
fi; \
done
我同意 Etan 的观点,$[Base ...]
语法很奇怪而且肯定是不正确的。
如果您想了解有关 eval
和调试的更多详细信息,您可以查看 this post 和该系列中较早的内容。
CFormat:
define Format_File :=
@echo Formatting
ifneq ("$(wildcard $(1))","")
@echo if1
# The default extensions for intermediate files are not used,
# to avoid collisions with backup files open in the editor, etc.
# Save the original source file with an '_X' suffix on the extension.
ifneq("$(wildcard $(1)_X)","")
@echo if2
else
@echo else2
endif
@ren $(1) $(1)_X
# C-Comment is invoked separately, due to pathing limitations
# The redirection is a means to suppress blabbering.
@echo Formatting $(1) . . .
$(CFORMAT_PATH)\Cformat -h$(CFORMAT_PATH) $(1)_X -o$[Base, $(1)].tmp -ino >temp.tmp;
$(CFORMAT_PATH)\Ccomment -h$(CFORMAT_PATH) $[Base, $(1)].tmp -o$(1) >temp.tmp;
else
@echo else1
endif
endef
FormatAll: CFormat
$(foreach loopFile,$(ALL_S_SOURCES),$(eval $(call Format_File,$(loopFile))))
.PHONY: FormatAll
当我用 info 替换 eval 时,它正确地打印出了函数调用,但每次我尝试实际 eval 格式化程序时,它都会给我标题中的错误。
编辑:这个问题到处都是语法错误,但在@MadScientist 的建议下,我最终能够使用 shell 循环让它工作。
错误消息非常清楚:foreach
循环吐出目标配方定义的配方命令 before/outside。
您可以尝试类似的方法:
all:
$(foreach loopFile,$(ALL_S_SOURCES),$(eval $(call Format_File,$(loopFile))))
.PHONY: all
最简短的回答是,你不能那样做。像 $(foreach ...)
这样的单个函数或单个变量扩展 永远不会 扩展到 makefile 中的多个逻辑行。这不是 make 解析器的工作方式。
此外,$(eval ...)
可以用来构建一个完整的规则,但你不能用它来构建规则的一部分:在 make 开始解析评估的输出之前,它会 "close" 当前正在定义的任何规则(就像你不能在一个文件中引入规则,在另一个文件中引入配方,然后使用 include
来包含配方)。
您还没有真正解释为什么要以这种方式做事。一个简单的答案是使用 shell 循环,而不是 makefile 循环,如下所示:
FormatAll: CFormat
@for f in $(ALL_S_SOURCES); do \
echo Formatting; \
if [ -f $$f ]; then \
echo if1; \
if [ -f $${f}_X ]; then \
echo if2; \
else \
echo else2; \
fi; \
ren $$f $${f}_X; \
echo Formatting $$f . . .; \
$(CFORMAT_PATH)\Cformat -h$(CFORMAT_PATH) $F{f}_X -o$[Base, $$f].tmp -ino >temp.tmp; \
$(CFORMAT_PATH)\Ccomment -h$(CFORMAT_PATH) $[Base, $$f].tmp -o$$f >temp.tmp; \
else \
echo else1; \
fi; \
done
我同意 Etan 的观点,$[Base ...]
语法很奇怪而且肯定是不正确的。
如果您想了解有关 eval
和调试的更多详细信息,您可以查看 this post 和该系列中较早的内容。