Por que os Makefiles evitam que você copie e cole comandos do GCC

7

Sejamos honestos. Digitar longos comandos de compilação gcc manualmente é uma dor. Piora rapidamente quando sua base de código cresce, importa várias bibliotecas e você está constantemente ajustando as coisas. Você acaba tendo um pesadelo de copiar e colar que termina se você perder uma bandeira.

Digite makefiles.

Eles existem por um motivo: para impedir que você digite manualmente a mesma sequência de compilação repetidas vezes. Em vez de lembrar os sinalizadores exatos e a ordem dos arquivos de objetos, você escreve uma receita. Então você apenas digita make.

Como um Makefile realmente funciona

Você começa criando um arquivo chamado literalmente makefile. Sem extensão. Apenas o nome. Dentro, você define dependências.

Aqui está uma estrutura básica para um pequeno projeto C:

Observe o recuo. É aqui que os iniciantes tropeçam. Esse espaço antes do gcc? Tem que ser um caractere de tabulação. Não oito espaços. Uma guia. Se você usar espaços, make gerará um erro enigmático e você passará dez minutos se perguntando por que sua sintaxe parece boa ao olho humano, mas não à máquina. Cada linha de comando em uma dependência deve começar com uma guia. As próprias definições de dependência devem ser alinhadas à esquerda. Sem exceções.

A Lógica das Dependências

Um makefile possui dois tipos de linhas. As primeiras são linhas de dependência. Eles se parecem com alvo: pré-requisitos.

main.o: main.c utilitário.h

Isso se traduz em: “Eu preciso de main.o. Para obtê-lo, preciso de main.c e util.h.”

O segundo tipo é a linha executável. Ele fica na dependência e começa com uma guia. É o comando executado se make decidir que precisa ser reconstruído.

O sistema funciona com um princípio simples: se algum arquivo do lado direito dos dois pontos for mais recente que o arquivo da esquerda, execute os comandos abaixo. Alterar util.h? make vê, sabe que main.o e util.o dependem dele e os reconstrói. Ele automatiza a lógica.

A regra alvo

Existe uma regra de ouro para o topo do seu makefile. O primeiro alvo listado é aquele que make tenta construir por padrão.

No exemplo acima, main é a primeira linha. Então quando você executa make sem argumentos, ele cria o executável final.

principal: main.o utilitário.o
gcc -o main main.o util.o

Se você alterar main.o, isso acionará a reconstrução de main. Se você alterar main.c, ele acionará main.o, que então acionará main. É uma reação em cadeia. Você não precisa gerenciar isso. Você acabou de editar seu código-fonte e executar make.

E se eu não estiver no Unix?

Se você estiver no Windows ou usando um IDE como Visual Studio ou Xcode, talvez não veja um makefile no sentido tradicional. Não entrar em pânico. Seu compilador provavelmente possui funcionalidade equivalente.

Ambientes de desenvolvimento integrados geralmente possuem sistemas de construção subjacentes. Procure por “Configurações de compilação” ou “Propriedades do projeto”. Eles fazem a mesma coisa: rastreiam dependências e recompilam apenas o que mudou. Mas se você seguir a linha de comando, make é o padrão.

O panorama geral

Usar make não é