target variable in dynamic target

Viewed 478

I have a bit more complex Makefile with dynamically generated targets like this:

COMPONENTS = foo bar lipsum

define TEST_template =
  .PHONY: test-$(1)
  test-$(1):
    @echo test
endef
$(foreach cmpnt,$(COMPONENTS),$(eval $(call TEST_template,$(cmpnt))))

But now I'd like to add a target-specific variable to this target. With non-dynamic targets this works nicely:

test: VAR_ONE=1
test:
    @echo "VAR_ONE=$(VAR_ONE)"

But combining these two is not working

COMPONENTS = foo bar lipsum

define TEST_template =
  .PHONY: test2-$(1)
  test2-$(1): VAR_ONE=1
  test2-$(1):
    @echo "test - VAR_ONE=$(VAR_ONE)"
endef
$(foreach cmpnt,$(COMPONENTS),$(eval $(call TEST_template,$(cmpnt))))

Now running make test2-foo returns test - VAR_ONE=, so it seems the variable is not being set.

Is this even possible? I've been trying to achieve this for a couple of days now but I couldn't find anything.

2 Answers

You have to escape any variable reference inside the define that you don't want to be interpreted by the call. So it's:

define TEST_template =
  .PHONY: test2-$(1)
  test2-$(1): VAR_ONE=1
  test2-$(1):
        @echo "test - VAR_ONE=$$(VAR_ONE)"
endef

A good rule of thumb (although as with anything, there are exceptions) is that when defining a variable to be used with a call/eval pair, the arguments to call (e.g., $1, $2 etc.) should be referenced directly and all other variables should be escaped.

You have to write

    @echo "test - VAR_ONE=$$(VAR_ONE)"

(note the double $$). See info make

It's important to realize that the 'eval' argument is expanded twice; first by the 'eval' function, then the results of that expansion are expanded again when they are parsed as makefile syntax. This means you may need to provide extra levels of escaping for "$"

Related