Is it possible to have variables in GNU Make recipes?
Something like this doesn't work:
%_t.mkd : %.mkd REV=$$(svn info $<|grep 'Last Changed Rev'|cut -f4 -d\ ) echo $${REV}Is there some way to make that work at all?
As you can see what I want is to extract the revision that a file was changed and then use that later in the full recipe. Unfortunately I can't use svn:keywords as I need the revision number outside of the document in question.
4 Answers
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
maketo always use one shell process for the entire recipe, using the.ONESHELLdirective:.ONESHELL: foo: bar baz line1 line2 line3(Note that while
.ONESHELLis 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
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) 1 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} 3