Variables in GNU Make recipes, is that possible?
This doesn't work because the make
tool starts a new shell process for each recipe line. And shell variables – even 'exported' environment variables – cannot possibly propagate "upwards"; they're gone as soon as the shell process exits.
-
The traditional method is to join the recipe lines using
\
in the Makefile:foo: bar baz line1; \ line2; \ line3
(Note that the commands must be separated using
;
or&&
, because the backslashes are also passed to the shell which does the same line-joining.)See also
info make "Splitting Lines"
andinfo make "Splitting Recipe Lines"
in the GNU Make manual. -
The other method is to tell
make
to always use one shell process for the entire recipe, using the.ONESHELL
directive:.ONESHELL: foo: bar baz line1 line2 line3
See
info make "One Shell"
.(Note that while
.ONESHELL
is recommended by POSIX, not all make versions support it; e.g. BSD make only has a command-line flag for it. This shouldn't be a problem though.)
Thanks to https://stackoverflow.com/questions/6519234/cant-assign-variable-inside-recipe
This is the solution to change a variable in a recipe:
recipe: $(eval variablename=whatever)
taking what @user3645902 mentioned, here is the solution to the main question:
recipe:
@$(eval REV=`svn info $<|grep 'Last Changed Rev'|cut -f4 -d`)
@echo $(REV)
According to Gnu Make 6.5 Setting Variables:
The shell assignment operator
!=
can be used to execute a program and set a variable to its output. This operator first evaluates the right-hand side, then passes that result to the shell for execution. If the result of the execution ends in a newline, that one newline is removed; all other newlines are replaced by spaces. The resulting string is then placed into the named recursively-expanded variable.
So you could try the following (not tested):
REV != $$(svn info $<|grep 'Last Changed Rev'|cut -f4 -d\ ) \
echo $${REV}