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:// | ||