Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Advanced variable inheritance in GNU make

I'm reading the GNU make manual, and got confused about the variable inheritance mechanism. Let me go through the basics first.


I quote from the manual chapter 6.10 Variables from the Environment :

Variables in make can come from the environment in which make is run. Every environment variable that make sees when it starts up is transformed into a make variable with the same name and value.

So imagine that I open a shell (call it "shell 1") and I define two variables. Then I startup make with two options, "op1" and "op2". The program make itself reads a makefile and constructs a third variable, called "varC". We get the situation as in the figure below:

enter image description here


I continue with a quote from the manual:

When make runs a recipe, variables defined in the makefile are placed into the environment of each shell.

So that's what I am going to do now. The first recipe line for the target gets executed, for which make opens a temporary shell (call it "shell 2"). I presume that all variables "varA", "varB" and "varC" are present in this shell, and thus can be used by the recipe line. Although I am not 100% sure.

enter image description here


The manual continues about the case where a recipe calls make recursively:

By default, only variables that came from the environment or the command line are passed to recursive invocations. You can use the export directive to pass other variables.

The next recipe line is a recursive $(MAKE) call. The toplevel make opens a temporary shell (call it "shell 3") to run this sub-make instance. Because varC was not explicitely exported, I believe that it is not present in shell 3, nor in the sub-make. Am I correct?

enter image description here

I posted this topic to get clarifications from experienced makefile writers. I am a newbie to this topic, but I'm doing my best to study the manual and get started after that. All help is greatly appreciated :-)

PS: if you post an answer, please mention if your answer applies to Linux, Windows, or both.

like image 675
K.Mulier Avatar asked Sep 06 '25 23:09

K.Mulier


1 Answers

I think you're overdissecting the paragraph:

When 'make' runs a command script, variables defined in the makefile are placed into the environment of that command. This allows you to pass values to sub-'make' invocations. By default, only variables that came from the environment or the command line are passed to recursive invocations. You can use the 'export' directive to pass other variables.

All of this goes together, so ONLY environment variables set in the incoming environment, or on the command line, or explicitly 'export'-ed in the Makefile are placed in the environment of commands that are invoked (whether that command is $(MAKE) or something else).

One interesting corner case is a variable set both in the incoming environment and in the Makefile (but not explicitly exported). The Makefile value then overrides the incoming environment value, AND is also exported (because it was in the incoming environment, albeit with a different value).

Makefile:

TEST = test
default:
        @echo TEST="\"$$TEST\""

result:

$ make
TEST=""
$ TEST=xx make
TEST="test"
$ make TEST=xx
TEST="xx"
like image 168
Chris Dodd Avatar answered Sep 10 '25 06:09

Chris Dodd