How can i pass ENV variables between make targets
By default make invokes a new shell environment for each recipe, the export
ed variable on the first line isn't in scope for the second.
You can fix this in multiple ways:
Export the variable with make's export
directive
target1: export var1 := test
target1:
$(MAKE) target2
Use make's command line variable assignment
target1:
$(MAKE) target2 var1=test
Use shell command variable assignment
target1:
var1=test $(MAKE) target2
Combine the two commands in a single recipe
target1:
export var1=test; $(MAKE) target2
Force make to pass all recipes to the same shell instance
.ONESHELL:
target1:
export var1=test
$(make) target2
Pass environment variables to dependent targets in Makefile
I ended up doing the following:
.PHONY: lint test teamcity
lint:
# commands here
test:
# commands here
teamcity: export TEAMCITY_VERSION=1
teamcity: lint test
Here TEAMCITY_VERSION
is declared as a target-specific variable, and the export
directive exports it into the environment for prerequisite targets.
How to set child process' environment variable in Makefile
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 ).
exporting env variables from a common target to all targets in Makefile
Just don't put the assignments in a rule:
# file common.mk
export LD_LIBRARY_PATH=${MY_HOME}/LIBS:${LD_LIBRARY_PATH}
export MY_VERSION=2.2
...
and don't bother with the prerequisite setup
:
#file Makefile
include ${MY_RUN_DIR}/common.mk
run:
# do something, such as
@echo my version is $$MY_VERSION
Passing additional variables from command line to make
You have several options to set up variables from outside your makefile:
From environment - each environment variable is transformed into a makefile variable with the same name and value.
You may also want to set
-e
option (aka--environments-override
) on, and your environment variables will override assignments made into makefile (unless these assignments themselves use theoverride
directive . However, it's not recommended, and it's much better and flexible to use?=
assignment (the conditional variable assignment operator, it only has an effect if the variable is not yet defined):FOO?=default_value_if_not_set_in_environment
Note that certain variables are not inherited from environment:
MAKE
is gotten from name of the scriptSHELL
is either set within a makefile, or defaults to/bin/sh
(rationale: commands are specified within the makefile, and they're shell-specific).
From command line -
make
can take variable assignments as part of his command line, mingled with targets:make target FOO=bar
But then all assignments to
FOO
variable within the makefile will be ignored unless you use theoverride
directive in assignment. (The effect is the same as with-e
option for environment variables).Exporting from the parent Make - if you call Make from a Makefile, you usually shouldn't explicitly write variable assignments like this:
# Don't do this!
target:
$(MAKE) -C target CC=$(CC) CFLAGS=$(CFLAGS)Instead, better solution might be to export these variables. Exporting a variable makes it into the environment of every shell invocation, and Make calls from these commands pick these environment variable as specified above.
# Do like this
CFLAGS=-g
export CFLAGS
target:
$(MAKE) -C targetYou can also export all variables by using
export
without arguments.
set env variable from a Makefile command and use in another Make command
Let me suggest this:
get_env ::
$(eval MY_ENV := $somevalue)
cmd_1 cmd_2 :: get_env
MY_ENV=$(MY_ENV) python myscript.py $@
Some explanations:
::
makes the targets phony, so you won't have to add a line.PHONY: get_env cmd_1 cmd_2
in the Makefile;$@
is the current target
The key point is to add a dependency to get_env
in the rule, so that MY_ENV
is kept.
For a simpler trial, run make bar
or make baz
with this toy Makefile:
foo ::
$(eval qux := `pwd`)
bar baz :: foo
@echo "qux = $(qux) and target = $@"
Makefile environment variable for specific target
I would do it this way:
test: export GOOS=
test: export GOARCH=
test: fmt vet
go test ./...
workaround to make exporting environment variable from makefile possible
As Andreas says, there is no "workaround" for this. It's a fundamental feature of a POSIX operating system. The only way for the parent process (e.g. a shell) to have its environment modified is by doing something different than simply run make
. If you're willing to do that, then you have options.
For example, if your makefile does this:
target:
@echo 'export VAR=test'
then in your shell you can do this:
$ eval $(make target)
and now that variable will be set. Of course, this will fail miserably if your makefile prints ANYTHING except valid shell syntax so you can only do a very limited set of things.
Alternatively you can have the makefile write stuff to a file then source the file, like this:
target:
echo 'export VAR=test' > target
then:
$ make target
$ . target
Related Topics
Surprise! The Shell Suggests Command Line Switches
On-The-Fly Output Redirection, Seeing The File Redirection Output While The Program Is Still Running
Finding Threading Bottlenecks and Optimizing for Wall-Time with Perf
Distro for Linux Kernel Development
Substituting a String in Place of Variable in Shell
Docker Compose Volume Permissions Linux
The Sort -R Command Doesn't Sort Lines Randomly in Linux
How to Idiomatically Package Dependencies for a Qt Application Using Cpack
Symbol Lookup Error: ./Executablename: Undefined Symbol: _Zn18Qxmldefaulthandlerc2Ev
Sorting with Multiple Keys with Linux Sort Command
Bash Loop Through Directory Including Hidden File
What Is The Fastest Way to Display an Image in Qt on X11 Without Opengl
Busybox in Embedded Linux Shows "Applet Not Found"
Berkeley Db Mismatch Error While Configuring Ldap
Cx_Oracle: Distutils.Errors.Distutilssetuperror: Cannot Locate Oracle Include Files