next up previous contents
Next: Carregamento e Ligação Dinâmicos Up: Ligadores Previous: Ligadores   Sumário


Bibliotecas

Quando um programador usa em seus programas funções oferecidas pelo sistema, estas funções estão usualmente já montadas, disponibilizadas em formato objeto. Entretanto, ao invés de ter um arquivo objeto para cada função (o que tornaria o número de objetos excessivo) estas funções estão usualmente organizadas na forma de arquivos do tipo biblioteca.

Bibliotecas são arquivos que contêm um conjunto de módulos objetos, normalmente agrupados de acordo com sua funcionalidade. A origem do termo ``biblioteca'' vêm da época dos computadores de grande porte, para os quais as rotinas auxiliares eram mantidas em fitas ou cartões armazenados em salas com prateleiras.

Nesta seção, bibliotecas estáticas serão descritas -- bibliotecas dinâmicas serão vistas na Seção 4.7. Uma biblioteca estática fornece código objeto que deve ser integrado ao módulo executável antes do momento de execução, durante o processo de ligação.

Em geral, o sistema operacional apresenta utilitários para manipular arquivos tipo biblioteca. Em Unix (Linux), o utilitário ar é utilizado para criar, manter e extrair módulos de arquivos de bibliotecas estáticas. Por exemplo, se um módulo objeto arqmat.o tiver sido criado com a linha de comando

 > gcc -c arqmat.c
esse módulo pode ser incluído em uma biblioteca libmy.a, criada pelo usuário, com a linha de comando
 > ar -r libmy.a arqmat.o
A chave -r indica que ocorrerá uma troca (replacement) do módulo, caso houvesse uma versão anterior já armazenada na biblioteca; caso contrário, o módulo é acrescentado à biblioteca.

Se essa for a primeira operação com essa biblioteca, ela será criada pelo programa ar. Nesse caso, uma solicitação de listar o conteúdo (com a opção -t) mostrará que apenas esse módulo está presente:

 > ar -t libmy.a
 arqmat.o

Novos módulos podem ser similarmente incluídos:

 > ar -r libmy.a convexp.o
 > ar -t libmy.a
 arqmat.o
 convexp.o

A estrutura típica de um arquivo do tipo biblioteca nesse tipo de sistema operacional é composta por uma identificação do tipo de arquivo (em geral, a string !<arch>\n), um diretório de membros do arquivo e por uma seção com o conteúdo de cada membro do arquivo.

O diretório de membros do arquivo é composto por uma série de cabeçalhos de membro, sendo que cada cabeçalho de membro contém:

A estrutura de um arquivo do tipo biblioteca pode ser usado para agregar qualquer tipo de conteúdo, mas usualmente apenas módulos objetos são agrupados em bibliotecas.

No processo de ligação, além dos módulos objetos gerados a partir dos arquivos fontes originais, o programador pode especificar arquivos do tipo biblioteca. Inicialmente, o ligador irá resolver as referências que puderem ser estabelecidas a partir dos módulos objetos fornecidos. Se, ao final dessa etapa, ainda houver referências não-resolvidas, o ligador procura pela definição dos símbolos dentro das bibliotecas. Ao encontrar o cabeçalho do módulo especificado, o ligador obtém dali toda a informação necessária para extrair apenas o módulo desejado e assim integrá-lo ao módulo de carga executável.

Arquivos de biblioteca são extensamente utilizados, embora nem sempre de forma explícita. Por exemplo, na implementação GNU para o compilador C a biblioteca libc.a, armazenada no diretório /usr/lib, contém as funções da biblioteca padrão da linguagem. Como essas funções são amplamente utilizadas (tal como a rotina printf), o programador não precisa explicitar para o ligador que essa biblioteca deverá ser utilizada para a resolução de símbolos -- o próprio compilador gcc irá integrar essa biblioteca ao processo de ligação.

Quando uma outra biblioteca tiver de ser utilizada, contendo por exemplo rotinas matemáticas (em Unix, na biblioteca libm.a) ou rotinas associadas a outros pacotes ou aplicativos (bancos de dados, interfaces gráficas), é preciso passar essa informação ao ligador. No caso do ligador ld, há duas chaves relacionadas ao fornecimento dessa informação -- essas chaves podem ser especificadas para o compilador, que as repassa ao programa ligador. A chave -lxxx indica que a biblioteca cujo nome é libxxx.a deve ser incorporada ao processo de resolução de referências.

Por exemplo, considere o seguinte programa que incorpora uma rotina matemática -- no caso, cos para o cálculo do cosseno de um valor real especificado na linha de comando:
\begin{listing}{1}
// calccos.c: calcula o cosseno do valor especificado
...

Se o correspondente arquivo de biblioteca com rotinas matemáticas, que contém o código objeto para a rotina cos, não for especificado, um erro de ligação será gerado:

 > gcc calccos.c
 /tmp/ccKOiW4b.o: In function `main':
 /tmp/ccKOiW4b.o(.text+0x54): undefined reference to `cos'
 collect2: ld returned 1 exit status

Para incluir a ligação das rotinas matemáticas, o código deve ser compilado e ligado com a inclusão da chave -lm, como em

  > gcc calccos.c -lm

A outra chave associada à especificação de bibliotecas é -L, que especifica um diretório onde arquivos do tipo biblioteca estarão armazenados, caso seja necessário fazer essa busca em um diretório distinto dos usados por padrão pelo sistema operacional -- tipicamente, os diretórios /lib, /usr/lib e /usr/local/lib.


next up previous contents
Next: Carregamento e Ligação Dinâmicos Up: Ligadores Previous: Ligadores   Sumário
Ivan L. M. Ricarte 2003-02-14