Double Dollar "$$@" target name in GNU Make

423 Views Asked by At

I have a rule from OP-TEE (uses large makefile include and make invocation trees to compile two operating system kernels and applications) with some immediately expanded variables -- as far as I can tell, there is no second expansion relevant here, since the double double dollar is in the rule and thus not subject to second expansion. It should always be expanded in the second phase:

$(link-out-dir$(sm))/$(user-ta-uuid).elf: $(objs) $(libdeps) \
                  $(link-script-pp$(sm))
    @$(cmd-echo-silent) '  LD      $$@'
    echo Target '$@', '$$@', "$@", "$$@"

In the output, one can see that all occurrences of $@and $$@ are expanded by make, not by sh, but the single dollar ones are not filled with the correct value, and the double ones did not escape themselves:

echo Target '', 'out/someuuid.elf', "", "out/someuuid.elf"
Target , out/someuuid.elf, , out/someuuid.elf

What i was expecting was:

echo Target 'out/someuuid.elf', '$@', "out/someuuid.elf", "$@"
Target out/someuuid.elf, $@, out/someuuid.elf,

Which mechanism of make could be the reason for the expansion to work differently here?

This target is nested two layers deep in other makefiles and four make invocations, thus it's a bit difficult to find out what the buildchain has configured differently here.


I cannot reproduce this behaviour with a minimal makefile:

all: target1 target2 target3

.PHONY: target1 target2 target3 all
.SUFFIXES:

target1:
        echo Target1 '$@', '$$@', "$@", "$$@"

# should make no difference, since used in immediate context on rule specification
TARGET2 := target2
TARGET3 = target3

$(TARGET2):
        echo Target2 '$@', '$$@', "$@", "$$@"

$(TARGET3):
        echo Target3 '$@', '$$@', "$@", "$$@"

yielding the expected output with $@ expanding to the target name and $$@ expanding to a string or empty list of positional shell parameters:

echo Target1 'target1', '$@', "target1", "$@"
Target1 target1, $@, target1,
echo Target2 'target2', '$@', "target2", "$@"
Target2 target2, $@, target2,
echo Target3 'target3', '$@', "target3", "$@"
Target3 target3, $@, target3,

Specifying .SECONDEXPANSION does not change the results, as expected.

1

There are 1 best solutions below

1
On

Syntax highlighting can be tricky -- I wasn't aware of the whole target being content of a variable itself -- some targets above there was a define gen-link-t beginning a multiline variable, ending some targets below.

The target was actually invoked after generation using $(eval $(call gen-link-t)) at the end of the file, instead of being read in line-by-line -- causing the first expansion of $$ to $ to happen when expanding the variable within the $(call), making the call return the $ as plain text. The second evaluation happened when make was reading this target again via $(eval)