Since version 4.0 of GNU Make a feature was added that almost every makefile should use. The 4.0 release notes describes the feature as “setting the -r and -R options in MAKEFLAGS inside a makefile now works as expected, removing all builtin rules and variables, respectively.”
Unfortunately, despite the claim it does not work as expected. Maybe there’s some justification for the behavior, but it certainly isn’t expected.
Why set the make flags -r
and -R
? The Linux makefile explains it
perfectly “Do not use make’s builtin rules and variables (this
increases performance and avoids hard-to-debug behavior).”
For me personally, setting those flags makes the ever useful output of
-p
and -d
less verbose and easier to read.
For this explainer I created two makefiles. Makefile.builtins
and
Makefile.nobuiltins
:
Makefile.builtins
$(foreach v, $(.VARIABLES), $(info $(v)))
Makefile.nobuiltins
MAKEFLAGS += -rR
$(foreach v, $(.VARIABLES), $(info $(v)))
Each makefile will print a list of defined variables names. We can
easily count how many variables each makefile has defined by piping to
wc
.
$ make -f Makefile.builtins | wc -l
make: *** No targets. Stop.
107
This invocation is showing 107 defined variables. This number includes variables inherited from the environment, which is around 10 variables in the chroot environment I’m using. So make has around 97 builtin variables. So how many variables does the second makefile have defined?
make -f Makefile.nobuiltins | wc -l
make: *** No targets. Stop.
107
I told you the behavior isn’t as expected.
To prove the behavior of -rR
on the command line isn’t the same as
setting MAKEFLAGS
consider the next invocation:
make -f Makefile.builtins -rR | wc -l
make: *** No targets. Stop.
44
Why isn’t it 0 (or 10 counting the inherited variable from the environment)? That’s because make needs a few variables to be around no matter what.
Those variables as far as I can tell are:
.DEFAULT_GOAL .FEATURES .LOADED .RECIPEPREFIX .SHELLFLAGS .VARIABLES CURDIR GNUMAKEFLAGS MAKE MAKEFILES MAKEFILE_LIST MAKEFLAGS MAKELEVEL MAKE_COMMAND MAKE_HOST MAKE_TERMERR MAKE_VERSION MFLAGS SHELL SUFFIXES
and the cryptic variables %D %F *D *F +D +F <D <F ?D ?F @D @F ^D ^F