O que é um Makefile?




O objetivo principal de um arquivo makefile é criar regras de compilação para programas de software. Ele é utilizado pelo programa make para compilar, linkar, montar arquivos de projeto, dentre outras tarefas.


Vantagens
  • Se alguma modificação altera apenas poucos arquivos, a compilação não precisa necessariamente recompilar todo o projeto. Por exemplo, o comando "-o file"  ('pretend that source file has not changed, even though it has changed') diz para o programa fazer de conta que aquele arquivo não foi modificado, mesmo que tenha sido, dispensando assim sua recompilação.
  • É possível integrar com ferramentas de documentação, verificação, e outras ferramentas, como doxygen e clang-format.
  • É uma forma de garantia de gerar sempre 'a mesma coisa' em computadores diferentes ou por desenvolvedores diferentes.


Estrutura

Como muitos tipos de arquivos, o makefile tem uma estrutura definida que deve ser seguida para o bom funcionamento de suas 'receitas':
target: dependencies
[tab] command

Vamos lá, o que significa cada uma dessas pequenas partes?
  • target: pode ser dito que o target é o nome da ação a ser tomada, cada target possui suas dependências e seus comandos. Para ficar mais clara sua interpretação, você pode imaginar o target como uma receita de bolo, então o target seria 'bolo' (não é um bom exemplo mas é de fácil compreensão);
  • dependencies: são os materiais necessários para executar as ações correspondentes aquele target;
  • [tab]: é uma regra no makefile que o tab são 4 espaços, e deve ser dado o tab, caso sejam dados os espaços será gerado um erro em sua execução;
  • command: é o comando ou os comandos necessários para satisfazer todas as necessidades daquele target.

Além da estrutura citada acima, os arquivos makefile permitem criar macros para facilitar o reuso de comandos e sua manutenção.

A definição de uma macro é a seguinte:
PROJ=Projeto_Teste

E posteriormente você pode utilizar esta macro utilizando a seguinte sintaxe:
$(PROJ)

Exemplo:
# Esta é uma linha comentada
CC=g++
# CFLAGS são opções passadas para o compilador
CFLAGS= -c -Wall

all: prog

prog: main.o fatorial.o hello.o
    $(CC) main.o fatorial.o hello.o -o prog

main.o: main.cpp
    $(CC) $(CFLAGS) main.cpp

fatorial.o: fatorial.cpp
    $(CC) $(CFLAGS) fatorial.cpp

hello.o: hello.cpp
    $(CC) $(CFLAGS) hello.cpp

clean:
    rm -rf *.o 

Abaixo são listados algumas variáveis internas que auxiliam o desenvolvimento de um makefile:
 $@ Nome da regra 
 $< Nome da primeira dependência 
 $^ Lista de dependências
 $? Lista de dependências mais recentes que a regra.
 $* Nome do arquivo sem sufixo



Automatizando

Como pode ser visualizado no arquivo acima, não é muito simples adicionar um novo arquivo no makefile. ERRADO. Da forma que foi feito o makefile acima, realmente pode se tornar complicado o crescimento de um projeto com mais arquivos, ter que criar uma nova regra para cada novo arquivo. Porém o que é muito comum é criar receitas reutilizáveis, ou seja, independente do arquivo a ser utilizado, a forma de compilar é a mesma. E isto facilita muito a interpretação do arquivo, e sua manutenção.


Abaixo segue a estrutura do mesmo makefile mostrado acima, porém com algumas melhorias agora que simplificam a inclusão de arquivos.

CC=g++
CFLAGS=-c –Wall
OBJECTS = main.o hello.o fatorial.o

all: prog

prog: $(OBJECTS)
    $(CC) $(OBJECTS) -o prog

%.o: %.cpp
    $(CC) $(CFLAGS) $<

clean:
    rm -rf *.o



Conclusão

Podemos dizer que o uso de makefiles ajuda em muito nossos desenvolvimentos, desde garantir a repetibilidade da forma de compilação, até a documentação e verificação do código.


Ficou com alguma dúvida ou tem alguma coisa a adicionar?
Entre em contato conosco.



Referências
https://www.gnu.org/software/make/
https://www.embarcados.com.br/introducao-ao-makefile/
https://pt.wikibooks.org/wiki/Programar_em_C/Makefiles
https://www3.nd.edu/~zxu2/acms60212-40212/Makefile.pdf

Postar um comentário

0 Comentários