W jaki sposób ten Makefile tworzy program C nawet bez określania kompilatora?

41

Korzystałem z pliku Makefile z książki „ Advanced Linux Programming (2001)” [kod] . Dziwne było dla mnie, że GNU make poprawnie kompiluje kod, nawet nie określając kompilatora w Makefile. To jak pieczenie bez przepisu!

To jest minimalna wersja kodu:

test.c

int main(){}

Makefile

all:            test

i spraw, by naprawdę działało! Jest to polecenie, które wykonuje:

cc     test.c   -o test

Nie mogłem znaleźć niczego przydatnego w dokumentacji. Jak to mozliwe


PS Jedna dodatkowa uwaga: Nawet język nie jest określony; Ponieważ test.cjest dostępny, GNU makeużywa cc. Jeśli istnieje test.cpplub test.cc(gdy nie ma test.c), używa g++(i nie c++).

Ho1
źródło
4
„To jak pieczenie bez żadnego przepisu!” Przepis mówi ci, aby zagotować wodę, ale nie to, czy powinieneś gotować wodę za pomocą patelni na kuchence gazowej, patelni na kuchence indukcyjnej, czajniku elektrycznym lub kotle umieszczonym na statywie nad ogniem. Nie powiedziałoby ci nawet, skąd masz wziąć wodę. To tak, jakby kazać makegotować wodę, a stosując jej wewnętrzne zasady, makepo prostu
wymyślę
1
@ Rhymoid To jest jak krzyczenie: Chcę ciasto! A potem robot o nazwie makesprawdza lodówkę i dowiaduje się, że jest dostępna mąka, a następnie wypieka dla ciebie domyślne ciasto z wewnętrznego przepisu. :-)
Ho1
@ Ho1: Robot może zapytać, które ciasto chcesz mieć? :): D
Thushi,

Odpowiedzi:

68

Make robi to przy użyciu swoich wbudowanych reguł . Mówią one w szczególności, jak skompilować kod C i jak połączyć programy z jednym obiektem.

W rzeczywistości nie potrzebujesz nawet pliku Makefile:

make test

działałby bez niego.

Aby zobaczyć ukryte reguły, które umożliwiają to wszystko, użyj -popcji bez Makefile:

make -p -f /dev/null

Jak zauważył alephzero , Make ma wbudowane reguły od bardzo dawna (jeśli nie zawsze); Pierwsza wersja Stuarta Feldmana w Unixie V7 je definiujefiles.c , o czym wspomina jego artykuł z 1979 roku . Są również częścią specyfikacji POSIX . (Nie oznacza to, że wszystkie implementacje Make je obsługują - stara Borland Make for DOS nie, przynajmniej do wersji 3.0).

Stephen Kitt
źródło
2
Tak myślałem, ale POSIX też je określa !
Stephen Kitt
5
@KingZoingo Make jest w rzeczywistości rodzajem mechanizmu wnioskowania: ma zestaw reguł (wbudowany i z pliku Makefile), istniejące artefakty (pliki w bieżącym katalogu lub nazwane w pliku Makefile) i żądane artefakty (cele w Makefile); po prostu próbuje dopasować reguły i istniejące artefakty, aby ustalić, czy może ich użyć do uzyskania wymaganych artefaktów. Wbudowane reguły mówią, że test.cmożna go wykorzystać do produkcji test. make -dpokaże ci szczegółowo proces ...
Stephen Kitt
4
@ Ho1 @StephenKitt To było na makedługo przed wynalezieniem GNU lub POSIX. Pierwsza wersja została napisana prawie 40 lat temu, a wcześniej istniały pewne prototypowe wersje zbudowane ze skryptów powłoki.
alephzero,
3
@jamesqf CPPnadal wywołuje preprocesor ( cc -Ezwykle); kompilatorem C ++ jest CXX.
Stephen Kitt
3
@ Ho1 CXXw tym kontekście jest zmienną Make, a nie poleceniem - $(CXX)w Makefile zostanie zastąpione poleceniem, aby uruchomić kompilator C ++.
Stephen Kitt