Matt Joiner
Matt Joiner

Reputation: 118530

Disable make builtin rules and variables from inside the make file

I want to disable builtin rules and variables as per passing the -r and -R options to GNU make, from inside the make file. Other solutions that allow me to do this implicitly and transparently are also welcome.

I've found several references to using MAKEFLAGS, and had similar problems.

Upvotes: 82

Views: 36556

Answers (8)

HolyBlackCat
HolyBlackCat

Reputation: 96256

Do this:

MAKEFLAGS += rR
$(foreach x,$(filter-out .% MAKE% SHELL CURDIR,$(.VARIABLES)) MAKEINFO,$(if $(filter default,$(origin $x)),$(eval override undefine $x)))

Here, rR is equivalent to --no-builtin-rules --no-builtin-variables.

--no-builtin-rules seems to work properly, but --no-builtin-variables is wonky.

--no-builtin-variables prevents the recipes from seeing the variables, but if you try to access them outside of a recipe, they are still there.

That's what the second line is for. It manually undefines all built-in variables. (Same idea as in @JohnMarshall's answer, but without shell invocations.)

It removes all variables for which $(origin ) reports default, except that it ignores SHELL,CURDIR, and variables starting with . and MAKE (except MAKEINFO), since those look useful.

Upvotes: 1

John Marshall
John Marshall

Reputation: 7005

Disabling the built-in rules is done by writing an empty rule for .SUFFIXES:

.SUFFIXES:

Having erased the built-in rules, I'm not sure that erasing the built-in variables helps you much more than just remembering to set them yourself or not use them, but you could use something like

$(foreach V,
    $(shell make -p -f/dev/null 2>/dev/null | sed -n '/^[^:#= ]* *=/s/ .*//p'),
    $(if $(findstring default,$(origin $V)),$(eval $V=)))

...which is admittedly fairly crazy. If there is a way to get a list of the defined variables from within make (instead of shelling out to another make), it would be viable. As it is, it's not really much better than

CC=
CXX=
# etc, for each likely built-in variable

Upvotes: 54

Jaakko
Jaakko

Reputation: 5360

https://www.gnu.org/software/make/manual/make.html#Canceling-Rules

# Disable built-in rules and variables
MAKEFLAGS += --no-builtin-rules
MAKEFLAGS += --no-builtin-variables

# Makefile begins
main: main.c
    cc main.c -o main

Upvotes: 19

Armali
Armali

Reputation: 19375

Disabling of built-in rules by writing an empty rule for .SUFFIXES does not work if one then writes another .SUFFIXES rule to add previously known suffixes - the built-in rules are re-enabled. Example: One wants to define rules for .c.i and .i.o, and to disable the built-in rule .c.o. Writing

.SUFFIXES:
.SUFFIXES: .o .i .c

does not work - it does not prevent the built-in rule .c.o from being applied.

The solution is the one employed by Marc Eaddy and documented in the GNU make manual, 10.5.6 Canceling Implicit Rules:

You can override a built-in implicit rule (or one you have defined yourself) by defining a new pattern rule with the same target and prerequisites, but a different recipe. When the new rule is defined, the built-in one is replaced. The new rule’s position in the sequence of implicit rules is determined by where you write the new rule.

You can cancel a built-in implicit rule by defining a pattern rule with the same target and prerequisites, but no recipe. For example, the following would cancel the rule that runs the assembler:

    %.o : %.s

Upvotes: 11

Brandon Bloom
Brandon Bloom

Reputation: 1342

@hseldon has the right idea because .SUFFIXES doesn't cover the match-everything built-in implicit rules. However, I don't think his syntax is exactly right.

MAKEFLAGS += --no-builtin-rules

.SUFFIXES:
.SUFFIXES: .you .own .here

See http://www.gnu.org/software/make/manual/make.html#Match_002dAnything-Rules and http://www.gnu.org/software/make/manual/make.html#index-g_t_002eSUFFIXES-998

Upvotes: 39

hseldon
hseldon

Reputation: 35

################################################################
# DISABLE BUILT-IN RULES
#
.SUFFIXES:
    MAKEFLAGS += -r

Upvotes: 1

Marc Eaddy
Marc Eaddy

Reputation: 1792

This works for me:

# Disable implicit rules to speedup build
.SUFFIXES:
SUFFIXES :=
%.out:
%.a:
%.ln:
%.o:
%: %.o
%.c:
%: %.c
%.ln: %.c
%.o: %.c
%.cc:
%: %.cc
%.o: %.cc
%.C:
%: %.C
%.o: %.C
%.cpp:
%: %.cpp
%.o: %.cpp
%.p:
%: %.p
%.o: %.p
%.f:
%: %.f
%.o: %.f
%.F:
%: %.F
%.o: %.F
%.f: %.F
%.r:
%: %.r
%.o: %.r
%.f: %.r
%.y:
%.ln: %.y
%.c: %.y
%.l:
%.ln: %.l
%.c: %.l
%.r: %.l
%.s:
%: %.s
%.o: %.s
%.S:
%: %.S
%.o: %.S
%.s: %.S
%.mod:
%: %.mod
%.o: %.mod
%.sym:
%.def:
%.sym: %.def
%.h:
%.info:
%.dvi:
%.tex:
%.dvi: %.tex
%.texinfo:
%.info: %.texinfo
%.dvi: %.texinfo
%.texi:
%.info: %.texi
%.dvi: %.texi
%.txinfo:
%.info: %.txinfo
%.dvi: %.txinfo
%.w:
%.c: %.w
%.tex: %.w
%.ch:
%.web:
%.p: %.web
%.tex: %.web
%.sh:
%: %.sh
%.elc:
%.el:
(%): %
%.out: %
%.c: %.w %.ch
%.tex: %.w %.ch
%: %,v
%: RCS/%,v
%: RCS/%
%: s.%
%: SCCS/s.%
.web.p:
.l.r:
.dvi:
.F.o:
.l:
.y.ln:
.o:
.y:
.def.sym:
.p.o:
.p:
.txinfo.dvi:
.a:
.l.ln:
.w.c:
.texi.dvi:
.sh:
.cc:
.cc.o:
.def:
.c.o:
.r.o:
.r:
.info:
.elc:
.l.c:
.out:
.C:
.r.f:
.S:
.texinfo.info:
.c:
.w.tex:
.c.ln:
.s.o:
.s:
.texinfo.dvi:
.el:
.texinfo:
.y.c:
.web.tex:
.texi.info:
.DEFAULT:
.h:
.tex.dvi:
.cpp.o:
.cpp:
.C.o:
.ln:
.texi:
.txinfo:
.tex:
.txinfo.info:
.ch:
.S.s:
.mod:
.mod.o:
.F.f:
.w:
.S.o:
.F:
.web:
.sym:
.f:
.f.o:

Put this in a file named disable_implicit_rules.mk and include it in every makefile.

Upvotes: 7

Jack Kelly
Jack Kelly

Reputation: 18667

You could start the Makefile with a #! and call it something different so people don't try to use make directly:

#!/usr/bin/make -rRf
# ...

This will cause horrific problems if GNU make is not the system make. Maybe a wrapper script?

You can also read $(MAKEFLAGS) and make sure the required flags are present.

Upvotes: 3

Related Questions