How to set child process' environment variable in Makefile
Solution 1
Make variables are not exported into the environment of processes make invokes... by default. However you can use make's export
to force them to do so. Change:
test: NODE_ENV = test
to this:
test: export NODE_ENV = test
(assuming you have a sufficiently modern version of GNU make >= 3.77 ).
Solution 2
As MadScientist pointed out, you can export individual variables with:
export MY_VAR = foo # Available for all targets
Or export variables for a specific target (target-specific variables):
my-target: export MY_VAR_1 = foo
my-target: export MY_VAR_2 = bar
my-target: export MY_VAR_3 = baz
my-target: dependency_1 dependency_2
echo do something
You can also specify the .EXPORT_ALL_VARIABLES
target to—you guessed it!—EXPORT ALL THE THINGS!!!:
.EXPORT_ALL_VARIABLES:
MY_VAR_1 = foo
MY_VAR_2 = bar
MY_VAR_3 = baz
test:
@echo $$MY_VAR_1 $$MY_VAR_2 $$MY_VAR_3
Solution 3
I only needed the environment variables locally to invoke my test command, here's an example setting multiple environment vars in a bash shell, and escaping the dollar sign in make
.
SHELL := /bin/bash
.PHONY: test tests
test tests:
PATH=./node_modules/.bin/:$$PATH \
JSCOVERAGE=1 \
nodeunit tests/
Solution 4
I would re-write the original target test, taking care the needed variable is defined IN THE SAME SUB-PROCESS as the application to launch:
test:
( NODE_ENV=test mocha --harmony --reporter spec test )
Related videos on Youtube
bodokaiser
Hey, I am Bodo Kaiser and I have a bit knowledge around nodejs.
Updated on July 11, 2022Comments
-
bodokaiser almost 2 years
I would like to change this Makefile:
SHELL := /bin/bash PATH := node_modules/.bin:$(PATH) boot: @supervisor \ --harmony \ --watch etc,lib \ --extensions js,json \ --no-restart-on error \ lib test: NODE_ENV=test mocha \ --harmony \ --reporter spec \ test clean: @rm -rf node_modules .PHONY: test clean
to:
SHELL := /bin/bash PATH := node_modules/.bin:$(PATH) boot: @supervisor \ --harmony \ --watch etc,lib \ --extensions js,json \ --no-restart-on error \ lib test: NODE_ENV=test test: mocha \ --harmony \ --reporter spec \ test clean: @rm -rf node_modules .PHONY: test clean
Unfortunately the second one does not work (the node process still runs with the default
NODE_ENV
.What did I miss?
-
truthadjustr over 3 yearsYour
Unfortunately
comment stems from a misunderstanding between an environment variable versus aMakefile
variable. The best way to prove that an environment variable has been set, is to query this environment variable inside another program thatmake
wil call. Only doingecho $(BLAH)
is merely evaluating Makefile's key/value mechanism inside the Makefile. In python, you canprint(os.getenv("MURDOC"))
to truly query the environment variable.
-
-
Gauthier over 9 yearsI have GNU make 3.81, and
all: <\n\t>export PROJ_ROOT=$(CURDIR)<\n\t>echo $(PROJ_ROOT)<\n>
outputs the correct expansion for the first row, but onlyecho
for the second one.PROJ_ROOT
is not set after running make. Spaces around=
give "bad variable name" for export. Having the first row as prerequisite as in your example gives "commands commence before first target" -
MadScientist over 9 years@Gauthier yes of course. That's not what I wrote. You added a <\n\t> after the
all:
, which is not in my example. My example is intended to be used as written: it's defining a target-specific variable, NOT adding a command to the recipe. Also you cannot use a recipe and a target-specific variable on a target at the same time: you have to write the target twice. See the second example in the question, and ask a new question if this doesn't help explain it: there's not enough space or formatting in comments. -
mickmackusa about 7 yearsPlease edit your answer to include some explanation. Code-only answers do very little to educate future SO readers. Your answer is in the moderation queue for being low-quality.
-
Keith Hanlan almost 7 yearsThorSummoner, this solution is not as flexible as the approach above. For example, one might wish to have one single rule for invoking a command and then several other rules which modify that behaviour by setting environment variables. Consider: test: cmd perf: export PERF="yes" perf: test If 'cmd' is complicated (and it usually is), then this approach is a lot easier to maintain. Your approach to setting the environment variable in the cmd rule makes this more difficult.
-
AnthonyC over 5 yearsOddly enough I did test it earlier that showed it worked.. (not sure why now..) I can go back and delete the comment I guess..
-
holms over 5 yearsWhat about multiple variables?
-
MadScientist over 5 yearsEach variable has to be set on its own separate line in the makefile.
-
holms over 5 yearsThat's fine but your added it to the head of target. Just listing them in context of target won't work? Because it doesn't work for me
-
MadScientist over 5 yearsSorry but I don't understand what you mean. Probably you should file a new question rather than asking in the comments here.
-
jjmerelo over 5 yearsHow modern is modern?
-
MadScientist over 5 yearsTarget-specific variables were added in GNU make 3.77. They are exportable as of GNU make 3.81. See git.savannah.gnu.org/cgit/make.git/tree/NEWS
-
Sergei about 5 years@AnthonyC It works because there are two
MY_VAR
s: one is makefile variable accessed as${MY_VAR}
and another one is bash exported variable, accessed as$$MY_VAR
-
Eric Chen almost 5 yearsUseful. But cannot find a way to export only a set of variables.
-
smac89 about 3 yearsNote if the variable already exists in your makefile and you just want to export it to another command, you can use the syntax
export var ?=
without assigning a new value -
Ken almost 2 years.EXPORT_ALL_VARIABLES is right answer