I'm trying to access a variable declared by previous command (inside a Makefile).
Here's the Makefile
:
all:
./script1.sh
./script2.sh
Here's the script declaring the variable I want to access,script1.sh
:
#!/usr/bin/env bash
myVar=1234
Here's the script trying to access the variable previously defined, script2.sh
:
#!/usr/bin/env bash
echo $myVar
Unfortunately when I run make
, myVar
isn't accessible. Is there an other way around? Thanks.
The two separate invocations of the scripts create two separate environments. The first script sets a variable in its environment and exits (the environment is lost). The second script does not have that variable in its environment, so it outputs an empty string.
You can not have environment variables pass between environments other than between the environments of a parent shell to its child shell (not the other way around). The variables passed over into the child shell are only those that the parent shell has
export
-ed. So, if the first script invoked the second script, the value would be outputted (if it wasexport
-ed in the first script).In a shell, you would
source
the first file to set the variables therein in the current environment (and thenexport
them!). However, in Makefiles it's a bit trickier since there's no convenientsource
command.Instead you may want to read this StackOverflow question.
EDIT in light of @ghoti's answer: @ghoti has a good solution, but I'll leave my answer in here as it explains a bit more verbosely about environment variables and what we can do and not do with them with regards to passing them between environments.
Make will run each shell command in its own shell. And when the shell exits, its environment is lost.
If you want variables from one script to be available in the next, there are constructs which will do this. For example:
This causes Make to launch a single shell to handle both scripts.
Note also that you will need to export the variable in order for it to be visible in the second script; unexported variables are available only to the local script, and not to subshells that it launches.
UPDATE (per Kusalananda's comment):
If you want your shell commands to populate MAKE variables instead of merely environment variables, you may have options that depend on the version of Make that you are running. For example, in BSD make and GNU make, you can use "variable assignment modifiers" including (from the BSD make man page):
Thus, with BSD make and GNU make, you could do this:
Note that
script1.sh
does not include any shebang because it's being sourced, and is therefore running in the calling shell, whatever that is. That makes the shebang line merely a comment. If you're on a system where the default shell is POSIX but not bash (like Ubuntu, Solaris, FreeBSD, etc), this should still work because POSIX shells should all understand the concept of exporting variables.