O make é uma ferramenta de linha de comando usada para connstruir (compilar) projetos de software complexos. Ele utiliza um arquivo chamado Makefile, onde se definem as dependências entre os arquivos do projeto e os comandso que devem ser executados para produzir os executáveis ou artefatos finais.
Parâmetros Básicos do Make
-s: Executa os comandos silenciosamente, sem exibi-los no terminal.-C DIRETÓRIO: Altera o diretório de trabalho antes de iniciar a construção.
Sintaxe Fundamantal
Comentários: São indicados pelo caractere #. Tudo após ele na mesma linha é ignorado pelo make.
Regra de Construção: Constitui o bloco central do Makefile. Uma regra é composta por um alvo (target), suas prerequisitos (dependências) e uma ou mais receitas (comandos).
# Define metas falsas (não correspondem a arquivos reais)
.PHONY: limpar tudo
# Define a meta padrão a ser construída quando 'make' é chamado sem argumentos
.DEFAULT_GOAL: aplicativo
# Definição de uma variável
alvo_principal = saudacao
# Regra principal, depende da meta 'alvo_principal'
tudo: $(alvo_principal)
@echo "Construção completa"
# Regra para a meta 'alvo_principal', que depende de 'modulo.o'
$(alvo_principal): modulo.o
cc modulo.o -o $(alvo_principal)
# Regra usando '%' para correspondência de padrão
# Compila qualquer arquivo .c em um .o correspondente
%.o: %.c
cc -c $< -o $@
# Regra com '::' permite múltiplas definições independentes
limpar::
rm -f *.o $(alvo_principal)
limpar::
@echo "Limpeza concluída"
A diretiva .PHONY declara que os alvos listados não são nomes de arquivos. Isso impede o make de procurar por um arquivo chamado "limpar" e garante que a receita seja sempre executada quando solicitada.
Nota: O
makedecide se uma regra precisa ser reexecutada comparando os carimbos de data e hora (timestamps) dos arquivos. Se qualquer pré-requisito for mais recente que o alvo, a receita será disparada.
Variáveis Automáticas
$@: O nome do alvo da regra.$^: Todos os pré-requisitos, com nomes de arquivo únicos.$<: O primeiro pré-requisito.$*: O prefixo do alvo que corresponde ao padrão%.$?: Os pré-requisitos que são mais recentes que o alvo.
Variáveis
As variáveis no Makefile funcionam de forma semelhante a macros em C, armazenando texto. São referenciadas usando a sintaxe $(VAR). O modificador override é usado para forçar a atribuição de uma variável, mesmo que ela tenha sido definida na linha de comando.
Existem diferentes operadores de atribuição:
=: Atribuição recursiva (ou simples). O valor é expandido a cada vez que a variável é usada.:=: Atribuição simples (ou imediata). O valor é expandido no momento da definição.?=: Atribuição condicional. Define a variável apenas se ela ainda não tiver um valor.+=: Atribuição por acréscimo. Adiciona texto ao valor atual da variável.
A diferença entre = e := é crucial:
# Com '=' (expansão adiada)
origem = inicio
destino = $(origem) final
origem = conclusao
# Neste ponto, 'destino' será expandido para "conclusao final"
# Com ':=' (expansão imediata)
origem := inicio
destino := $(origem) final
origem := conclusao
# Neste ponto, 'destino' será expandido para "inicio final"
Funções
Funções são chamadas usando a sintaxe $(nome_funcao argumento1, argumento2). O Makefile oferece diversas funções embutidas:
$(shell COMANDO): Executa um comando do shell e retorna sua saída.$(wildcard padrão): Retorna uma lista de arquivos que correspondem ao padrão (ex.:*.c).$(subst de,para,texto): Substitui todas as ocorrências dedeporparanotexto.$(patsubst padrão,substituição,texto): Substitui palavras notextoque correspondam aopadrão.$(addprefix prefixo,texto): Adiciona umprefixoa cada palavra notexto.- : Invoca uma função definida pelo usuário.
Inclusão e Diretivas Condicionais
include: Inclui outro arquivo Makefile. Se o arquivo não existir, -include (ou sinclude) fará com que o make ignore o erro e continue.
inclua config.mk
Condicionais: Permitem executar partes da receita apenas se uma condição for verdadeira.
# Verifica se a variável MODO está definida como 'debug'
ifeq ($(MODO),debug)
FLAGS := -g -O0
else
FLAGS := -O2
endif
# Verifica se a variável SISTEMA não está definida como 'linux'
ifneq ($(SISTEMA),linux)
COMPILADOR := gcc
endif