Diferenças
Aqui você vê as diferenças entre duas revisões dessa página.
| c:o_sistema_make [2023/08/01 18:06] – criada maziero | c:o_sistema_make [2023/08/01 20:15] (atual) – edição externa 127.0.0.1 | ||
|---|---|---|---|
| Linha 1: | Linha 1: | ||
| + | ====== O sistema Make ====== | ||
| + | |||
| + | {{ progc_make.mkv |Video desta aula}} | ||
| + | |||
| + | O '' | ||
| + | |||
| + | O Make é uma ferramenta essencial em grandes projetos, quando há muitos arquivos envolvidos, ou quando a compilação usa muitos //flags// e opções. | ||
| + | |||
| + | ===== O makefile ===== | ||
| + | |||
| + | Para compilar um projeto, o programa '' | ||
| + | |||
| + | Um arquivo '' | ||
| + | |||
| + | <code make> | ||
| + | # comentário | ||
| + | alvo: dependência dependência dependência ... | ||
| + | receita | ||
| + | receita | ||
| + | ... | ||
| + | </ | ||
| + | |||
| + | Onde: | ||
| + | |||
| + | * **alvo**: nome do objeto a ser construído (geralmente um nome de arquivo ou uma ação sobre os arquivos) | ||
| + | * **dependência**: | ||
| + | * **receita**: | ||
| + | |||
| + | <note warning> | ||
| + | A endentação das linhas de comando abaixo de cada regra deve ser feita com **tabulação** (TAB) e nunca com espaços em branco. | ||
| + | </ | ||
| + | |||
| + | ===== Exemplo ===== | ||
| + | |||
| + | Considere um programa C composto pelos seguintes arquivos: | ||
| + | |||
| + | <code c escreva.h> | ||
| + | #ifndef __ESCREVA__ | ||
| + | #define __ESCREVA__ | ||
| + | |||
| + | void escreva (char *msg) ; | ||
| + | |||
| + | #endif | ||
| + | </ | ||
| + | |||
| + | <code c escreva.c> | ||
| + | #include < | ||
| + | |||
| + | void escreva (char *msg) | ||
| + | { | ||
| + | printf (" | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | <code c hello.c> | ||
| + | #include " | ||
| + | |||
| + | int main () | ||
| + | { | ||
| + | escreva (" | ||
| + | return (0) ; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | O arquivo a seguir define uma regra mínima para compilar o programa e gerar o executável '' | ||
| + | |||
| + | <code make Makefile> | ||
| + | hello: hello.c escreva.c escreva.h | ||
| + | gcc -Wall hello.c escreva.c -o hello | ||
| + | </ | ||
| + | |||
| + | A regra acima significa, literalmente: | ||
| + | |||
| + | * '' | ||
| + | * para (re)compilar o alvo '' | ||
| + | |||
| + | Ao executar o comando '' | ||
| + | |||
| + | < | ||
| + | $ ls | ||
| + | escreva.c | ||
| + | |||
| + | $ make | ||
| + | gcc hello.c escreva.c -o hello -Wall | ||
| + | |||
| + | $ ls | ||
| + | escreva.c | ||
| + | </ | ||
| + | |||
| + | <note tip> | ||
| + | Caso nenhum alvo seja indicado na linha de comando do '' | ||
| + | </ | ||
| + | |||
| + | Uma característica essencial do sistema '' | ||
| + | |||
| + | ===== Regras de compilação e de ligação ===== | ||
| + | |||
| + | Podem ser definidas regras separadas para compilação e ligação, agilizando a construção de sistemas com muitos arquivos: | ||
| + | |||
| + | <code make Makefile> | ||
| + | # regras de ligação | ||
| + | hello: hello.o escreva.o | ||
| + | gcc hello.o escreva.o -o hello | ||
| + | |||
| + | # regras de compilação | ||
| + | hello.o: hello.c escreva.h | ||
| + | gcc -c hello.c -Wall | ||
| + | |||
| + | escreva.o: escreva.c escreva.h | ||
| + | gcc -c escreva.c -Wall | ||
| + | </ | ||
| + | |||
| + | Assim, como as regras do arquivo '' | ||
| + | |||
| + | Exemplo (o comando '' | ||
| + | |||
| + | < | ||
| + | $ make | ||
| + | make: Nada a ser feito para `hello' | ||
| + | |||
| + | $ touch hello.c | ||
| + | $ make | ||
| + | gcc -c hello.c -Wall | ||
| + | gcc hello.o escreva.o -o hello -Wall | ||
| + | |||
| + | $ touch escreva.c | ||
| + | $ make | ||
| + | gcc -c escreva.c -Wall | ||
| + | gcc hello.o escreva.o -o hello -Wall | ||
| + | |||
| + | $ touch escreva.h | ||
| + | $ make | ||
| + | gcc -c hello.c -Wall | ||
| + | gcc -c escreva.c -Wall | ||
| + | gcc hello.o escreva.o -o hello -Wall | ||
| + | </ | ||
| + | |||
| + | ===== Regras usuais ===== | ||
| + | |||
| + | As seguintes regras são usualmente encontradas em arquivos '' | ||
| + | |||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | |||
| + | < | ||
| + | # regra default (1a) | ||
| + | all: hello | ||
| + | |||
| + | ... | ||
| + | |||
| + | # remove arquivos temporários | ||
| + | clean: | ||
| + | -rm -f *~ *.o | ||
| + | |||
| + | # remove tudo o que não for o código-fonte original | ||
| + | purge: clean | ||
| + | -rm -f hello | ||
| + | </ | ||
| + | |||
| + | <note tip> | ||
| + | Por default, o '' | ||
| + | </ | ||
| + | |||
| + | ===== Variáveis ===== | ||
| + | |||
| + | Variáveis podem ser criadas dentro do '' | ||
| + | |||
| + | <code make Makefile> | ||
| + | # Makefile de exemplo (Manual do GNU Make) | ||
| + | |||
| + | CFLAGS = -Wall # flags de compilacao | ||
| + | LDLIBS = -lm # bibliotecas a ligar | ||
| + | |||
| + | # arquivos-objeto | ||
| + | objects = main.o kbd.o command.o display.o \ | ||
| + | insert.o search.o files.o utils.o | ||
| + | |||
| + | edit : $(objects) | ||
| + | cc -o edit $(objects) $(LDLIBS) | ||
| + | main.o : main.c defs.h | ||
| + | cc -c main.c $(CFLAGS) | ||
| + | kbd.o : kbd.c defs.h command.h | ||
| + | cc -c kbd.c $(CFLAGS) | ||
| + | command.o : command.c defs.h command.h | ||
| + | cc -c command.c $(CFLAGS) | ||
| + | display.o : display.c defs.h buffer.h | ||
| + | cc -c display.c $(CFLAGS) | ||
| + | insert.o : insert.c defs.h buffer.h | ||
| + | cc -c insert.c $(CFLAGS) | ||
| + | search.o : search.c defs.h buffer.h | ||
| + | cc -c search.c $(CFLAGS) | ||
| + | files.o : files.c defs.h buffer.h command.h | ||
| + | cc -c files.c $(CFLAGS) | ||
| + | utils.o : utils.c defs.h | ||
| + | cc -c utils.c $(CFLAGS) | ||
| + | clean : | ||
| + | -rm -f edit $(objects) | ||
| + | </ | ||
| + | |||
| + | <note tip> | ||
| + | Na declaração da variável '' | ||
| + | </ | ||
| + | |||
| + | Regras podem ser usadas para alterar o valor de variáveis. No exemplo abaixo, a regra '' | ||
| + | |||
| + | <code make> | ||
| + | # compila com flags de depuração | ||
| + | debug: CFLAGS += -DDEBUG -g | ||
| + | debug: all | ||
| + | </ | ||
| + | |||
| + | ===== Regras implícitas ===== | ||
| + | |||
| + | O sistema '' | ||
| + | |||
| + | A geração de arquivo-objeto ('' | ||
| + | |||
| + | < | ||
| + | $(CC) $(CPPFLAGS) $(CFLAGS) -c fonte.c | ||
| + | </ | ||
| + | |||
| + | A ligação de arquivos-objeto ('' | ||
| + | |||
| + | < | ||
| + | $(CC) $(LDFLAGS) arq1.o arq2.o ... $(LDLIBS) -o executavel | ||
| + | </ | ||
| + | |||
| + | As variáveis usadas nessas regras implícitas têm os seguintes significados: | ||
| + | |||
| + | ^ variável ^ significado ^ exemplo ^ | ||
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| + | |||
| + | Eis como ficaria nosso '' | ||
| + | |||
| + | <code make Makefile> | ||
| + | CFLAGS = -Wall -g # gerar " | ||
| + | |||
| + | objs = hello.o escreva.o | ||
| + | |||
| + | # regra default (primeira regra) | ||
| + | all: hello | ||
| + | |||
| + | # regras de ligacao | ||
| + | hello: $(objs) | ||
| + | |||
| + | # regras de compilação | ||
| + | hello.o: | ||
| + | escreva.o: escreva.c escreva.h | ||
| + | |||
| + | # remove arquivos temporários | ||
| + | clean: | ||
| + | -rm -f $(objs) *~ | ||
| + | |||
| + | # remove tudo o que não for o código-fonte | ||
| + | purge: clean | ||
| + | -rm -f hello | ||
| + | </ | ||
| + | |||
| + | Uma lista de receitas e regras implícitas para várias linguagens pode ser encontrada [[http:// | ||
| + | |||
| + | ===== Tópicos avançados ===== | ||
| + | |||
| + | Este pequeno tutorial apenas " | ||
| + | |||
| + | * Variáveis automáticas | ||
| + | * Regras com padrões | ||
| + | * Condicionais | ||
| + | * // | ||
| + | * Makefiles recursivos | ||
| + | * Avaliação de regras em paralelo | ||
| + | * Geração automática de dependências | ||
| + | * ... | ||
| + | |||
| + | Esses e outros tópicos podem ser estudados em maior profundidade no [[http:// | ||