somevar := apple
export somevar
update := $(shell echo \"v=$$somevar\")
all:
@echo $(update)
I was hoping to apple as output of command, however i
@Beta's answer contains the crucial pointer: with GNU make
, variables marked with export
are only available to [the shells launched for] recipe commands (commands that are part of rules), regrettably not to invocations of $(shell ...)
(they only see the environment that make
itself saw when it was launched).
There is a workaround, however: explicitly pass the exported variable as an environment variable to the shell
function:
update := $(shell somevar='$(somevar)' perl -e 'print "$$ENV{somevar}"')
By prepending the shell command with =
, that definition is added as an environment variable to the environment that the command sees - this is a generic shell feature.
Caveat: @Kaz points out in a comment that this method misbehaves if $(somevar)
contains certain chars., because the variable expansion is verbatim (no escaping), which can break the resulting shell command, and suggests the following variant to also work with embedded '
instances (breaks the input value into single-quoted substrings with quoted '
spliced in):
update := $(shell somevar='$(subst ','\'',$(somevar))' perl -e 'print "$$ENV{somevar}"')
This should work with all values except multi-line ones (which are rare; there is no workaround for multi-line values that I'm aware of).
On a side note, literal $
chars. in values must be represented as $$
, otherwise make
will interpret them as references to its own variables.
Note that I've deliberately NOT chosen the OP's original statement, update := $(shell echo "v=$$somevar")
, for demonstration, because it contains a pitfall that muddles the issue: due to how the shell evaluates a command line, somevar=apple echo v=$somevar
does NOT evaluate to v=apple
, because the $somevar
reference is expanded before somevar=apple
takes effect. To achieve the desired effect in this case, you'd have to use 2 statements: update := $(shell export somevar="$(somevar)"; echo "v=$$somevar")
As for the bug-vs.-feature debate:
While it can be argued that the shell
function should see the same environment as recipe commands, the documentation makes no such promise - see http://www.gnu.org/software/make/manual/make.html#Shell-Function. Conversely, http://www.gnu.org/software/make/manual/make.html#Variables_002fRecursion only mentions making exported variables available to recipe commands.