Home > database >  Quoting shell env vars in Makefile
Quoting shell env vars in Makefile

Time:02-16

I thought I understood that simply-expanded variables got their value once, when the Makefile is read -- but I've got confused:

var := $$RANDOM

echo:
        @echo v1: $(var)
        @echo v2: $(var)

With result

$ make
v1: 11478
v2: 24064

So how come the shell env var is referenced twice?

I see that var := $(shell echo $$RANDOM) don't do the second value assignment -- how is this machinery different?

CodePudding user response:

Simply-expanded variables are MAKE constructs. Indeed, that variable is only expanded one time, by make. But, it expands into a shell variable:

var := $$RANDOM

now the value of the var variable in make is the static string $RANDOM and make will never expand it again. You can determine this by doing something like:

var := $(info expanding RANDOM)$$RANDOM

and you'll see it only prints expanding RANDOM one time.

But, this rule:

echo:
        @echo v1: $(var)
        @echo v2: $(var)

invokes shell two times and each time passing the static string $RANDOM, which the shell expands, each time the shell is invoked, and you get different answers. Basically, make is running:

/bin/sh -c 'echo v1: $RANDOM'
/bin/sh -c 'echo v2: $RANDOM'

If you change it to this:

var := $(shell echo $$RANDOM)

Here, make is invoking the shell, one time, and assigning the result of that shell command to the variable var. So after this, var contains the literal string 12345 or whatever the result is, not $RANDOM.

BTW, you should add:

SHELL := /bin/bash

to your makefile, because $RANDOM is a bash feature that is not available in the POSIX shell, and make always invokes /bin/sh by default: on some systems /bin/sh is the same thing as bash but on other systems, it isn't.

  • Related