Mon 21 Sep 2015 02:59:44 AM UTC, original submission:
The motivation for the `override` declaration is to allow appending a value to a variable set as a command-line override. For example:
# Example taken from the gnu make manual, section 6.7
override CFLAGS += -g
For recursive makes, it is at least possible that it will be desired to pass the change down through recursive makes. That will not happen automatically because the original command-line override is passed through MAKEFLAGS as a command-line override to the sub-make, ignoring the local "override" declaration. Explicitly exporting the variable doesn't help, because command-line overrides override exported variables.
Two simple solutions seem reasonable:
override CFLAGS += -g
MAKEFLAGS += CFLAGS+=-g
or
override CFLAGS += -g
MAKEOVERRIDES += CFLAGS+=-g
Unfortunately, the first one never works, and the second one only works if CFLAGS is actually overridden on the command line.
---
Makefile:
ifeq "$(MAKELEVEL)" "0"
override foo+=added
MAKEOVERRIDES += foo+=added
all:
@echo outer: 'foo is "$(foo)" from $(origin foo)'
@$(MAKE)
else
all:
@echo inner: 'foo is "$(foo)" from $(origin foo)'
endif
---
$ # This works fine
$ make -s foo=override
outer: foo is "override added" from override
inner: foo is "override added" from command line
$ # But without the command line override, it fails
$ make -s
outer: foo is "added" from override
inner: foo is "" from undefined
---
If we append to MAKEFLAGS, then the outcome is even worse:
$ cat Makefile
ifeq "$(MAKELEVEL)" "0"
override foo+=added
MAKEFLAGS += foo+=added
all:
@echo outer: 'foo is "$(foo)" from $(origin foo)'
@$(MAKE)
else
all:
@echo inner: 'foo is "$(foo)" from $(origin foo)'
endif
$ make -s foo=override
outer: foo is "override added" from override
inner: foo is "override" from command line
$ make -s
outer: foo is "added" from override
inner: foo is "" from undefined
---
Curiously, if we append to both MAKEFLAGS and MAKEOVERRIDES, the result is as desired.
The issue comes from the regeneration of MAKEFLAGS in define_makeflags. In particular, towards the end of that function, in the conditional starting at main.c:3237, MAKEFLAGS has "-- $(MAKEOVERRIDES)" added to it, but only if there were any command-line overrides. If there are no command-line overrides, then the exported value of MAKEFLAGS will consist only of flags, and the modification of MAKEOVERRIDES will be lost. Consequently, appending to MAKEOVERRIDES only works if there are command-line overrides.
If we append a definition to MAKEFLAGS, then MAKEFLAGS will be regenerated as `<flags> -- $(MAKEOVERRIDES)`, since the definition in MAKEFLAGS is considered a command-line override during the first scan of MAKEFLAGS. The actual command-line override read during the first scan is not retained in MAKEFLAGS, on the assumption that it will appear in MAKEOVERRIDES.
Unfortunately, MAKEOVERRIDES will not be set correctly in that case, because the stanza starting at main.c:1623 where MAKEOVERRIDES is created happens before the first scan of MAKEFLAGS, and thus does not include any variable settings which had been added to MAKEFLAGS. If there are command-line overrides from the command-line, MAKEOVERRIDES is set to ${--command-variables--} and --command-variables-- is set to the list of command-line overrides, but in any event the modifications made to MAKEFLAGS will be lost.
If the modification is made to both MAKEFLAGS and MAKEOVERRIDES, then the modification will be passed to submakes, because the addition to MAKEFLAGS will cause MAKEFLAGS to include a reference to MAKEOVERRIDES, and the addition to MAKEOVERRIDES will therefore be used. (In fact, any setting in MAKEFLAGS would work.)
The simple resolution would be to unconditionally regenerate MAKEFLAGS with "-- $(MAKEOVERRIDES)", even if there are no command-line overrides, by changing line 3237 of main.c from:
if (all && command_variables)
to
if (all)
|