Como Makefiles automatizam a compilação do GCC e economizam seu tempo

4

Digitar longos comandos gcc repetidamente é doloroso. Fica pior quando você adiciona bibliotecas ou ajusta o código constantemente. Makefiles corrige isso. Eles automatizam o processo de construção para que você pare de digitar os mesmos comandos repetidamente.

Aqui está um exemplo simples de Makefile. Ele substitui uma sequência de compilação manual.

Salve isso em um arquivo chamado makefile. Execute make para construir o executável. Existe uma regra estrita. Você deve usar um caractere de tabulação antes de cada linha gcc. Oito espaços falharão. A ferramenta de construção irá rejeitá-lo. Todas as outras linhas devem começar na margem esquerda.

Noções básicas sobre dependências

Um Makefile possui dois tipos de linhas. As linhas alinhadas à esquerda são linhas de dependência. Eles definem relacionamentos entre arquivos. As linhas tabuladas são comandos executáveis. Pode ser qualquer comando válido do UNIX.

Pegue esta linha:
main.o: main.c utilitário.h

Isto diz que main.o depende de main.c e util.h. Se algum arquivo de origem for alterado, o comando abaixo dele será executado. Ele recria main.o.

A primeira linha do arquivo é especial. Ele define o alvo final. Neste caso, esse é o executável principal. Ele lista main.o e util.o como dependências. Se esses arquivos objeto forem mais recentes que a fonte, o Make os reconstrói. Em seguida, ele os vincula ao binário final.

Este comando é executado somente se as dependências mudarem. Se nada mudou, Make não faz nada. Esse é o principal benefício. Ele pula o trabalho que já foi feito.

Por que isso é importante para o seu fluxo de trabalho

Programas grandes possuem muitas bibliotecas e arquivos de origem. Rastrear quais arquivos foram alterados manualmente está sujeito a erros. Um Makefile lida com isso automaticamente. Ele recompila apenas o que é necessário. Você altera um arquivo de cabeçalho. Make reconstrói todos os arquivos de origem que o incluem. Você altera uma função de utilidade. Faça reconstruções apenas desse arquivo de objeto e vincule novamente o executável.

Você não precisa estar em um sistema UNIX para usar essa lógica. A maioria dos compiladores e IDEs modernos inclui recursos semelhantes. Verifique a documentação do seu compilador. Procure ferramentas de automação de construção. Eles funcionam da mesma maneira sob o capô.

Isso nos traz de volta a cabeçalhos como stdio.h. Você os incluiu em exemplos anteriores sem explicar por quê. São bibliotecas padrão. Alguém os escreveu anos atrás. Eles os disponibilizaram para evitar que você reinventasse funções básicas. Makefiles e bibliotecas padrão fazem parte da mesma filosofia. Eles permitem que você se concentre na lógica em vez do clichê.

A ferramenta é tão boa quanto suas regras. Se suas dependências estiverem erradas, o Make não conseguirá reconstruir o que deveria. Ou pior, criará código desatualizado. Verifique seus caracteres de tabulação. Verifique os nomes dos seus arquivos. Acerte a sintaxe e o compilador fará o trabalho pesado.

Você pode estar se perguntando se a compilação manual é cada vez mais rápida. Para um único arquivo, talvez. Mas no segundo em que você toca em um cabeçalho em um projeto com vários arquivos, o método manual perde. Você começa a copiar comandos. Você começa a cometer erros de digitação. Você começa a se perguntar por que main.o não foi atualizado.

A mudança da digitação de comandos para a definição de regras é o ganho real. Você define o estado. A ferramenta impõe as transições. É uma pequena mudança de hábito. Vale a pena em cada construção subsequente.