recipe line order not honored for $(foreach)

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

recipe line order not honored for $(foreach)

Hi everybody,

it appears that a $(foreach) statement appearing in any recipe line is
evaluated before all remaining lines regardless where in the recipe it
appears, then all remaining recipe lines are executed.  I would expect the
lines to be executed in the order of appearance.

A simple culprit example:

$ make --version
GNU Make 4.2.1

$ cat -n makefile
     1  .PHONY: all
     2  all: list.txt
     3  list.txt: $(MAKEFILE_LIST)
     4          $(RM) $@
     5          $(foreach x,$^,$(shell echo $x >> $@))
     6          test -f $@

# for copying the code
$ cat makefile
.PHONY: all
all: list.txt
list.txt: $(MAKEFILE_LIST)
  $(RM) $@
        $(foreach x,$^,$(shell echo $x >> $@))
        test -f $@

$ make
rm -f list.txt
test -f list.txt
make: *** [Makefile:6: list.txt] Error 1

The test -f fails, i.e. list.txt does not exist, since the $(foreach) loop
is evaluated first writing to list.txt, then the remaining recipe lines in
appearance order are executed: list.txt is removed by the recipe first line
such that the test in the third recipe line fails.

Is it intended that the recipe line order is not honored for $(foreach)?  I
think this behavior is counterintuitive and for me it smells like a bug.

As a side remark, a workaround for this sample issue is to move $(foreach)
into the **first** line with adjusted recipe code logic (I am well aware
that there are other make techniques to do this, but this is about the
$(foreach) precedence issue in a recipe block):

.PHONY: all
all: list.txt
list.txt: $(MAKEFILE_LIST)
        $(foreach x,$^,$(shell echo $x >> $@.tmp))
        mv -f $@.tmp $@

Any input highly appreciated.

Many thanks,

Bug-make mailing list
[hidden email]