Desmistificando a compilação de software (repost)

Há muito tempo atrás eu havia postado este artigo, como ele havia se perdido, acabei repostando:

Resolvi escrever este artigo hoje, pois já reparei que várias pessoas desistem de utilizar o linux ou trocam de distribuição pois não sabem como compilar um programa, este artigo trata (de forma resumida) como compilar um programa corretamente.

-Quando instalamos um pacote RPM , DPKG ou um outro como TGZ (não confundam com tar.gz que são arquivos compactados com tar), o que estamos instalando é o programa já compilado e “empacotado” em um arquivo compactado com informações sobre o conteúdo deste pacote que são utilizados pelo gerenciador de pacotes (RPM, DPKG, etc..) para facilitar o gerenciamento destes softwares em nossa máquina.
No GCC existem várias opções que podem ser ativadas e configuradas para otimizar a compilação e a execução de softwares como, por exemplo, o uso ou não de instruções extendidas (MMX,MMX2, SSE, SSE2, 3DNow!, etc). Acontece que, quando utilizamos um pacote binário já pronto, estas opções normalmete são suprimidas, pois os pacotes que são liberados por uma distribuição linux devem rodar no maior número de máquinas (e arquiteturas diferentes) possível. Logo, compilar um software em nosso computador, pode ser bem útil quando se trata de softwares que usamos com frequência, pois estes softwares tenderão a ser um pouco (se formos pessimistas) mais rápidos do que o pacote que vem junto com alguma distribuição.
O Gentoo Linux, por exemplo, é um linux que se baseia nesta premissa. Nele, se você quiser, você pode compilar TODO o seu sistema linux (o ganho de desempenho é gritante) com uma ferramenta chamada portage, que facilita todo o procsso de compilação de um software. Mas o que vamos tratar aqui é da compilação pura e simples, abordando alguns aspectos úteis da compilação.
Para ilustrar melhor nosso artigo, vamos supor que o software que nós vamos instalar é o FOOSOFT. Abaixo segue a lista de passos iniciais:

Ir até o site do fabricante e baixar o arquivo com o código-fonte do software, normalmente os arquivos de código fonte possuem 2 extensões: .tar.gz ou .tar.bz2
Logo após, devemos descompactar o arquivo:

Se for .tar.gz (arquivo tar compactado com gzip) podemos usar o seguinte comando:
tar -xzvf foosoft-1.0.tar.gz (troque o foosoft-1.0.tar.gz pelo nome do arquivo que você baixou)

Se for .tar.bz2 (arquivo tar compactado com gzip) podemos usar o seguinte comando:
tar -xjvf foosoft-1.0.tar.bz2 (troque o foosoft-1.0.tar.bz2 pelo nome do arquivo que você baixou)

Primeira lição: com o tar, utilizamos a opção “z” para usar a descompactação com gzip e a opção “j” para a descompactação com bzip2

A opção “v” do tar é para ele mostrar na tela os arquivos e diretórios que ele ele está descompactando, normalmente os softwares bem feitos, quando descompactados, são criados em um diretório do tipo nome_do_software-versão, no nosso exemplo deveríamos ficar com um diretório chamado foosoft-1.0

Vamos para dentro do diretório que acabamos de criar:

cd foosoft-1.0 (troque o foosoft-1.0 pelo nome de seu diretório)

Dentro deste diretório está o arquivo que é o “bicho-papão” das compilações: o “configure“. O configure é um arquivo que prepara o seu software para ser instalado em sua máquina: define onde os arquivos binários, de configuração e os arquivos temporários serão colocados, define algumas bibliotecas que podem ser usadas junto com o software e algumas opções de compilação. a primeira coisa que temos que fazer é ver quais as opções podemos usar com o configure: ./configure --help (o ./ é necessário pois o configure está em um diretório que o linux não sabe que há um arquivo que podemos executar, logo o ./ diz que é para executar o configure do diretório corrente). Abaixo um exemplo da saída do configure da aalib:

root@omega:~/aalib-1.4.0# ./configure --help
Usage: configure [options] [host]
Options: [defaults in brackets after descriptions]
Configuration:
--cache-file=FILE cache test results in FILE
--help print this message
--no-create do not create output files
--quiet, --silent do not print `checking...' messages
--version print the version of autoconf that created configure
Directory and file names:
--prefix=PREFIX install architecture-independent files in PREFIX [/usr/local]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [same as prefix]
--bindir=DIR user executables in DIR [EPREFIX/bin]
--sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
--libexecdir=DIR program executables in DIR [EPREFIX/libexec]
--datadir=DIR read-only architecture-independent data in DIR [PREFIX/share]
--sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data in DIR [PREFIX/com]
--localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
--libdir=DIR object code libraries in DIR [EPREFIX/lib]
--includedir=DIR C header files in DIR [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
--infodir=DIR info documentation in DIR [PREFIX/info]
--mandir=DIR man documentation in DIR [PREFIX/man]
--srcdir=DIR find the sources in DIR [configure dir or ..]
--program-prefix=PREFIX prepend PREFIX to installed program names
--program-suffix=SUFFIX append SUFFIX to installed program names
--program-transform-name=PROGRAM run sed PROGRAM on installed program names
Host type:
--build=BUILD configure for building on BUILD [BUILD=HOST]
--host=HOST configure for HOST [guessed]
--target=TARGET configure for TARGET [TARGET=HOST]
Features and packages:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--x-includes=DIR X include files are in DIR
--x-libraries=DIR X library files are in DIR
--enable and --with options recognized:
--enable-shared[=PKGS] build shared libraries [default=yes]
--enable-static[=PKGS] build static libraries [default=yes]
--enable-fast-install[=PKGS] optimize for fast installation [default=yes]
--with-gnu-ld assume the C compiler uses GNU ld [default=no]
--disable-libtool-lock avoid locking (might break parallel builds)
--with-x11-driver=no Used to disable x11 driver
--with-slang-driver=no Used to disable slang driver
--with-curses-driver=no/yes Used to disable/force curses driver
--with-gpm-mouse=base-dir Specifies the base gpm directory
--with-x use the X Window System
--with-sunos-curses Used to force SunOS 4.x curses
--with-osf1-curses Used to force OSF/1 curses
--with-vcurses[=incdir] Used to force SysV curses
--with-ncurses[=base-dir] Compile with ncurses/locate base dir

Não vou falar de todas as opções, pois algumas são específicas, mas vou falar das opções que utilizamos em 99% das compilações (sim, você vai ter que ler a saída de todos os “configures” que você utilizar para ver o que é bom e o que é ruim para você):

A opção mais importante (na minha opinião) é a opção “--prefix“: Ela diz onde vai ser instalado o seu software. Por exemplo, se utilizarmos a opção ./configure --prefix=/tmp/software, será criado um diretório chamado /tmp/software e todo o software será instalado lá dentro. Isto não é muito bom na maioria das vezes, pois normalmente queremos instalar um software que se integre com o nosso sistema operacional e, desta forma, toda árvore de diretórios será criada em um diretório não padrão (/tmp/software). esta opção é bacana para descobrirmos quais arquivos serão instalados pelo software e para testarmos se o software funciona antes de instalarmos em nosso sistema. O prefixo padrão para softwares no linux é “/usr” ou “/usr/local“.
Se vocês reparem nas opções logo abaixo do prefix, vão notar que o padrão delas (notaram os colchetes? isso são as opções padrão) é EPREFIX/XXX, estas opções são para setar diretórios não padrão para cada parte do software (arquivos temporários, documentações, etc). A maioria delas não precisa ser mexida, com exceção do --localstatedir (que seria pelo padrão /usr/var e precisa ser /var) e o --sysconfdir (que seria pelo padrão /usr/etc é tem que ser em /etc).
Em 90% das compilações você terá que usar:

./configure --prefix=/usr --localstatedir=/var --sysconfdir=/etc

O erro mais possível que pode acontecer neste passo é você não ter alguma biblioteca que seja um pré-requisito para o programa instalada, neste caso você pode escolher compilar a biblioteca antes de compilar o seu programa ou instalar a biblioteca que vem junto com o seu sistema operacional (no Fedora e no conectiva as bibliotecas normalmente são os pacotesxxxx-devel, em outras distribuições é o próprio nome da biblioteca). Por exemplo, se o erro foi que a biblioteca libao está “missing” (faltando), você pode compilar e instalar a libao ou instalar o pacote libao-devel para prosseguir com a compilação.

Depois de passar pelo configure (sem erros), a coisa fica bem mais fácil: é só executar o comando make para compilar (se você tiver uma máquina rápida, você pode usar make -j2 para compilar mais rápido)
Quando acabar, é só instalar o seu software: make install
A maioria dos softwares pode ser desinstalado utilizando-se o comando make uninstall de dentro do diretório da compilação.

Deixe um comentário