Como esse Makefile cria o programa C sem especificar um compilador?

41

Eu estava usando um Makefile do livro " Advanced Linux Programming (2001)" [código] . Foi estranho para mim ver que o GNU make compila o código corretamente, sem especificar um compilador no Makefile. É como assar sem receita!

Esta é uma versão mínima do código:

test.c

int main(){}

Makefile

all:            test

e fazer realmente funciona! Este é o comando que ele executa:

cc     test.c   -o test

Não encontrei nada útil na documentação. Como isso é possível?


PS Uma nota adicional: Mesmo o idioma não está especificado; Como test.cestá disponível, o GNU makeusa cc. Se existe test.cppou test.cc(quando não há test.c), ele usa g++(e não c++).

Ho1
fonte
4
"É como assar sem receita!" Uma receita diria para você ferver água, mas não se você deve ferver água usando uma panela em um fogão a gás, uma panela em um fogão de indução, uma chaleira elétrica ou um caldeirão colocado em um tripé em um incêndio. Nem diria onde você deveria conseguir sua água. Isso é como dizer makepara ferver água, e usando suas regras internas, makesó vai descobrir como;)
Rhymoid
1
@Rhymoid É como gritar: eu quero um bolo! E então, um robô chamado makeverifica sua geladeira e descobre que há farinha disponível e, em seguida, assa um bolo padrão para você a partir de sua receita interna. :-)
Ho1
@ Ho1: O robô pode perguntar: qual bolo você quer comer, senhor? :): D
Thushi 4/17

Respostas:

68

O Make faz isso usando suas regras internas . Eles dizem em particular como compilar código C e como vincular programas de objeto único.

Na verdade, você nem precisa de um Makefile:

make test

funcionaria sem um.

Para ver as regras ocultas que tornam tudo isso possível, use a -popção sem Makefile:

make -p -f /dev/null

Como apontado por alephzero , o Make possui regras embutidas há muito tempo (se não sempre); A primeira versão de Stuart Feldman no Unix V7 as definefiles.c , e seu artigo de 1979 as menciona. Eles também fazem parte da especificação POSIX . (Isso não significa que todas as implementações do Make os suportam - o antigo Borland Make for DOS não, pelo menos até a versão 3.0.)

Stephen Kitt
fonte
2
Eu pensei que sim, mas o POSIX os especifica também !
Stephen Kitt
5
O @KingZoingo Make é, de fato, um tipo de mecanismo de inferência: possui um conjunto de regras (internas e do Makefile), artefatos existentes (arquivos no diretório atual ou nomeados no Makefile) e artefatos solicitados (destinos no Makefile); ele simplesmente tenta corresponder regras e artefatos existentes para determinar se pode usá-los para obter os artefatos solicitados. As regras internas informam que test.cpode ser usado para produzir test. make -dirá mostrar-lhe o processo em detalhe ...
Stephen Kitt
4
@ Ho1 @StephenKitt Isso aconteceu makemuito antes da invenção do GNU ou POSIX. A primeira versão foi escrita há quase 40 anos, e havia algumas versões de protótipo criadas a partir de shell scripts, mesmo antes disso.
alephzero
3
@jamesqf CPPainda chama o pré-processador ( cc -Enormalmente); o compilador C ++ é CXX.
Stephen Kitt
3
@ Ho1 CXXnesse contexto é a variável Make, não um comando - $(CXX)em um Makefile será substituído por um comando para executar um compilador C ++.
Stephen Kitt