Dakota
Dakota

Reputation: 1274

$(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

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.

Upvotes: 2

Views: 1299

Answers (2)

MadScientist
MadScientist

Reputation: 101131

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.

Upvotes: 3

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136515

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

Upvotes: 0

Related Questions