11
votes

I try to implement a non-recursive make build system in my current project. What I struggle with is variables scopes. Target specific variables don't fit my needs as often variables define targets and not prerequisites. What I need is:

Makefile1:

SOMEVAR := original_value
include Makefile2
$(warning $(SOMEVAR))

Makefile2:

#some magic here to do what I want and make me happy
SOMEVAR := included_value
#and maybe here

And the output I want is 'original_value'.

Are there any strategies to make it real?

EDIT: The only solution I came for the moment is to force and organize myself to place all inlcudes in the end of each particular Makefile and use immediate variable assignment :=

1
That solution sounds pretty good. What's wrong with it? And what is SOMEVAR, what is it used for?Beta
The thing I don't like in this solution is that it is very shaky. If some poor guy who will take my place won't get the idea and place include somewhere else he'll get tons of surprisesAlexander Reshytko
If Makefile2 is included more than once, and it defines a recipe which refers to $(SOMEVAR), then it'll break horribly --- variables inside recipes are evaluated when the recipes are executed, which means that they'll all see $(SOMEVAR) last value, not the value it had when the recipe was defined.David Given

1 Answers

9
votes

One strategy is the old-fashioned solution to variable name collisions when all you have is global variables: add a prefix to your variable names in a form of poor-man's namespaces.

Makefile1:

Makefile1_SOMEVAR := original_value
include Makefile2
$(warning $(Makefile1_SOMEVAR))

Makefile2:

# no magic needed
Makefile2_SOMEVAR := included_value
# rest of Makefile2 uses $(Makefile2_SOMEVAR) of course

Hey presto, with a convention like this it's as if each makefile has its own local variables (or, at least, its own variables in a namespace that doesn't collide with any other makefiles).