user1234
user1234

Reputation: 135

pass env variables in make command in makefile

I am trying to pass a shell variable from one makefile command to another, but so far have not been successful.

target1:
     curl ... ${myvar} ## using myvar from target2

target2:
     export myvar=$(shell curl .....);
     echo $myvar

In the above case, I am not even getting the output on echo $myvar. Is there something I'm doing wrong?

Upvotes: 1

Views: 2813

Answers (2)

larsks
larsks

Reputation: 311416

In a Makefile, every line of a target is run in a separate shell. Additionally, a command can only change the environment for itself and its children. So when you have:

target2:
     export myvar=$(shell curl .....);
     echo $myvar

And you run make target2, the following happens:

  1. Make starts a shell that runs export myvar=...some value...
  2. The shell exits.
  3. Make runs another shell that runs echo $myvar
  4. That shell exits.

First, there's a syntax problem here: when you write $myvar, this will be interpreted by make as a request for the value $m followed by the text yvar. To access shell variables, you need to escape the $, like this:

echo $$myvar

But that won't solve this problem, because as we see from the above sequence, the export command happens in a shell process which immediately exits, so it's effectively invisible to anything else.

This target would work the way you expect if you were to write:

target2:
     export myvar=$(shell curl .....); \
     echo $$myvar

Here, because we're using the \ to escape the end-of-line, this is all one long "virtual" line and executes in a single shell process, so the echo statement will see the variable value set in the previous statement.

But nothing will make an environment variable set in a shell process in one target visible in another target, because there's no way to get these to execute in the same process.

If you need to set variables in your Makefile that are visible across all targets, set make variables:

myvar = $(shell curl ...)

target1:
     curl ... $(myvar)

A workaround, as you have discovered, is to re-execute make as a child process from within the process that set the environment variable as in:

target2:
     export myvar=$(shell curl .....); \
     echo $$myvar; \
     $(MAKE) myvar=$$myvar

But often this sort of recursive call to make results in a more complicated Makefile.

Upvotes: 2

user1234
user1234

Reputation: 135

Found the answer. Posting if anyone comes across this. I needed to use $$ instead of $

target1:
     curl ... ${myvar} ## using myvar from target2
     
target2:
     export myvar=$(shell curl .....);
     echo $$myvar
     $(MAKE) myvar=$${myvar} target1 

Upvotes: 0

Related Questions