8

I would like to use make's eval function to define several (dynamically-named) variables inside a foreach, but I can't get eval to do this job.

I tried something like this:

$(eval \
    var1 = val1 \
    var2 = val2 \
)

It doesn't work: var1 gets defined as val1 var2 = val2 and var2 is not defined. It makes sense, because I put \ at the end of the second line. But if I remove it, the eval call will never be terminated.

I tried different things to have this \ only seen by eval, but nothing did the trick. Hence the question: is it possible to define multiple variables in the same eval call ?

Of course I could call eval twice... it's rather curiosity.

Ramkrishna Sharma
  • 6,961
  • 3
  • 42
  • 51
lephe
  • 302
  • 4
  • 14
  • I don't think it's possible because in a more general way you can't declare two variables in the same line. It must be due to the way make parse's the variable declaration. Anyway you can put multiple eval functions in a defined function and call only this function, so it only takes one line at the call. – Tim Jul 06 '16 at 13:16
  • @TimF I guess you're right. But since `eval` can be used to parse the result of `call`, which is multi-line, I expected to be able to write a "multi-line literal string". – lephe Jul 06 '16 at 13:33
  • I've tried multiple solutions and finally found an answer, see below ;) – Tim Jul 06 '16 at 13:43

2 Answers2

9

What separates each variable definition is the newline character, which you are escaping with the backslash. Since you cannot put it directly in the eval function, you have to define it and to use it into eval like this :

define newline


endef

Then if you place the following lines inside a target :

$(eval FOO=abc$(newline)BAR=def)
@echo FOO : $(FOO) BAR : $(BAR)

You will have this result :

FOO : abc BAR : def

Note that if you want to use a variable in the definition of the second one you have to escape the $ character like this :

$(eval FOO=abc$(newline)BAR=def$$(FOO))
@echo FOO : $(FOO) BAR : $(BAR)

The result will eventually be :

FOO : abc BAR : defabc

This is due to the fact that there is a first level of interpretation before that eval actually begins to do its work (the newline is added here) but we want the interpretation of the variable to occur only during the real eval work, when the variable is defined, which is why we need a double $ symbol.

Tim
  • 1,853
  • 2
  • 24
  • 36
  • That's clever. It makes the code lighter like I sought. +1 – lephe Jul 06 '16 at 13:49
  • It appears that this trick won't work if the second variable uses the first, e.g. `FOO=abc$(newline)BAR=FOO`. In this example BAR remains empty. – lephe Jul 06 '16 at 14:40
  • @lephe : See the end of my answer, I edited it to add what you're looking for. – Tim Jul 06 '16 at 14:48
  • This answer may also be helpful: https://stackoverflow.com/a/649462/1997726 Similar concept, but you can define the entire eval body in a variable and pass that to eval. – Tails86 Oct 10 '22 at 15:20
2

Simply use the foreach:

oneline = FOO=abc BAR=def XX=...
$(foreach line,$(oneline),$(eval $(line)))
$(info $(FOO) $(BAR))

The result:

abc def
tonado
  • 21
  • 1