I was using a Makefile from the book "Advanced Linux Programming (2001)" [code]. It was strange for me to see that GNU make does compile the code correctly, without even specifying a compiler in the Makefile. It's like baking without any recipe!
This is a minimal version of the code:
test.c
int main(){}
Makefile
all: test
and make really works! This is the command it executes:
cc test.c -o test
I couldn't find anything useful in the documentation. How this is possible?
P.S. One additional note: Even the language is not specified; Because test.c
is available, GNU make
uses cc
. If there exists test.cpp
or test.cc
(when there is no test.c
), it uses g++
(and not c++
).
1 Answer 1
Make does this using its built-in rules. These tell it in particular how to compile C code and how to link single-object programs.
You actually don't even need a Makefile:
make test
would work without one.
To see the hidden rules that make all of this possible, use the -p
option with no Makefile:
make -p -f /dev/null
The -r
option disables these built-in rules.
As pointed out by alephzero, Make has had built-in rules for a very long time (if not always); Stuart Feldman's first version in Unix V7 defines them in files.c
, and his 1979 paper mentions them. They're also part of the POSIX specification. (This doesn't mean that all implementations of Make support them — the old Borland Make for DOS doesn't, at least up to version 3.0.)
-
5@KingZoingo Make is in effect an inference engine of sorts: it has a set of rules (built-in and from the Makefile), existing artifacts (files in the current directory or named in the Makefile), and requested artifacts (targets in the Makefile); it simply tries to match rules and existing artifacts to determine whether it can use them to obtain the requested artifacts. The built-in rules tell it
test.c
can be used to producetest
.make -d
will show you the process in detail...Stephen Kitt– Stephen Kitt2016年11月22日 21:39:22 +00:00Commented Nov 22, 2016 at 21:39 -
5@Ho1 @StephenKitt This was been in
make
long before GNU or POSIX were invented. The first version was written nearly 40 years ago, and there were some prototype versions built from shell scripts even before that.alephzero– alephzero2016年11月23日 01:07:09 +00:00Commented Nov 23, 2016 at 1:07 -
3@jamesqf
CPP
still invokes the preprocessor (cc -E
typically); the C++ compiler isCXX
.Stephen Kitt– Stephen Kitt2016年11月23日 05:22:19 +00:00Commented Nov 23, 2016 at 5:22 -
3@Ho1
CXX
in this context is the Make variable, not a command —$(CXX)
in a Makefile will be replaced by a command to run a C++ compiler.Stephen Kitt– Stephen Kitt2016年11月23日 10:47:22 +00:00Commented Nov 23, 2016 at 10:47 -
2
make
cares about extensions on Unix.make
(andcc
) is probably the main reason to actually care about extensions, in fact, since pattern rules are easier to use than writing the same rule for every source file.Jonathan Cast– Jonathan Cast2016年11月24日 03:47:42 +00:00Commented Nov 24, 2016 at 3:47
make
to boil water, and using its internal rules,make
will just figure out how ;)make
checks your fridge and finds out there's some flour available, then bakes a default cake for you from its internal recipe. :-)