mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-12-28 19:58:51 +00:00
243 lines
8.4 KiB
Makefile
243 lines
8.4 KiB
Makefile
|
---
|
|||
|
language: make
|
|||
|
contributors:
|
|||
|
- ["Robert Steed", "https://github.com/robochat"]
|
|||
|
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
|
|||
|
filename: Makefile
|
|||
|
|
|||
|
lang: pt-br
|
|||
|
---
|
|||
|
|
|||
|
Um Makefile define um gráfico de regras para criar um alvo (ou alvos). Sua finalidade é fazer o mínimo de trabalho necessário para atualizar um alvo para a versão mais recente da fonte. Famosamente escrito ao longo de um fim de semana por Stuart Feldman em 1976, ainda é amplamente usada (particularmente no Unix e no Linux) apesar de muitos concorrentes e críticas.
|
|||
|
|
|||
|
Existem muitas variedades de make na existência, no entanto, este artigo pressupõe que estamos usando o GNU make, que é o padrão no Linux.
|
|||
|
|
|||
|
```make
|
|||
|
|
|||
|
# Comentários podem ser escritos assim.
|
|||
|
|
|||
|
# O arquivo deve ser nomeado Makefile e então pode ser executado como `make <alvo>`.
|
|||
|
# Caso contrário, nós usamos `make -f "nome-do-arquivo" <alvo>`.
|
|||
|
|
|||
|
# Aviso - use somente TABS para identar em Makefiles, nunca espaços!
|
|||
|
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
# Noções básicas
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
|
|||
|
# Regras são do formato
|
|||
|
# alvo: <pré-requisito>
|
|||
|
# onde os pré-requisitos são opcionais.
|
|||
|
|
|||
|
# Uma regra - esta regra só será executada se o arquivo0.txt não existir.
|
|||
|
arquivo0.txt:
|
|||
|
echo "foo" > arquivo0.txt
|
|||
|
# Mesmo os comentários nestas seções da 'receita' são passados para o shell.
|
|||
|
# Experimentar `make arquivo0.txt` or simplyou simplesmente `make` - primeira regra é o padrão.
|
|||
|
|
|||
|
# Esta regra só será executada se arquivo0.txt for mais recente que arquivo1.txt.
|
|||
|
arquivo1.txt: arquivo0.txt
|
|||
|
cat arquivo0.txt > arquivo1.txt
|
|||
|
# se as mesmas regras de citação do shell.
|
|||
|
@cat arquivo0.txt >> arquivo1.txt
|
|||
|
# @ pára o comando de ser ecoado para stdout.
|
|||
|
-@echo 'hello'
|
|||
|
# - significa que make continuará em caso de erro.
|
|||
|
# Experimentar `make arquivo1.txt` na linha de comando.
|
|||
|
|
|||
|
# Uma regra pode ter vários alvos e vários pré-requisitos
|
|||
|
arquivo2.txt arquivo3.txt: arquivo0.txt arquivo1.txt
|
|||
|
touch arquivo2.txt
|
|||
|
touch arquivo3.txt
|
|||
|
|
|||
|
# Make vai reclamar sobre várias receitas para a mesma regra. Esvaziar
|
|||
|
# receitas não contam e podem ser usadas para adicionar novas dependências.
|
|||
|
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
# Alvos falsos
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
|
|||
|
# Um alvo falso. Qualquer alvo que não seja um arquivo.
|
|||
|
# Ele nunca será atualizado, portanto, o make sempre tentará executá-lo.
|
|||
|
all: maker process
|
|||
|
|
|||
|
# Podemos declarar as coisas fora de ordem.
|
|||
|
maker:
|
|||
|
touch ex0.txt ex1.txt
|
|||
|
|
|||
|
# Pode evitar quebrar regras falsas quando um arquivo real tem o mesmo nome
|
|||
|
.PHONY: all maker process
|
|||
|
# Este é um alvo especial. Existem vários outros.
|
|||
|
|
|||
|
# Uma regra com dependência de um alvo falso sempre será executada
|
|||
|
ex0.txt ex1.txt: maker
|
|||
|
|
|||
|
# Alvos falsos comuns são: todos fazem instalação limpa ...
|
|||
|
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
# Variáveis Automáticas e Curingas
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
|
|||
|
process: Arquivo*.txt # Usando um curinga para corresponder nomes de arquivos
|
|||
|
@echo $^ # $^ é uma variável que contém a lista de pré-requisitos
|
|||
|
@echo $@ # imprime o nome do alvo
|
|||
|
#(fpara várias regras alvo, $@ é o que causou a execução da regra)
|
|||
|
@echo $< # o primeiro pré-requisito listado
|
|||
|
@echo $? # somente as dependências que estão desatualizadas
|
|||
|
@echo $+ # todas as dependências, incluindo duplicadas (ao contrário do normal)
|
|||
|
#@echo $| # todos os pré-requisitos 'somente pedidos'
|
|||
|
|
|||
|
# Mesmo se dividirmos as definições de dependência de regra, $^ vai encontrá-los
|
|||
|
process: ex1.txt arquivo0.txt
|
|||
|
# ex1.txt será encontrado, mas arquivo0.txt será desduplicado.
|
|||
|
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
# Padrões
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
|
|||
|
# Pode ensinar make a converter certos arquivos em outros arquivos.
|
|||
|
|
|||
|
%.png: %.svg
|
|||
|
inkscape --export-png $^
|
|||
|
|
|||
|
# As regras padrões só farão qualquer coisa se decidirem criar o alvo.
|
|||
|
|
|||
|
# Os caminhos de diretório são normalmente ignorados quando as regras de
|
|||
|
# padrões são correspondentes. Mas make tentará usar a regra mais
|
|||
|
# apropriada disponível.
|
|||
|
small/%.png: %.svg
|
|||
|
inkscape --export-png --export-dpi 30 $^
|
|||
|
|
|||
|
# make utilizará a última versão para uma regra de padrão que encontrar.
|
|||
|
%.png: %.svg
|
|||
|
@echo esta regra é escolhida
|
|||
|
|
|||
|
# No entanto, o make usará a primeira regra padrão que pode se tornar o alvo
|
|||
|
%.png: %.ps
|
|||
|
@echo esta regra não é escolhida se *.svg and *.ps estão ambos presentes
|
|||
|
|
|||
|
# make já tem algumas regras padrões embutidas. Por exemplo, ele sabe
|
|||
|
# como transformar arquivos *.c em arquivos *.o.
|
|||
|
|
|||
|
# Makefiles antigos podem usar regras de sufixo em vez de regras padrões
|
|||
|
.png.ps:
|
|||
|
@echo essa regra é semelhante a uma regra de padrão.
|
|||
|
|
|||
|
# make sobre a regra de sufixo
|
|||
|
.SUFFIXES: .png
|
|||
|
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
# Variáveis
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
# aka. macros
|
|||
|
|
|||
|
# As variáveis são basicamente todos os tipos de string
|
|||
|
|
|||
|
name = Ted
|
|||
|
name2="Sarah"
|
|||
|
|
|||
|
echo:
|
|||
|
@echo $(name)
|
|||
|
@echo ${name2}
|
|||
|
@echo $name # Isso não funcionará, tratado como $ (n)ame.
|
|||
|
@echo $(name3) # Variáveis desconhecidas são tratadas como strings vazias.
|
|||
|
|
|||
|
# Existem 4 lugares para definir variáveis.
|
|||
|
# Em ordem de prioridade, do maior para o menor:
|
|||
|
# 1: argumentos de linha de comando
|
|||
|
# 2: Makefile
|
|||
|
# 3: variáveis de ambiente do shell - faça importações automaticamente.
|
|||
|
# 4: make tem algumas variáveis predefinidas
|
|||
|
|
|||
|
name4 ?= Jean
|
|||
|
# Somente defina a variável se a variável de ambiente ainda não estiver definida.
|
|||
|
|
|||
|
override name5 = David
|
|||
|
# Pára os argumentos da linha de comando de alterar essa variável.
|
|||
|
|
|||
|
name4 +=grey
|
|||
|
# Anexar valores à variável (inclui um espaço).
|
|||
|
|
|||
|
# Valores variáveis específicos de padrões (extensão GNU).
|
|||
|
echo: name2 = Sara # Verdadeiro dentro da regra de correspondência
|
|||
|
# e também dentro de suas recursivas dependências
|
|||
|
# (exceto que ele pode quebrar quando seu gráfico ficar muito complicado!)
|
|||
|
|
|||
|
# Algumas variáveis definidas automaticamente pelo make
|
|||
|
echo_inbuilt:
|
|||
|
echo $(CC)
|
|||
|
echo ${CXX}
|
|||
|
echo $(FC)
|
|||
|
echo ${CFLAGS}
|
|||
|
echo $(CPPFLAGS)
|
|||
|
echo ${CXXFLAGS}
|
|||
|
echo $(LDFLAGS)
|
|||
|
echo ${LDLIBS}
|
|||
|
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
# Variáveis 2
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
|
|||
|
# O primeiro tipo de variáveis é avaliado a cada vez que elas são usadas.
|
|||
|
# TIsso pode ser caro, então existe um segundo tipo de variável que é
|
|||
|
# avaliado apenas uma vez. (Esta é uma extensão do GNU make)
|
|||
|
|
|||
|
var := hello
|
|||
|
var2 ::= $(var) hello
|
|||
|
#:= e ::= são equivalentes.
|
|||
|
|
|||
|
# Essas variáveis são avaliadas procedimentalmente (na ordem em que
|
|||
|
# aparecem), quebrando assim o resto da línguagem!
|
|||
|
|
|||
|
# Isso não funciona
|
|||
|
var3 ::= $(var4) and good luck
|
|||
|
var4 ::= good night
|
|||
|
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
# Funções
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
|
|||
|
# make tem muitas funções disponíveis.
|
|||
|
|
|||
|
sourcefiles = $(wildcard *.c */*.c)
|
|||
|
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
|
|||
|
|
|||
|
# O formato é $(func arg0,arg1,arg2...)
|
|||
|
|
|||
|
# Alguns exemplos
|
|||
|
ls: * src/*
|
|||
|
@echo $(filter %.txt, $^)
|
|||
|
@echo $(notdir $^)
|
|||
|
@echo $(join $(dir $^),$(notdir $^))
|
|||
|
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
# Diretivas
|
|||
|
#-----------------------------------------------------------------------
|
|||
|
|
|||
|
# Inclua outros makefiles, úteis para código específico da plataforma
|
|||
|
include foo.mk
|
|||
|
|
|||
|
sport = tennis
|
|||
|
# Compilação condicional
|
|||
|
report:
|
|||
|
ifeq ($(sport),tennis)
|
|||
|
@echo 'game, set, match'
|
|||
|
else
|
|||
|
@echo "They think it's all over; it is now"
|
|||
|
endif
|
|||
|
|
|||
|
# Há também ifneq, ifdef, ifndef
|
|||
|
|
|||
|
foo = true
|
|||
|
|
|||
|
ifdef $(foo)
|
|||
|
bar = 'hello'
|
|||
|
endif
|
|||
|
```
|
|||
|
|
|||
|
### More Resources
|
|||
|
|
|||
|
+ [documentação gnu make](https://www.gnu.org/software/make/manual/)
|
|||
|
+ [tutorial de carpintaria de software](http://swcarpentry.github.io/make-novice/)
|
|||
|
+ aprenda C da maneira mais difícil [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)
|