Neste post mostramos como criar um Makefile para realizar a compilação de programas C/C++.
Makefiles são muito bons pra automatizar a execução de comandos, evitando ter que digitá-los toda vez.
Também gerenciam dependências entre arquivos, recompilando apenas o que é necessário.
Instalando do Make no Ubuntu Linux
Usamos o comando abaixo para realizar a instalação do GCC (compilador para C), G++ (compilador para C++) e do Make no Ubuntu 18.04.
sudo apt install gcc g++ make
Códigos de exemplo
Primeiro vamos criar os códigos de exemplo.
Segue o código de uma função simples, que retorna o valor absoluto de um inteiro.
// biblioteca.cpp #include "biblioteca.h" int absoluto(int val) { if (val >= 0) return val; else return -val; }
Segue o cabeçalho correspondente a esta função.
// biblioteca.h int absoluto(int val);
Segue código da função main(), que retorna 1 (o valor absoluto de -1).
// main.cpp #include <stdio.h> #include "biblioteca.h" int main() { int num = -1; printf("absoluto(%d) = %d\n", num, absoluto(num)); return 0; }
Estrutura de um Makefile
Um arquivo Makefile diz ao comando make como ele deve realizar a compilação do seu programa.
A estrutura básica de um Makefile é mostrada a seguir.
# Makefile # Comentários começam com o símbolo jogo-da-velha # e terminam no fim da linha NOMEDASECAO: DEPENDENCIAS COMANDOS OUTRASECAO: DEPENDENCIAS COMANDOS SECAOSEMDEPENDENCIAS: COMANDOS
Temos comentários, obviamente servem para descrever o que está sendo feito e desabilitar partes do código.
Cada seção é composta por seu nome (que corresponde a um arquivo principal sendo gerado pela seção), as dependências (que correspondem a outros arquivos utilizados para gerar o principal) e os comandos (que utilizam geram o arquivo principal).
Os comandos de uma seção devem ser precedidos por um caractere TAB (tabulação). Não podem ser espaços!
Funcionamento do Makefile
O nome da seção corresponde a um arquivo principal. As dependências correspondem a outros arquivos ou seções.
Se o arquivo principal não existe, então os comandos da seção são executados.
Se o arquivo principal existe, então é verificado se alguma das dependências são mais novas que o arquivo existente. Sendo alguma dependência mais nova, os comandos da seção são executados.
Se uma dependência for outra seção, o mesmo é feito para tal seção, gerando as dependências antes de executar os comandos da seção atual.
Criando o Makefile para compilação
Queremos que o Makefile gerencie a compilação dos códigos-objeto e executável; ele também deve gerenciar a limpeza (exclusão dos códigos-objeto e executável).
O código-objeto main.o (compilado a partir de main.cpp) deve ser recompilado sempre que main.cpp ou biblioteca.h forem modificados. Por isso nomeamos a seção main.o (arquivo de saída da compilação) e declaramos os arquivos main.cpp e biblioteca.h como dependências. O comando de compilação fica na linha abaixo com um caractere TAB inicial.
De forma semelhante, o código-objeto biblioteca.o (compilado a partir de biblioteca.cpp) deve ser recompilado sempre que biblioteca.cpp ou biblioteca.h forem modificados. Nomeamos a seção biblioteca.o, declaramos as dependências como biblioteca.cpp e biblioteca.h e definimos o comando de compilação.
Para gerar o executável main (linkado a partir de main.o e biblioteca.o) deve ser recompilado sempre que main.o ou biblioteca.o forem recompilados. Nomeamos a seção main, declaramos as dependências main.o e biblioteca.o e definimos o comando de likagem.
Definimos também a seção de nome clean para realizar a limpeza (excluir os códigos-objeto e do executável). A seção clean não possui dependências.
# Makefile # Linka códigos-objeto (cria executável main) main: main.o biblioteca.o g++ -o main main.o biblioteca.o # Compila main.cpp (cria código-objeto main.o) main.o: main.cpp biblioteca.h g++ -c -o main.o main.cpp # Compila biblioteca.cpp (cria código-objeto biblioteca.o) biblioteca.o: biblioteca.cpp biblioteca.h g++ -c -o biblioteca.o biblioteca.cpp # Remove executável e códigos-objeto clean: rm -f main *.o
Com esse arquivo salvo com o nome Makefile (inicial deve ser maiúlscula), basta executar o comando make.
Executando o comando make
O comando make realiza a leitura do arquivo Makefile e executa as seções presentes nas opções. Quando não fornecemos nenhuma opção ao comando make ele executará a primeira seção, correspondente a criação do executável main.
make -- g++ -c -o main.o main.cpp g++ -c -o biblioteca.o biblioteca.cpp g++ -o main main.o biblioteca.
Podemos então executar o programa.
./main -- absoluto(-1) = 1
Para limpar o executável e os códigos-objeto, basta executar o comando make com opção clean.
make clean -- rm -f main *.o
Quero mais!
Agora que já teve o pontapé inicial, é fácil prosseguir por conta:
Veja a documentação sobre a ferramenta GNU Make.
Até mais!
Leia mais:
Veja mais posts da Categoria Programação!