Departamento de Ciência da
Computação - IME - USP
Este projeto foi originalmente elaborado
pelo professor Francisco Reverbel
OK, let's be straight about it,
the syntax of make is really stupid.
If you use spaces where you're supposed to use tabs or vice versa,
your makefile blows up. And the error messages are really confusing.
Fonte: Running Linux, Matt Welsh and Lar Kaufman
Neste exercício-programa você fará um programa em C que se chamara Make.c. O programa utilizará as estruturas de dados das notas de aulas do professor Paulo Feofiloff para a representação de um "digrafo de dependência" através de vetor de listas de adjacência, como descrito mais adiante.
O seu programa deverá chamar-se Make. O `M' maiúsculo em Make é para diferenciar o seu programa do utilitário make do UNIX. Da mesma maneira que o make, o seu programa, ao ser chamado na linha de comando sem opção alguma, lerá um arquivo de nome MakeFile contendo informações de dependência e comandos para reconstrução (rebuilding commands) de objetos. O F maiúsculo em MakeFile server para não confundirmos a entrada do Make com o arquivo Makefile; que vocês muito provavelmente estarão utilizando.
<target> : <dependências> <comando1> <comando2> ...
Um target é usualmente o nome de um arquivo que é gerado por um programa; exemplos de targets são arquivos executáveis (bin ou .o). Um target também pode ser o nome de uma ação, tal como "clean".
Uma dependência é um arquivo que é usado para criar o target. Um target pode depender de vários arquivos.
Um comando é uma ação que Make pode mandar que seja executada. Um regra pode ter mais que um comando, cada um em uma linha. Deve existir um caractere TAB ('\t') no início de cada linha que possui um comando.
A seguir está um exemplo típico de um arquivo MakeFile que seu programa Make deve ser capaz de tratar (os números das linhas foram colocada apenas para efeito de referência, eles não fazem parte do MakeFile):
1 meuprog: meuprog.o fila.o etc.o 2 gcc meuprog.o fila.o etc.o -o meuprog 3 4 meuprog.o: meuprog.c minhasdefs.h fila.h etc.h 5 gcc -c meuprog.c 6 7 fila.o: fila.c minhasdefs.h fila.h 8 gcc -c fila.c 9 10 etc.o: etc.c minhasdefs.h etc.h 11 gcc -c etc.c 12 13 clean: 14 rm -f meuprog.o fila.o etc.o 15 cp meuprog.c ../ultimo/meuprog-salvo.c 16 cp fila.c ../ultimo/fila-sava.cEste exemplo ilustra o formato do arquivo MakeFile que o seu programa deve tratar:
meu_prompt> gcc -c fila.cdeverá ser executado para reconstruir o target fila.o a partir dos arquivos fila.c, minhasdefs.h e fila.h. Neste particular MakeFile, cada linha de dependência é seguida por apenas uma linha de comando. Seu programa, entretanto, deve ser capaz de tratar o caso em que várias linhas de comando seguem uma linha de dependência.
As linhas de dependências em um MakeFile (ou Makefile) definem um digrafo de dependências: um digrafo onde os vértices correspondem a targets e arquivos e os arcos representam a dependência entre estes targets e arquivos. Sempre que um arquivo arquivo1 depende de um arquivo arquivo2 o correspondente digrafo de dependências deve conter um arco do vértice de nome arquivo1 ao vértice de nome arquivo2. A Linha 7 do nosso exemplo de MakeFile acima diz que o respectivo digrafo de dependências contém arcos do vértice de nome fila.o ao vértice de nome fila.c, ao vértice de nome minhasdefs.h, e ao vértice fila.h.
Um ciclo em um digrafo é caminho fechado. Mais precisamente, um ciclo é uma seqüência de vértices v1-v2-...-vk tal que
existe um arco de vi a vi+1 (i=1,...,k-1) e um arco de vk a v1.
Um digrafo de depêndencias não deve conter ciclos. Isto, entretanto, não é obstácute para que um digrafo correspondente a um arquivo MakeFile tenha circuitos. Isto apenas significa que o Make deverá ser capaz de verificar a presença ou não de ciclos no digrafo. A existência de ciclos deve ser considerada pelo Make como um erro na especificação do MakeFile. Detecção de ciclos é um dos objetos de estudo da Tarefa 4. Por enquanto não se preocupe com isto.
static char *nome[maxV], *comandos[maxV];
Para cada vértice v o seu programa deve manter em:
meu_prompt> MakeChamado desta maneira Make deverá procura no diretório corrente um arquivo de nome MakeFile e processá-lo da seguinte forma:
meu_prompt> make Makeproduza o executável de nome Make correspondente a sua Tarefa 3.
meu_prompt>tar -xvf tarefa3.tgzcrie um diretório que tenha o seu login na rede Linux como nome. Neste diretório devem estar todos os arquivos da sua Tarefa 3, inclusive o Makefile que você usou. Se você achar necessário coloque junto um arquivo 00-leia-me, onde você descreve algo que achar necessário: como limitações e bugs no seu programa