Comment ce Makefile crée-t-il le programme C sans même spécifier un compilateur?

41

J'utilisais un Makefile du livre " Advanced Linux Programming (2001)" [code] . C'était étrange pour moi de voir que GNU make compilait le code correctement, sans même spécifier un compilateur dans le Makefile. C'est comme cuire sans aucune recette!

Ceci est une version minimale du code:

test.c

int main(){}

Makefile

all:            test

et fait vraiment fonctionner! C'est la commande qu'il exécute:

cc     test.c   -o test

Je n'ai rien trouvé d'utile dans la documentation. Comment c'est possible?


PS Une note supplémentaire: Même la langue n’est pas spécifiée; Parce que test.cest disponible, GNU makeutilise cc. S'il existe test.cppou test.cc(quand il n'y en a pas test.c), il utilise g++(et non c++).

Ho1
la source
4
"C'est comme cuire sans aucune recette!" Une recette vous indiquerait de faire bouillir de l'eau, mais ne vous demandera pas de le faire en utilisant une casserole sur une cuisinière à gaz, une casserole sur une cuisinière à induction, une bouilloire électrique ou un chaudron placé sur un trépied au-dessus d'un feu. Cela ne vous dirait même pas où vous devriez aller chercher votre eau. C'est comme si on disait makede faire bouillir de l'eau et qu'on utilise ses règles internes makepour comprendre comment;)
Rhymoid
1
@ Rhymoid C'est comme crier: je veux un gâteau! Et puis un robot appelé makevérifie votre réfrigérateur et découvre qu'il y a de la farine disponible, puis prépare un gâteau par défaut à partir de sa recette interne. :-)
Ho1
@ Ho1: Le robot pourrait vous demander quel gâteau vous voulez avoir, monsieur? :): D
Thushi

Réponses:

68

Make le fait en utilisant ses règles intégrées . Celles-ci lui indiquent notamment comment compiler le code C et comment lier des programmes mono-objets.

En fait, vous n'avez même pas besoin d'un Makefile:

make test

fonctionnerait sans un.

Pour voir les règles cachées rendant tout cela possible, utilisez l' -poption sans makefile:

make -p -f /dev/null

Comme l'a souligné alephzero , Make a des règles intégrées depuis très longtemps (sinon toujours); La première version de Stuart Feldman dans Unix V7 les définitfiles.c , et son article de 1979 les mentionne. Ils font également partie de la spécification POSIX . (Cela ne signifie pas que toutes les implémentations de Make les prennent en charge - l'ancienne version de Make pour DOS de Borland ne fonctionne pas, du moins jusqu'à la version 3.0.)

Stephen Kitt
la source
2
Je le pensais bien, mais POSIX le spécifie aussi !
Stephen Kitt
5
@KingZoingo Make est en réalité un moteur d'inférence: il contient un ensemble de règles (intégrées et à partir du Makefile), des artefacts existants (fichiers du répertoire courant ou nommés dans le Makefile) et des artefacts demandés (cibles du Makefile); il essaie simplement de faire correspondre les règles et les artefacts existants pour déterminer s'il peut les utiliser pour obtenir les artefacts demandés. Les règles intégrées indiquent qu'il test.cpeut être utilisé pour produire test. make -dva vous montrer le processus en détail ...
Stephen Kitt
4
@ Ho1 @StephenKitt Cela a été fait makebien avant que GNU ou POSIX aient été inventés. La première version a été écrite il y a près de 40 ans et il existait déjà des versions de prototype à partir de scripts shell.
alephzero
3
@jamesqf CPPappelle toujours le préprocesseur ( cc -Egénéralement); le compilateur C ++ est CXX.
Stephen Kitt
3
@ Ho1 CXXdans ce contexte est la variable Make, pas une commande - $(CXX)dans un Makefile sera remplacé par une commande pour exécuter un compilateur C ++.
Stephen Kitt