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 和该系列中较早的内容。