On Mon, 2010-08-09 at 10:00 -0700, Philip Prindeville wrote:
Is this expected behavior?
Yes.
$ cat makefile1
override CFLAGS+=-DB
$(info makefile1: CFLAGS=$(CFLAGS))
all:
make -f makefile2
$ cat makefile2
$(info makefile2: CFLAGS=$(CFLAGS))
override CFLAGS+=-DC
$(info makefile2: CFLAGS=$(CFLAGS))
all:
@echo foo
$ make -f makefile1 CFLAGS=-DA
makefile1: CFLAGS=-DA -DB
make -f makefile2
makefile2: CFLAGS=-DA
makefile2: CFLAGS=-DA -DC
foo
So why isn't the CFLAGS that gets passed to the submake set to "-DA -DB"?
Because you're not invoking make with 'CFLAGS=$(CFLAGS)', you're
invoking it with 'CFLAGS=-DA'.
When the sub-make is invoked, it passes that same command line argument
to the sub-make; that is, running "make CFLAGS=-DA" means that the
recipe that invokes the sub-make will be the equivalent of "make -f
makefile2 CFLAGS=-DA"
Hence the behavior you see.
What's even more confusing is that make apparently keeps two copies...
the one that's in-scope for the current make, and the one that gets
re-exported into sub-makes.
Nope. It's much simpler than that: the assignments on the command line
are simply added to a variable which is then passed to sub-makes. See
the docs about the MAKEOVERRIDES variable, etc.
To allow the behavior you're looking for WOULD be much more complicated:
rather than just passing down the same assignments on the command line,
make would have to remember that a particular variable was a
command-line variable and construct the value to pass down (with all
quoting etc.) dynamically by looking up the values of those assignments
in the current make environment whenever it runs a recipe that appears
to be a sub-make (in which case your example still wouldn't work,
because you're using "make" instead of the $(MAKE) variable and you
didn't prefix your recipe line with "+", so make can't tell that this
recipe invokes a sub-make).
To avoid these kinds of issues, the typical method is to reserve certain
variables for the command line, such as CFLAGS, LDFLAGS, CPPFLAGS,
CXXFLAGS, etc. and then use a different variable internally to hold all
the values.
For example, you might have something like this:
CFLAGS = -O2 -g
CPPFLAGS =
_CFLAGS =<other flags>
_CPPFLAGS = -I...
%.o : %.c
$(CC) $(_CFLAGS) $(_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<
Or similar.