Pesquisa de site

Uma breve introdução aos 'Makefiles' no desenvolvimento de software de código aberto com GNU Make


GNU Make é um utilitário de desenvolvimento que determina as partes de uma base de código específica que devem ser recompiladas e pode emitir comandos para executar essas operações na base de código. Este utilitário make específico pode ser usado com qualquer linguagem de programação, desde que sua compilação possa ser feita a partir do shell, emitindo comandos.

Para usar o GNU Make, precisamos ter algum conjunto de regras que defina o relacionamento entre os diferentes arquivos em nosso programa e comandos para atualizar cada arquivo. Eles são gravados em um arquivo especial chamado ‘makefile‘. O comando 'make' utiliza a base de dados 'makefile' e os horários das últimas modificações dos arquivos para decidir qual todos os arquivos devem ser recompilados novamente.

Conteúdo de um Makefile

Geralmente 'makefiles' contêm 5 tipos de coisas, a saber: regras implícitas, regras explícitas, definições de variáveis , diretivas e comentários.

  1. Uma regra explícita especifica como criar/refazer um ou mais arquivos (chamados de alvos, serão explicados mais tarde) e quando fazer o mesmo.
  2. Uma regra implícita especifica como criar/refazer um ou mais arquivos com base em seus nomes. Ele descreve como um nome de arquivo de destino está relacionado a um arquivo com nome semelhante ao destino.
  3. Uma definição de variável é uma linha que especifica um valor de string para uma variável a ser substituída posteriormente.
  4. Uma diretiva é uma instrução para o make fazer algo especial enquanto lê o makefile.
  5. Um símbolo '#' é usado para representar o início de um comentário dentro de makefiles . Uma linha que começa com ‘#’ é simplesmente ignorada.

Estrutura dos Makefiles

A informação que diz ao make como recompilar um sistema vem da leitura de um banco de dados chamado makefile. Um makefile simples consistirá em regras da seguinte sintaxe:

target ... : prerequisites ... 
	recipe 
... 
...

Um destino é definido para ser o arquivo de saída gerado pelo programa. Também podem ser alvos falsos, que serão explicados abaixo. Exemplos de arquivos de destino incluem executáveis, arquivos de objeto ou alvos falsos como limpo, instalar, desinstalar etc.

Um pré-requisito é um arquivo usado como entrada para criar os arquivos de destino.

Uma receita é a ação que make executa para criar o arquivo de destino com base nos pré-requisitos. É necessário colocar tabulação antes de cada receita dentro dos makefiles a menos que especifiquemos a variável '.RECIPEPREFIX' para definir algum outro caractere como prefixo para receita.

Um exemplo de Makefile

final: main.o end.o inter.o start.o
	gcc -o final main.o end.o inter.o start.o
main.o: main.c global.h
	gcc -c main.c
end.o: end.c local.h global.h
	gcc -c end.c
inter.o: inter.c global.h
	gcc -c inter.c
start.o: start.c global.h
	gcc -c start.c
clean:
	rm -f main.o end.o inter.o start.o

No exemplo acima usamos arquivos fonte 4 C e dois arquivos de cabeçalho para criar o executável final. Aqui, cada arquivo ‘.o’ é um destino e um pré-requisito dentro do makefile. Agora dê uma olhada no último nome do alvo clean. É apenas uma ação e não um arquivo de destino.

Como normalmente não precisamos disso durante a compilação, não está escrito como pré-requisito em nenhuma outra regra. Os alvos que não se referem a arquivos, mas são apenas ações, são chamados de alvos falsos. Eles não terão nenhum pré-requisito como outros arquivos de destino.

Como o GNU Make processa um Makefile

Por padrão, make começa com o primeiro alvo no 'makefile' e é chamado como ' meta padrão'. Considerando nosso exemplo, temos final como nosso primeiro alvo. Como seus pré-requisitos incluem outros arquivos objeto, eles devem ser atualizados antes da criação do final. Cada um desses pré-requisitos é processado de acordo com suas próprias regras.

A recompilação ocorre se houver modificações feitas nos arquivos de origem ou nos arquivos de cabeçalho ou se o arquivo objeto não existir. Depois de recompilar os arquivos-objeto necessários, make decide se deseja vincular novamente final ou não. Isto deve ser feito se o arquivo final não existir, ou se algum dos arquivos objeto for mais recente que ele.

Portanto, se alterarmos o arquivo inter.c, ao executar make ele recompilará o arquivo fonte para atualização o arquivo objeto inter.o e depois linkar final.

Usando variáveis dentro de Makefiles

Em nosso exemplo, tivemos que listar todos os arquivos de objetos duas vezes na regra para final conforme mostrado abaixo.

final: main.o end.o inter.o start.o
	gcc -o final main.o end.o inter.o start.o

Para evitar tais duplicações, podemos introduzir variáveis para armazenar a lista de arquivos objetos que estão sendo usados dentro do makefile. Usando a variável OBJ podemos reescrever o exemplo makefile para um semelhante mostrado abaixo.

OBJ = main.o end.o inter.o start.o
final: $(OBJ)
	gcc -o final $(OBJ)
main.o: main.c global.h
	gcc -c main.c
end.o: end.c local.h global.h
	gcc -c end.c
inter.o: inter.c global.h
	gcc -c inter.c
start.o: start.c global.h
	gcc -c start.c
clean:
	rm -f $(OBJ)

Regras para limpar o diretório de origem

Como vimos no exemplo makefile, podemos definir regras paralimpar o diretório de origem removendo os arquivos-objeto indesejados após a compilação. Suponha que tenhamos um arquivo de destino chamado clean. Como make pode diferenciar as duas situações acima? Aí vem o conceito de alvos falsos.

Um alvo falso é aquele que não é realmente o nome de um arquivo, mas apenas um nome para uma receita a ser executada sempre que uma solicitação explícita for feita a partir do makefile<. Um dos principais motivos para usaralvo falso é evitar conflito com um arquivo de mesmo nome. Outro motivo é melhorar o desempenho.

Para explicar isso, revelarei uma reviravolta inesperada. A receita para clean não será executada por padrão ao executar make. Em vez disso, é necessário invocar o mesmo emitindo o comando make clean.

.PHONY: clean
clean:
	rm -f $(OBJ)

Agora tente criar makefiles para sua própria base de código. Fique à vontade para comentar aqui com suas dúvidas.