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 documento em CWEB que deverá charmar-se Make.w ou um programa em C. Este documento ou programa utilizará a biblioteca do SGB para a criação e recuperação de um `grafo de dependências', como descrito a seguir.
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ências e comandos para reconstrução (rebuilding comandos) de objetos. O `F' maiúsculo em MakeFile é para não confundir a entrada do Make com o arquivo Makefile; que você muito provavelmente estará 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. Nota: deve existir um caractere TAB ('\t') no início de cada linha.
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.oEste exemplo ilustra o formato do arquivo MakeFile que o seu programa deve tratar:
meu_prompt> gcc -c fila.c
deverá 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 grafo de dependências: um grafo onde os vértices correspondem a targets e arquivos de dependências, e os arcos representam a dependência entre estes targets e arquivos. Sempre que um arquivo arquivo1 depende de um arquivo arquivo2 o correspondente grafo 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 grafo 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 grafo é 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 grafo de depêndencias não deve conter ciclos. Isto, entretanto, não é obstáculo para que um grafo de dependência 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 circlos no grafo de dependências. A existência de ciclos deve ser considerada pelo Make como um erro na especificação do MakeFile. Detecção de ciclos será o objeto de estudo do Exercício-Programa 3. (Por enquanto não se preocupe com isto.)
meu_prompt> Make Chamado desta maneira Make deverá procura no diretório corrente um arquivo de no MakeFile e processá-lo da seguinte forma:
- (Contrói o grafo de dependências) Make lê o arquivo MakeFile, que tem o formato descrito acima, e contrói o correspondente grafo de dependências usando o módulo GB_GRAPH do SGB.
- (Salva o grafo) Após a criação do grafo de dependências na representação interna do SGB, Make converte este grafo para a representação simbólica (texto) do SGB e salva está representação no diretório corrente em um arquivo de nome MakeFile.gb. Tudo isto corresponde a uma simples chamada da rotina gb_save do módulo GB_SAVE do SGB.
meu_prompt> Make -g Chamado desta forma Make deve procurar no diretório corrente um arquivo de nome MakeFile.gb e processá-lo da seguinte maneira:
- (Restaura o grafo de dependências) Make lê o arquivo Makefile.gb, que contém um grafo de dependências no formato simbólico (texto) do SGB, e converte este grafo para a representação interna do SGB. Tudo isto corresponde a uma simples chamada da rotina restore_graph do módulo GB_SAVE do SGB.
- (Recria o MakeFile) Make percorre o grafo de dependências, produz e envia para a saída padrão (stdout) o MakeFile que gerou este grafo de dependências. Assim, ao percorrer o grafo de dependências Make envia para a saída padrão algo parecido com o exemplo de MakeFile acima, possivelmente sem as linhas em branco ou trocando alguma das regras de lugar; esta ordem é irrelevante, ela depende de como o seu Make gerou o grafo.
http://www.ime.usp.br/~coelho/grafos/sgb/exemplos/
Um vértice v, apontador para um registro ou estrutura do tipo Vertex, deve conter:
O nome comandos não é nome padrão de um dos campos de um registro do tipo Vertex. Use a seguinte macro do C:
#define comandos z.S
Assim, v->comandos é um nome mnemônico para v->z.S.
Important: Utility fields u and v of each vertex are reserved for use by the search routine when hashing is active. You can crash the system if you try to fool around with these values yourself, or if you use any subroutines that change those fields. The first two characters in the current graph's util_types field should be VV if the hash table information is to be saved by GB_SAVE.
Warning: Users of this hash scheme must preserve the number of vertices g->n in the current graph g. If g->n is changed, the hash table will be worthless, unless hash_setup is used to rehash everything.
Caution: This hash coding scheme is system-dependent, because it uses the system's character codes. If you create a graph on a machine with ASCII code and save it with GB_SAVE, and if you subsequently ship the resulting text file to some friend whose machine does not use ASCII code, your friend will have to rebuild the hash structure with hash_setup before being able to use hash_lookup successfully.
Como devemos alocar o grafo já que o número de vértices não é fixado logo de cara? A estrutura do SGB permite que arcos sejam alocados dinamicamente, mas não permite que o mesmo seja feito com vértices. Uma possibilidade é fazer um tipo de realloc; podemos chamar de gb_alloc. Que tal? Por favor, proponham suas soluções para este problema.
cweave, latex,
ctangle
(se você fez em CWEB) e gcc
.
meu_prompt> make Make.texgere o documento Make.tex correspondente ao seu EP2,
meu_prompt> make Make.dviproduza o Make.dvi correspondente ao seu EP2,
meu_prompt> make Make.ccrie o arquivo Make.c correspondente ao seu EP2, e
meu_prompt> make Makeproduza o executável de nome Make correspondente ao seu EP2.
meu_prompt>tar -xvf ep2.tarcrie um diretório que tenha o seu login na rede Linux como nome. Neste diretório devem estar todos os arquivos do seu EP2, inclusive o Makefile que você usou. Se você achar necessários coloque junto um arquivo 00-leia-me, onde você descreve algo que achar necessário: como limitações e bugs no seu programa