The Basics: Getting environment variables into GNU Make

[article]
Summary:

The most basic rule of GNU Make and the environment is that any variable set in the environment when GNU Make is started will be available as a GNU Make macro inside the Makefile.

The most basic rule of GNU Make and the environment is that any variable set in the environment when GNU Make is started will be available as a GNU Make macro inside the Makefile.

For example, if FOO is set in the environment to foo when GNU Make is run then the following Makefile:

$(warning $(FOO))

will output Makefile:1: foo verifying that FOO was indeed set to bar inside the Makefile.   It's possible to discover where FOO got that value using GNU Make's $(origin) function (see http://www.gnu.org/software/make/manual/html_node/Origin-Function.html#Origin-Function for the full documentation of $(origin)).

For a variable VAR defined in the environment and automatically imported into GNU Make $(origin VAR) has the value environment.  So enhancing the Makefile above to:

$(warning $(FOO) $(origin FOO))

gives the output Makefile:1: foo environment.

A variable imported from the environment can be overriden inside the Makefile just by setting its value.  So changing the example Makefile to

FOO=bar

$(warning $(FOO) $(origin FOO))

now gives the output Makefile:3: bar file.  Notice how the value of $(origin FOO) has changed from environment to file.  file indicates that the variable got its value inside a Makefile.

It's possible to prevent a definition in a Makefile from overriding the environment by specifying the -e (or --environment-overrides) option on the command-line of GNU Make. 

Running the above Makefile with, as before, FOO set to foo in the environment and the -e command-line option gives the output Makefile:2: foo environment override. Notice here that FOO has the value from the environment (foo) and that the output of $(origin) has changed to environment override to inform us that the variable came from the environment and even though it was redefined in the Makefile the value from the environment
was being used.

$(origin) can still return environment (instead of environment override) if the variable being tested was defined in the environment, but there was no attempt to redefine it in the Makefile.

If all you care about is whether the variable got its value from the environment then using $(firstword $(origin VAR)) is always guaranteed to return the string environment if the variable VAR is getting its value from the environment (regardless of whether -e is specified or not).

And it's possible to override the overriding using the override directive.  Suppose you absolutely want to guarantee that FOO gets its value inside the Makefile, and not from the environment you override it (more on the override directive here http://www.gnu.org/software/make/manual/html_node/Override-Directive.html#Override-Directive):

override FOO=bar

$(warning $(FOO) $(origin FOO))

This will output Makefile:3: bar override regardless of the value of FOO in the environment and whether or not you specify the -e command-line option.  Note that $(origin) tells you this is an override by returning $(override).

The other way to get around -e and set the value of a macro is by setting it on the GNU Make command-line.  For example, running FOO=foo make -e FOO=fooey on the following Makefile outputs Makefile:3: fooey command line:

FOO=bar

$(warning $(FOO) $(origin FOO))

Here $(origin) says command line.  But if FOO=bar were override FOO=bar in that Makefile the output would be: Makefile:3: bar override.

Confused?   There's actually a simple rule that enables you to figure this out (or you can just resort to $(origin)): the override directive beats the command line which beats environment overrides (-e option) which beats macros defined in a Makefile file which beats the original environment.

The Basics: Getting environment variables out of GNU Make

The environment GNU Make uses when it runs commands (such as commands in
any rules it is running) is the environment GNU Make started with plus any variables exported in the Makefile (plus a few it adds itself).

Consider this simple

About the author

John Graham-Cumming's picture John Graham-Cumming

John Graham-Cumming is Co-Founder at Electric Cloud, Inc . Prior to joining Electric Cloud, John was a Venture Consultant with Accel Partners, VP of Internet Technology at Interwoven, Inc. (IWOV), VP of Engineering at Scriptics Corporation (acquired by Interwoven), and Chief Architect at Optimal Networks, Inc. John holds BA and MA degrees in Mathematics and Computation and a Doctorate in Computer Security from Oxford University. John is the creator of the highly acclaimed open source POPFile project. He also holds two patents in network analysis and has others pending.

CMCrossroads is one of the growing communities of the TechWell network.

Featuring fresh, insightful stories, TechWell.com is the place to go for what is happening in software development and delivery.  Join the conversation now!

Upcoming Events

Oct 12
Oct 21
Nov 09
Nov 09