Compilação e instalação de software |
Atualmente é muito simples instalar um programa já compilado, com package managers como o pgktools, rpm, dpkg (respectivamente do Slakware, RedHat e Debian), mas o administrador de sistemas encontrará muitos programas (geralmente os mais interessantes) disponíveis somente em fonte (source code) e às vezes nem tão bem documentados assim. Entretanto, compilar um programa não é algo reservado aos gênios, quando se tem um pouco de cuidado e precaução. Tarefa mais difícil sem dúvida é a conversão de um programa projetado para outro "sabor" de Unix para o Linux. Discutiremos nesse capítulo algumas operações comumente realizadas na instalação de programas a partir dos fontes, uma habilidade que todo administrador de sistema deve ter.
Alguns conselhos iniciais:
mc
para tornar a tarefa mais simples.
ldconfig -p|less
.
cp /dev/null
install-inicio
), para depois usar o find
para encontrar os
arquivos criados ou modificados pela instalação. Melhor ainda, use um programa
como instmon
ou installwatch
para monitorar sua
instalação e ficar mais fácil de desinstalar o programa, caso voce se
arrependa depois.
Há alguns anos atrás o Linux usava exclusivamente bibliotecas de carga dinâmica DLL. Este tipo de biblioteca é mais complicada para se criar e não permite a modificação de um programa durante a sua execução, Para ganhar estas vantagens, foi criado um novo tipo de bibliotecas, ELF. Contudo, muitos programas ainda usam os DLLs, portanto voce encontrará em seu sistema bibliotecas que aparentam ser cópias, mas são realmente dois tipos diferentes. Os carregadores destes dois tipos de bibliotecas são o ld.so (para DLL) e ld-linux.so.1 (para ELF). Com o advento do Glibc-2 (no lugar de libc-5, mais usado atualmente), novo carregador poderá também ser encontrado o ld-linux.so.2. Glibc-2 tem suporte para internacionalização e threads [38] já incluidos na biblioteca.
Um programa pode ser executado em qualquer sistema Linux quando ele é estaticamente ligado (linked). O que acontece nesse caso? A biblioteca é incluida na forma binária para fazer parte do programa. Dá para se perceber que, desta forma, o programa fica muito maior do que ele precisaria ser, se a bilbioteca fosse carregada no sistema, ademais a memória ocupada pela biblioteca poderia ser compartilhada pelos vários programas que utilizam estas bibliotecas, resultando numa economia de memória e aumento na velocidade (menos tempo carregando bibliotecas). Por que mesmo assim se usam programas ligados estaticamente? Porque existem bibliotecas comerciais (notadamente o Motif), permitidas de serem entregues em binário junto com um programa gratuito, mas não separadamente, para carga dinàmica. Felizmente o Lesstif já está bem desenvolvido e substitui o Motif em 90% dos casos. |
Para sabermos quais bibliotecas são esperadas por um programa executável,
podemos usar o comando ldd <programa>
e ele listará as
bibliotecas com suas versões instaladas e, na mesma linha com um separador
"=>" a biblioteca presente que satisfaz o requisito e sua versão
corrrespondente, ou uma mensagem dizendo que ela está ausente. Veja um
exemplo:
~$ ldd `which netscape` libXt.so.6 => /usr/X11R6/lib/libXt.so.6 (0x4000c000) libSM.so.6 => /usr/X11R6/lib/libSM.so.6 (0x4004a000) libICE.so.6 => /usr/X11R6/lib/libICE.so.6 (0x40052000) libXmu.so.6 => /usr/X11R6/lib/libXmu.so.6 (0x40066000) libXpm.so.4 => /usr/X11R6/lib/libXpm.so.4 (0x40077000) libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x40083000) libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x4008d000) libdl.so.1 => /lib/libdl.so.1 (0x4011e000) libc.so.5 => /lib/libc.so.5 (0x40121000) libg++.so.27 => /usr/lib/libg++.so.27 (0x401dd000) libstdc++.so.27 => /usr/lib/libstdc++.so.27 (0x40220000) libm.so.5 => /lib/libm.so.5 (0x40252000) |
Neste exemplo, todas as bibliotecas foram encontradas e carregadas e se
encontram listadas ao lado direito. Para instalar uma biblioteca necessária
mas ausente, devemos copiá-la em um dos diretórios listados no arquivo
/etc/ld.so.conf
e em seguida executar o comando
ldconfig
. Opcionalmente, podemo editar o arquivo e colocar
outros diretórios para o ldconfig
procurar as bibliotecas, e
depois re-executá-lo. Para verificar todas as bibliotecas presentes usamos,
ldconfig -p
.
Se um programa apresenta problemas na hora de executar, nem sempre a causa são
as bibliotecas usadas. Voce poderá depurar de várias formas essa execução, mas
uma maneira simples e rápida é com o programa strace. Adicione strace no
início da linha de comando que voce faria normalmente e verá todos as chamadas
de sistema do comando executado. Outra forma mais interessante é fazendo
strace -o saida.strace <comando a executar>
e depois verifique a
saida armazenada no arquivo saida.strace
. Quando o programa
executa um fork
(cria um programa filho), o strace
só o capturará se for executado com as chaves -f
ou
-ff
.
make
No pacote .tar.gz
de um programa distribuido em fonte,
normalmente voce encontrará um arquivo de nome Makefile
. O
conteúdo desse arquivo são as regras para a partir do fonte e dos compiladores
instalados (não só compiladores, na realidade, também formatadores de texto,
scripts em shell ou outras linguagens, macro-processadores, etc) produzir os
objetos que constituirão o programa final: executáveis, man pages, outras
documentações, e até scripts para a instalação automática do programa.
O Makefile
(ou vários, dependendo do programa), é uma espécie de
"programa" em linguagem declarativa, onde colocamos do lado esquerdo o objeto
desejado e do lado direito do que ele depende, separados por ":"
,
e na linha logo abaixo, indentado, as instruções para produzir o "alvo".
Parâmetros de um make
podem ser passados na linha de comando, mas
é mais comum passá-los no próprio Makefile
ou no
environment (variáveis do shell). Quando o make
é
executado ele procura um arquivo de nome Makefile
e o interpreta.
A vantagem do make
, é que ele testa a data dos alvos contra a
data das dependências e só compila o que for mais antigo, salvando assim tempo
na fase de desenvolvimento. Ademais, ele se presta à automação da instalação
do programa.
Vejamos um exemplo de Makefile
:
comentários variáveis (macros) regras |
# # Makefile for tcl/tk extensions # this is part of slidedraw # sldlib=libsldw.so.1.0 CC=gcc CFLAGS=-O -fPIC -g SHLIB_LD_LIBS= -ljpeg SHLIB_LD=gcc SHLIB_LD_FLAGS=-shared -Wl,-E -Wl,-soname,libsldw.so.1.0 OBJS=slide.o sldInit.o sldImage.o jpeg.o sldPs.o sldShow.o sldDrawText.o ${sldlib}: $(OBJS) ${SHLIB_LD} ${SHLIB_LD_FLAGS} -o $@ $(OBJS) ${SHLIB_LD_LIBS} .c.o: ${CC} ${CFLAGS} -c $< -o $@ install: libsldw.so.1.0 cp libsldw.so.1.0 /usr/local/lib ldconfig clean: rm -f *.o *~ distclean: rm -f *.o *~ libsldw.so.1.0 |
Voce deve procurar regras com o nome install e verificar os comandos abaixo
desta regra. Os programas usualmente encontrados são o ginstall
,
install
, ou mesmo o cp
. Verifique também algum
ln
(cria link). Todos estes escrevem arquivos nos diretórios do
seu sistema.
Entre um make
e outro, voce deverá usar, de preferência
make distclean
. Podemos também verificar quais as operações que
seriam realizadas por um make sem realmente executá-las, introduzindo
make -n
. (este comando irá imprimir todos os comandos na
sequência correnta, mas não executará nenhum, servindo para verificação.)
imake
e autoconf
O imake e o autconf são programas para
automatizar a geração de Makefiles
e assim obter maior
portabilidade entre diversos sistemas operacionais. Eles tentam descobrir
aonde se encontram certos arquivos (include files) que são
necessários para a compilação do programa.
Um programa que utiliza o imake irá requerer que voce execute
xmkmf
para produzir o Makefile
resultante a partir
de um arquivo Imakefile
que foi distribuido com o fonte do
programa a ser instalado. Com o imake a configuração
dependente da máquina e sistema operacional fica no seu sistema, e não no
programa que está sendo distribuido, permitindo o progamador criar programas
que compilam e executam numa variedade de ambientes diferentes. No Linux, o
arquivo com esta configuração é o
/usr/X11/lib/X11/config/Imake.tmpl
.
A sequência de comandos usual para compilar e instalar um programa que é
distribuido com uma Imakefile
é:
~$ xmkmf ~$ make clean ~$ make depend ~$ make ~$ make install |
Como imake foi criado para distribuir os programas do
X-Windows, o diretório de instalação default (se a aplicação não forçar outro)
para os executáveis é /usr/X11/bin
. A grande maioria dos
programas que usam esse método de configuração é desenvolvida para o X11,
apesar dele poder ser usado com um programa qualquer.
O autoconf é um programa similar, mas muito mais difundido
que o imake, com objetivo similar. Além de criar o Makefile, ele cria um
arquivo para inclusão (include file
) que será usado no programa
fonte para definir dependências do hardware ou do sistema operacional que
serão referenciadas nos programas. O programa executado na hora de compilar
toma o nome de configure
.
Um procedimento típico para instalar um programa que é distribuido com autoconf é o seguinte:
./configure <chaves (switches)> make make check make install |
patch
Programas muito grandes tomam tempo de download se voce os está carregando pela internet, por exemplo. Para aliviar esse problema, o autor do programa deixa disponível arquivos com patches (remendos) dos programas. Esses patches contém a informação necessária para, a partir de uma versão anterior do programa, transformar todos os fontes de modo a transformá-lo na versão mais nova. Geralmente essas diferenças são bem menores que o novo programa completo.
Os arquivos de patch são construido a partir do programa
diff
, que compara dois arquivos gerando um texto (opcionalmente
com algumas linhas que identificam o contexto) com símbolos que indicam o que
deve ser retirado e o que deve ser adicionado para converter um arquivo em um
outro, após a edição. Veja um pequeno texto, o mesmo após a edição e o
arquivo gerado pelo diff
:
Se fizermos um estudo da história dos povos americanos, verificamos que foi o Brasil o último daqueles países a dar a liberdade aos escravos. Entretanto, a forma gradual que adotamos ensejou que não herdássemos um forte preconceito racial, como nos Estados Unidos, nem mesmo um sistema de castas que atingiu vários países hispano-americanos. As nossas razões históricas também foram outras. |
Arquivo frase1.txt
:
Se fizermos um estudo da história dos povos americanos, verificamos que foi o Brasil o último daqueles paíse a dar a liberdade aos escravos. Entretanto, a forma gradual que adotamos ensejou que não herdássemos um forte preconceito (discutível) racial, como nos Estados Unidos, nem mesmo um sistema de castas que atingiu vários países hispano-americanos. O problema norte-americano foi resolvido de forma abrupta e violenta. As nossas razões históricas também foram outras. |
Diferença gerada a partir do comando diff frase.txt frase1.txt
:
4c4 < adotamos ensejou que não herdássemos um forte preconceito --- > adotamos ensejou que não herdássemos um forte preconceito (discutível) 6,7c6,9 < castas que atingiu vários países hispano-americanos. As < nossas razões históricas também foram outras. --- > castas que atingiu vários países hispano-americanos. > O problema norte-americano foi resolvido de forma > abrupta e violenta. > As nossas razões históricas também foram outras. |
Diferença com contexto (mais seguro de que as alterações são aplicáveis à
versão corrente), resultante da execução do comando:
diff -c frase.txt frase1.txt
: (que chamamos de
patchfile
)
*** frase.txt Sat Jan 16 23:44:16 1999 --- frase1.txt Sat Jan 16 23:48:30 1999 *************** *** 1,7 **** Se fizermos um estudo da história dos povos americanos, verificamos que foi o Brasil o último daqueles paíse a dar a liberdade aos escravos. Entretanto, a forma gradual que ! adotamos ensejou que não herdássemos um forte preconceito racial, como nos Estados Unidos, nem mesmo um sistema de ! castas que atingiu vários países hispano-americanos. As ! nossas razões históricas também foram outras. --- 1,9 ---- Se fizermos um estudo da história dos povos americanos, verificamos que foi o Brasil o último daqueles paíse a dar a liberdade aos escravos. Entretanto, a forma gradual que ! adotamos ensejou que não herdássemos um forte preconceito (discutível) racial, como nos Estados Unidos, nem mesmo um sistema de ! castas que atingiu vários países hispano-americanos. ! O problema norte-americano foi resolvido de forma ! abrupta e violenta. ! As nossas razões históricas também foram outras. |
Obs: Neste exemplo, o patchfile ficou maior do que o "fonte", e não justificaria o seu uso. Na prática, programas têm pequenas (e localizadas) alterações, em relação ao tamanho total do arquivo, o que gera um patchfile muitas vezes menor que o fonte completo. |
O que o programa patch
faz é, a partir de um destes arquivos
transformar a versão frase.txt
na versão (depois da edição)
frase1.txt
. Se o diff
for usado na forma com
contexto (segunda versão), patches de vários arquivos podem ser
concatenados em um úncio arquivo e assim regenerar vários fontes (inclusive em
sub-diretórios) a partir de um só patch file.
A utilização do comando patch se faz na forma:
patch -p0 patchfile
no diretório aonde frase.txt
se encontra. A chave -p0 dá como
resultado o arquivo "consertado" com o mesmo path do original.