Compilação de programas com make Prof. André Leon S. Gradvohl, Dr. [email protected] Plano de apresentação • O que é o make? • Vantagens • Estrutura de um makefile • Dependências e regras • Makefile avançado 2 O que é o make? • Make é um utilitário para facilitar a manutenção de programas. • A proposta do make é determinar automaticamente (baseado na data dos arquivos) que pedaços de um programa precisam ser recompilados; em seguida executar comandos para compilá-los e montá-los novamente em um único programa. • Na verdade, o make pode ser usado para qualquer tarefa que envolva atualização de arquivos. • Para usar o make, é preciso editar um arquivo texto (puro), geralmente chamado makefile, com as regras de compilação. 3 Vantagens do make • As vantagens do make são: 1. Organizar do processo de compilação dos arquivos 2. Evitar a compilação desnecessária de arquivos que não foram modificados. 3. Facilitar a manutenção dos arquivos necessários para a criação do programa. 4. Otimizar o processo de compilação dos programas. 4 Estrutura de um makefile • O makefile consiste de linhas de dependência que definem um target (regra), seguida por dois pontos e, opcionalmente, um conjunto de arquivos ou outras regras dos quais a regra inicial depende. • Após cada linha de dependência, pode existir uma série de comandos que definem como transformar os arquivos na regra. 5 Estrutura de um makefile • Exemplo: CC=gcc programa: arq1.o arq2.o <TAB> $(CC) arq1.o arq2.o –o programa arq1.o: arq1.c <TAB> $(CC) –c arq1.c –o arq1.o Para obter a regra programa, é preciso arq2.o: arq2.c executar antes as regras <TAB> $(CC) –c arq2.c –o arq2.o arq1.o e arq2.o Para executar a regra arq2.o, é preciso que o arquivo arq2.c. Se existir, arq2.c será compilado e gerará o arquivo arq2.o . Para executar a regra arq1.o, é preciso que o arquivo arq1.c. Se existir, arq1.c será compilado e gerará o arquivo arq1.o . 6 Estrutura de um makefile • Exemplo: CC=gcc programa: arq1.o arq2.o <TAB> $(CC) arq1.o arq2.o –o programa arq1.o: arq1.c <TAB> $(CC) –c arq1.c –o arq1.o arq2.o: arq2.c <TAB> $(CC) –c arq2.c –o arq2.o O que acontece se o arquivo arq2.c for modificado? R. Apenas as regras 1 e 3 serão executadas novamente. 7 Exercício makefile • Suponha que tenhamos um programa em C dividido da seguinte forma: 1. 2. 3. 4. 5. No arquivo main.c está o programa principal. No arquivo funcoes.h está a definição de todas as funções principais que serão usadas no programa. No arquivo funcoesAux.h está a definição de todas as funções principais que serão usadas no programa. No arquivo funcoes.c estão as funções principais do programa. No arquivo funcoesAux.c estão as funções auxiliares do programa. • Observações: I. As funções principais utilizam funções auxiliares. II. A função main, no programa principal, utiliza tanto funções principais quanto funções auxiliares. III. Queremos criar uma regra que apague o programa executável e todos os arquivos objeto (.o) gerados a partir das funções auxiliares. Como seria esse makefile para gerar o programa Prog.exe? 8 Exercício makefile: Solução CC=gcc Prog.exe: main.o funcoes.o funcoesAux.o $(CC) main.o funcoes.o funcoesAux.o –o Prog.exe main.o: main.c funcoes.h funcoesAux.h $(CC) –c main.c –o main.o funcoes.o: funcoes.c funcoes.h funcoesAux.h $(CC) -c funcoes.c –o funcoes.o funcoesAux.o: funcoesAux.c funcoesAux.h $(CC) -c funcoesAux.c –o funcoesAux.o clean: rm –f funcoesAux.o funcoesAux.o main.o Prog.exe 9 Makefile avançado • Como qualquer interpretador de scripts, o make também interpreta variáveis e alguns símbolos reservados. • Por exemplo, podemos especificar qual o compilador a ser utilizado, atribuindo o nome do compilador à variável CC, como fizemos nos exemplos anteriores: • CC=gcc • Podemos também especificar bibliotecas específicas: • LIBS=-lpthread 10 Makefile avançado • Como qualquer interpretador de scripts, o make aceita comentários, interpreta variáveis e alguns símbolos reservados. • Por exemplo, podemos especificar qual o compilador a ser utilizado, atribuindo o nome do compilador à variável CC, como fizemos nos exemplos anteriores: • CC=gcc • Podemos também especificar bibliotecas específicas: • LIBS=-lpthreads • Veja o exemplo a seguir. 11 Makefile avançado #Definicao do compilador CC=gcc #definição da biblioteca LIBS=-lpthread Prog.exe: main.o funcoes.o funcoesAux.o $(CC) main.o funcoes.o funcoesAux.o $(LIBS)–o Prog.exe main.o: main.c funcoes.h funcoesAux.h $(CC) –c main.c –o main.o funcoes.o: funcoes.c funcoes.h funcoesAux.h $(CC) -c funcoes.c –o funcoes.o funcoesAux.o: funcoesAux.c funcoesAux.h $(CC) -c funcoesAux.c –o funcoesAux.o clean: rm –f funcoesAux.o funcoesAux.o main.o Prog.exe 12 Makefile avançado • Além das variáveis definidas pelo usuário, o makefile possui alguns truques. Por exemplo: • FONTES=$(wildcard *.c) • O comando lista todos os arquivos que terminam com .c no diretório atual. • OBJETOS=$(FONTES:.c=.o) • O comando substitui todos os arquivos Fontes que contêm extensão .c por .o. • Informe o que acontece no exemplo a seguir: 13 Makefile avançado FONTES=$(wildcard *.c) OBJETOS=$(FONTES:.c=.o) lista: listaFontes listaObjetos listaFontes: $(FONTES) @echo “Os arquivos fonte sao” $(FONTES) listaObjetos: $(OBJETOS) @echo “Os arquivos objetos sao” $(OBJETOS) O que acontece se os arquivos com a extensão .o não existirem? R. O make os cria, pois sabe que os arquivos .c são compilados com o compilador para a linguagem C. 14 Makefile avançado • Na seção de regras, um truque interessante pode ser o seguinte: %.o: %.c $(CC) –c $< -o $@ • Basicamente, o que a regra diz é que todo arquivo .o depende de um arquivo .c. • O comando para gerar o arquivo .o a partir do arquivo .c é a seguinte: • Compilador $(CC) –c sem o linker. • Deve usar como fonte a dependência $< • E gerar como saída a regra $@ • Portanto, o comando pode ser substituído por: gcc –c arq1.c –o arq1.o 15 Exercício makefile avançado • O que faz o arquivo makefile a seguir? Considera como FONTES todos os arquivos com extensão.c. CC=gcc LIBS=-lpthread FONTES=$(wildcard *.c) os arquivos com extensão .o possuem o mesmo nome OBJETOS=$(FONTES:.c=.o) dos arquivos .c e ficarão na variável OBJETOS. Prog.exe: $(OBJETOS) $(CC) $(OBJETOS) $(LIBS) -o $@ %.o: %.c $(CC) -c $< -o $@ clean: rm -f *.o Prog.exe Para gerar o Prog.exe são necessários todos os arquivos objetos. Para cada arquivo .o deve existir um arquivo .c que deve ser compilado de acordo com o comando abaixo. 16 Por fim... • Nessa apresentação não foram exploradas todas as possibilidades do make, apenas as mais comuns. • O make é muito poderoso e, se bem utilizado, pode diminuir bastante o tempo gasto para compilar um programa. 17