¿Cómo hace este Makefile el programa C sin siquiera especificar un compilador?

41

Estaba usando un Makefile del libro " Advanced Linux Programming (2001)" [código] . Fue extraño para mí ver que GNU make compila el código correctamente, sin siquiera especificar un compilador en el Makefile. ¡Es como hornear sin ninguna receta!

Esta es una versión mínima del código:

prueba.c

int main(){}

Makefile

all:            test

y hacer que realmente funcione! Este es el comando que ejecuta:

cc     test.c   -o test

No pude encontrar nada útil en la documentación. ¿Cómo es esto posible?


PD Una nota adicional: incluso el idioma no está especificado; Porque test.cestá disponible, GNU makeutiliza cc. Si existe test.cppo test.cc(cuando no existe test.c), usa g++(y no c++).

Ho1
fuente
44
"¡Es como hornear sin ninguna receta!" Una receta le indicaría que hierva agua, pero no si debe hervir agua usando una sartén en una estufa de gas, una sartén en una estufa de inducción, un hervidor eléctrico o un caldero colocado sobre un trípode sobre un fuego. Ni siquiera le diría dónde debería obtener su agua. Esto es como decirle makeque hierva agua, y usando sus reglas internas, makesimplemente descubrirá cómo;)
Rhymoid
1
@Rhymoid Es como gritar: ¡quiero un pastel! Y luego un robot llamado makerevisa su refrigerador y descubre que hay algo de harina disponible, luego hornea un pastel predeterminado para usted a partir de su receta interna. :-)
Ho1
@ Ho1: El robot podría preguntar: ¿Qué pastel quiere tener, señor? :): D
Thushi

Respuestas:

68

Make hace esto usando sus reglas incorporadas . En particular, le indican cómo compilar código C y cómo vincular programas de un solo objeto.

En realidad ni siquiera necesitas un Makefile:

make test

funcionaría sin uno.

Para ver las reglas ocultas que hacen posible todo esto, use la -popción sin Makefile:

make -p -f /dev/null

Como señaló alephzero , Make ha tenido reglas incorporadas durante mucho tiempo (si no siempre); La primera versión de Stuart Feldman en Unix V7 los definefiles.c , y su artículo de 1979 los menciona. También son parte de la especificación POSIX . (Esto no significa que todas las implementaciones de Make los admitan; el antiguo Borland Make para DOS no lo hace, al menos hasta la versión 3.0).

Stephen Kitt
fuente
2
¡Pensé que sí, pero POSIX también los especifica !
Stephen Kitt
55
@KingZoingo Make es, en efecto, una especie de motor de inferencia: tiene un conjunto de reglas (integradas y desde el Makefile), artefactos existentes (archivos en el directorio actual o nombrados en el Makefile) y artefactos solicitados (objetivos en el Makefile); simplemente trata de hacer coincidir las reglas y los artefactos existentes para determinar si puede usarlos para obtener los artefactos solicitados. Las reglas incorporadas indican que test.cse puede usar para producir test. make -dle mostrará el proceso en detalle ...
Stephen Kitt
44
@ Ho1 @StephenKitt Esto sucedió makemucho antes de que se inventaran GNU o POSIX. La primera versión fue escrita hace casi 40 años, y hubo algunas versiones prototipo construidas a partir de scripts de shell incluso antes de eso.
alephzero
3
@jamesqf CPPtodavía invoca el preprocesador ( cc -Enormalmente); El compilador de C ++ es CXX.
Stephen Kitt el
3
@ Ho1 CXXen este contexto es la variable Make, no un comando: $(CXX)en un Makefile será reemplazado por un comando para ejecutar un compilador de C ++.
Stephen Kitt el