Idioma: 日本語 | Español | Français | Português | 中文 | English
Anterior | Próximo | Índice | Original em inglês (gnu.org)

11 Usar o make para atualizar arquivos de arquivo (archive)

Um arquivo de arquivo (archive) é um arquivo que reúne e armazena subarquivos nomeados chamados membros. Os arquivos de arquivo são gerenciados pelo programa ar e seu uso principal é como bibliotecas de sub-rotinas para a ligação (linking).

11.1 Membros de arquivo como alvos

Cada membro individual dentro de um arquivo de arquivo pode ser usado como alvo ou pré-requisito (prerequisite) do make. Um membro chamado member, contido no arquivo de arquivo archive, é especificado da seguinte forma:

archive(member)

Esta forma de escrita só pode ser usada em alvos e pré-requisitos, não em receitas (recipe)! Isso porque a maioria dos programas que você usaria numa receita não suporta essa sintaxe e não consegue atuar diretamente sobre os membros de arquivo. Apenas o ar e outros programas projetados especificamente para operar sobre arquivos de arquivo conseguem fazê-lo. Portanto, uma receita válida para atualizar um alvo que é membro de arquivo provavelmente usará o ar. Por exemplo, a regra a seguir significa: copiar o arquivo hack.o e criar o membro hack.o dentro do arquivo de arquivo foolib:

foolib(hack.o) : hack.o
        ar cr foolib hack.o

Na verdade, quase todos os alvos que são membros de arquivo são atualizados exatamente desta maneira, por isso existe uma regra implícita que faz isso automaticamente para você. [Importante] Se o arquivo de arquivo ainda não existir, é necessário acrescentar o sinalizador ‘c’ ao ar.

Para especificar vários membros do mesmo arquivo de arquivo, você pode escrever todos os nomes dos membros juntos entre os parênteses. Por exemplo, se você escrever assim:

foolib(hack.o kludge.o)

isso tem o mesmo significado que escrever desta forma:

foolib(hack.o) foolib(kludge.o)

Você também pode usar curingas no estilo do shell na referência a um membro de arquivo. Consulte Usar caracteres curinga em nomes de arquivos. Por exemplo, ‘foolib(*.o)’ expande-se para todos os membros existentes do arquivo de arquivo foolib cujos nomes terminam em ‘.o’; por exemplo, ficaria algo como ‘foolib(hack.o) foolib(kludge.o)’.

11.2 Regra implícita para alvos que são membros de arquivo

Lembre-se de que um alvo com a forma a(m) representa o membro chamado m dentro do arquivo de arquivo a.

Quando o make procura uma regra implícita para um alvo desse tipo, como recurso especial ele considera não só as regras que correspondem ao alvo real a(m), mas também as regras implícitas que correspondem a (m).

Graças a isso, uma regra especial cujo alvo é (%) corresponde. Essa regra atualiza o alvo a(m) copiando o arquivo m para dentro do arquivo de arquivo. Por exemplo, ela atualiza o alvo membro de arquivo foo.a(bar.o) copiando o arquivo bar.o para dentro do arquivo de arquivo foo.a como um membro chamado bar.o.

Quando essa regra se encadeia com outras, ela se torna muito poderosa. Assim, havendo um arquivo chamado bar.c, basta digitar ‘make "foo.a(bar.o)"’ (as aspas são necessárias para impedir que ‘(’ e ‘)’ sejam interpretados de forma especial pelo shell), mesmo sem nenhum makefile, para que a seguinte receita seja executada:

cc -c bar.c -o bar.o
ar r foo.a bar.o
rm -f bar.o

Aqui o make imaginou o arquivo bar.o como um arquivo intermediário. Consulte Cadeias de regras implícitas.

Regras implícitas como esta são escritas usando a variável automática ‘$%’. Consulte Variáveis automáticas.

O nome de um membro de arquivo dentro de um arquivo de arquivo não pode conter um nome de diretório, mas às vezes é útil, no makefile, fingir que pode. Se você escrever o alvo membro de arquivo foo.a(dir/file.o), o make realiza a atualização automática com a seguinte receita:

ar r foo.a dir/file.o

isso tem o efeito de copiar o arquivo dir/file.o para um membro chamado file.o. Em relação a esse tipo de uso, as variáveis automáticas %D e %F podem ser úteis.

11.2.1 Atualizar o diretório de símbolos do arquivo de arquivo

Um arquivo de arquivo usado como biblioteca normalmente contém um membro especial chamado __.SYMDEF. Ele mantém um catálogo (diretório) dos nomes de símbolos externos definidos por todos os demais membros. Depois de atualizar qualquer outro membro, você precisa atualizar também o __.SYMDEF, para que essa alteração seja corretamente refletida nele. Isso é feito executando o programa ranlib:

ranlib archivefile

Normalmente, você coloca esse comando na regra do arquivo de arquivo e torna todos os membros do arquivo de arquivo pré-requisitos dessa regra. Por exemplo, escreve-se assim:

libfoo.a: libfoo.a(x.o y.o …)
        ranlib libfoo.a

Com isso, os membros de arquivo x.o, y.o etc. são atualizados e, em seguida, a execução do ranlib atualiza o membro do diretório de símbolos __.SYMDEF. As regras para atualizar os membros não estão mostradas aqui. Muito provavelmente você pode omiti-las e deixar a cargo da regra implícita que copia arquivos para o arquivo de arquivo, descrita na seção anterior.

Observe que isso não é necessário ao usar o programa ar do GNU, pois o ar do GNU atualiza o membro __.SYMDEF automaticamente.

11.3 Perigos ao usar arquivos de arquivo

As regras embutidas para atualizar arquivos de arquivo não combinam bem com builds paralelos. Essas regras (exigidas pelo padrão POSIX) adicionam cada arquivo objeto ao arquivo de arquivo à medida que ele é compilado. Quando o build paralelo está habilitado, isso faz com que vários comandos ar tentem atualizar o mesmo arquivo de arquivo ao mesmo tempo, o que não é suportado.

Se você quiser usar builds paralelos com arquivos de arquivo, pode sobrepor (override) as regras padrão adicionando as seguintes linhas ao seu makefile:

(%) : % ;
%.a : ; $(AR) $(ARFLAGS) $@ $?

A primeira linha altera a regra que atualiza cada objeto dentro do arquivo de arquivo para que ela não faça nada. A segunda linha altera a regra padrão que constrói o arquivo de arquivo para que ela atualize, num único comando, todos os objetos desatualizados ($?).

É claro que os pré-requisitos da biblioteca ainda precisam ser declarados usando a sintaxe de arquivo de arquivo:

libfoo.a: libfoo.a(x.o y.o …)

Se você quiser escrever uma regra explícita, pode escrever assim:

libfoo.a: libfoo.a(x.o y.o …)
        $(AR) $(ARFLAGS) $@ $?

11.4 Regras de sufixo para arquivos de arquivo

Você também pode escrever um tipo especial de regra de sufixo para lidar com arquivos de arquivo. Para uma explicação completa das regras de sufixo, consulte Regras de sufixo à moda antiga. As regras de sufixo para arquivos de arquivo estão obsoletas no GNU make, porque as regras de padrão voltadas a arquivos de arquivo são um mecanismo mais geral (consulte Regra implícita para alvos que são membros de arquivo). Ainda assim, elas foram mantidas por compatibilidade com outros makes.

Para escrever uma regra de sufixo para arquivos de arquivo, basta escrever uma regra de sufixo usando ‘.a’ (um sufixo comumente usado para arquivos de arquivo) como sufixo do alvo. Por exemplo, a regra de sufixo à moda antiga que atualiza uma biblioteca de arquivo a partir de arquivos fonte em C é a seguinte:

.c.a:
        $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
        $(AR) r $@ $*.o
        $(RM) $*.o

Isso funciona exatamente como se você tivesse escrito a seguinte regra de padrão:

(%.o): %.c
        $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
        $(AR) r $@ $*.o
        $(RM) $*.o

De fato, é exatamente isso que o make faz quando encontra uma regra de sufixo que tem ‘.a’ como sufixo do alvo. Toda regra de sufixo duplo com a forma ‘.x.a’ é convertida em uma regra de padrão cujo padrão de alvo é ‘(%.o)’ e cujo padrão de pré-requisito é ‘%.x’.

Como você talvez queira usar ‘.a’ como sufixo de outro tipo de arquivo, o make também converte as regras de sufixo para arquivos de arquivo em regras de padrão da maneira usual (consulte Regras de sufixo à moda antiga). Assim, a regra de sufixo duplo ‘.x.a’ gera duas regras de padrão: ‘(%.o): %.x’ e ‘%.a: %.x’.


Anterior | Próximo | Índice | Original em inglês (gnu.org)