Wie macht dieses Makefile C-Programm, ohne überhaupt einen Compiler anzugeben?

41

Ich habe ein Makefile aus dem Buch " Advanced Linux Programming (2001)" [code] verwendet . Es war seltsam für mich zu sehen, dass GNU make den Code korrekt kompiliert, ohne überhaupt einen Compiler im Makefile anzugeben. Es ist wie Backen ohne Rezept!

Dies ist eine Minimalversion des Codes:

test.c

int main(){}

Makefile

all:            test

und machen wirklich funktioniert! Dies ist der Befehl, den es ausführt:

cc     test.c   -o test

Ich konnte in der Dokumentation nichts Nützliches finden. Wie ist das möglich?


PS Ein zusätzlicher Hinweis: Auch die Sprache ist nicht angegeben; Da zur test.cVerfügung steht, GNU makeverwendet cc. Wenn es existiert test.cppoder test.cc(wenn es kein gibt test.c), verwendet es g++(und nicht c++).

Ho1
quelle
4
"Es ist wie Backen ohne Rezept!" Ein Rezept würde Sie auffordern, Wasser zu kochen, aber nicht, ob Sie Wasser mit einer Pfanne auf einem Gasherd, einer Pfanne auf einem Induktionsherd, einem elektrischen Wasserkocher oder einem Kessel auf einem Stativ über einem Feuer kochen sollten. Es würde Ihnen nicht einmal sagen, wo Sie Ihr Wasser bekommen sollten. Dies ist so, als würde man sagen make, man solle Wasser kochen und seine internen Regeln make
anwenden
1
@ Rhymoid Es ist wie schreien: Ich will einen Kuchen! Und dann makeüberprüft ein Roboter namens Ihren Kühlschrank und stellt fest, dass Mehl verfügbar ist. Dann backt er einen Standardkuchen nach seinem internen Rezept für Sie. :-)
Ho1
@ Ho1: Der Roboter könnte fragen, welchen Kuchen Sie haben möchten, Sir? :): D
Thushi

Antworten:

68

Make verwendet dazu die eingebauten Regeln . Hier erfahren Sie insbesondere, wie Sie C-Code kompilieren und Einzelobjektprogramme verknüpfen.

Du brauchst eigentlich nicht mal ein Makefile:

make test

würde ohne einen funktionieren.

Verwenden Sie die -pOption ohne Makefile , um die verborgenen Regeln anzuzeigen, die all dies ermöglichen :

make -p -f /dev/null

Wie von alephzero hervorgehoben , hat Make sehr lange (wenn nicht immer) Regeln eingebaut. Stuart Feldmans erste Version in Unix V7 definiert siefiles.c , und sein Papier von 1979 erwähnt sie. Sie sind auch Teil der POSIX-Spezifikation . (Dies bedeutet nicht, dass alle Implementierungen von Make diese unterstützen - das alte Borland Make für DOS unterstützt dies nicht, zumindest nicht bis Version 3.0.)

Stephen Kitt
quelle
2
Ich dachte schon, aber POSIX spezifiziert sie auch !
Stephen Kitt
5
@KingZoingo Make ist in der Tat eine Art Inferenz-Engine: Es enthält eine Reihe von Regeln (eingebaut und aus dem Makefile), vorhandene Artefakte (Dateien im aktuellen Verzeichnis oder im Makefile benannt) und angeforderte Artefakte (Ziele im Makefile); Es wird lediglich versucht, Regeln und vorhandene Artefakte abzugleichen, um festzustellen, ob die angeforderten Artefakte mithilfe dieser Regeln abgerufen werden können. Die eingebauten Regeln besagen, test.cdass damit produziert werden kann test. make -dwird Ihnen den Prozess im Detail zeigen ...
Stephen Kitt
4
@ Ho1 @StephenKitt Dies war makelange bevor GNU oder POSIX erfunden wurden. Die erste Version wurde vor fast 40 Jahren geschrieben, und es gab einige Prototypversionen, die bereits zuvor aus Shell-Skripten erstellt wurden.
Alephzero
3
@jamesqf CPPruft immer noch den Präprozessor auf ( cc -Enormalerweise). Der C ++ - Compiler ist CXX.
Stephen Kitt
3
@ Ho1 ist CXXin diesem Zusammenhang die Variable Make, kein Befehl - $(CXX)in einem Makefile wird durch einen Befehl zum Ausführen eines C ++ - Compilers ersetzt.
Stephen Kitt