2
votes
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

When I replaced eval with info it printed out the function call correctly but every time I try to actually eval the formatter it gives me the error in the title.

Edit: This question was plagued with syntax errors everywhere but following the advice of @MadScientist I was eventually able to get it to work using shell loops.

2
What is ALL_S_SOURCES? What else is in that makefile? What version of make? With that exact snippet I don't that error with a few different versions of make. (As an aside what is $[Base, $(1)].tmp supposed to be doing in that recipe line for you?) - Etan Reisner
And actually if I fill in ALL_S_SOURCES with a filename (that exists) I get a missing separator error. That define looks like it wants to output recipe lines but $(eval) doesn't generate any output. Also assigning a define with := causes it to be evaluated immediately which means all your $1 references are going to be empty. In short this isn't even close to being able to work as-is. - Etan Reisner
Even if I replace the entire define with one echo statement I still cant get it to echo once for every file in the list. - Dakota
To get it to echo at recipe execution time you need to remove $(eval) from the foreach loop. Change the define to be echo $(1). Put @ before the $(foreach) and indent it with a tab. Then put ; at the end of the last argument of the $(foreach) call. Roughly. - Etan Reisner

2 Answers

3
votes

The shortest answer is, you can't do it that way. A single function like $(foreach ...), or a single variable expansion, can never expand to multiple logical lines in a makefile. That's just not how the make parser works.

Further, $(eval ...) can be used to construct a complete rule but you can't use it to build just part of a rule: before make starts to parse the output of the evaluation it will "close" any rule that's currently being defined (just like you can't put the introduction of a rule in one file and the recipe in another file and use include to include the recipe).

You haven't really explained why you want to do things in just this way. One simple answer is to use shell loops, not makefile loops, like this:

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

I agree with Etan that the $[Base ...] syntax is weird and certainly isn't right.

If you want more details about eval and debugging, you might check out this post and the earlier ones in the series.

0
votes

The error message is pretty clear: the foreach loop spits out recipe commands before/outside of a target recipe definition.

You can try something like:

all: 
    $(foreach loopFile,$(ALL_S_SOURCES),$(eval $(call Format_File,$(loopFile))))

.PHONY: all