Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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.

share|improve this question

2 Answers 2

up vote 2 down vote accepted

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" and info 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.)

share|improve this answer

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}
share|improve this answer
    
This would work at the top level of a makefile, but not in the middle of a recipe (where shell syntax is used, not Make syntax). It'd be REV != svn info ... too. –  grawity Jul 31 at 8:01
1  
Perhaps the op can set the variable once at the top level of his makefile then? :/ –  DavidPostill Jul 31 at 8:04
    
Nope, as you see I need it as part of the recipe since the value will be different for different files. –  Magnus Aug 1 at 10:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.