Construindo pacotes RPM seguindo os padrões Red Hat e Fedora (parte 1)
Nível: Introdutório
Familiaridade com compilação de programas a partir do código fonte
(configure && make && make install). Familiaridade com gerenciamento de
pacotes rpm (instalação, remoção e atualização).
O RPM foi, originalmente, desenvolvido por Ethan "E$" Cohen na Red Hat, para ser o gerenciador de pacotes (ou recursos) do Red Hat Linux. RPM> significava Resource Package Manager e depois, ficou conhecido por RPM Package Manager.
RPM hoje é utilizado em muitas distribuições Linux (como Fedora, Mandriva, SuSe e OpenSuSe) e também foi portado para outros sistemas operacionais, como AIX (à partir da versão 4) e o antigo Novell NetWare (à partir da versão 6.5 SP3).
A grande vantagem de se utilizar um gerenciador de pacotes é que o administrador do sistema não tem que preocupar-se com quais arquivos são instalados, dependências, e como removê-los do sistema sem deixar nada para trás.
RPM é um assunto que merece atenção pois é até parte dos conteúdos de estudo para se obter a certificação LPI nível 1.
Um arquivo RPM, geralmente, é nomeado da seguinte maneira:
<nome>-<versao>-<release>.<arquitetura>.rpm |
<nome> representa o nome do programa ou do pacote. O nome não pode conter espaços em branco.
<versao> representa a versão do programa empacotado. Não pode conter caracter "-".
<release> pode ser considerada a versão do pacote. A release pode conter apenas números inteiros. Quando há a necessidade de re-empacotar um programa sem atualizar sua versão, a release é que precisa ser incrementada.
<arquitetura> representa a arquitetura do pacote. Diz se o pacote foi construído para i386, x86_64, s390, ppc, entre outras.
Como, por exemplo:
hello-2.6-2.fc15.i686.rpm hello-2.6-2.fc15.src.rpm |
Onde:
hello é o nome
2.6 é a versão
2 é a release
i686 é a arquitetura
RPMs com a extensão noarch.rpm se referem a pacotes que não dependem de
uma arquitetura específica. Como por exemplo:
wxGlade-0.6.3tip20100625-3.fc15.noarch.rpm |
O pacote RPM é um binário dividido em 4 seções:
- Identificação do arquivo como sendo RPM e alguns cabeçalhos antigos;
- Assinatura, que pode ser utilizada para garantir integridade a autenticidade;
- Cabeçalhos contendo nome do pacote, versão, arquitetura, lista de arquivos, etc;
- Arquivos propriamente ditos, geralmente no formato cpio, comprimidos com gzip. Nas versões mais recentes podem ser usadas as compressões bzip2, lzma e xz.
O arquivo spec é como uma receita para a construção de um pacote RPM. Podemos comparar o spec com um Makefile do pacote.
Os arquivos spec seguem a nomenclatura <nome>.spec. Por exemplo, hello.spec.
Como exemplo, usaremos o spec do pacote hello.
O primeiro bloco do spec contém as definições básicas do pacote: nome, versão, release, sumário, grupo, licença, URL do projeto, arquivo de código fonte e o diretório de compilação.
Name: hello
Version: 2.6
Release: 2%{?dist}
Summary: Prints a Familiar, Friendly Greeting
Group: Development/Tools
# Parts of the documentation are under GFDL, BSD, and Public Domain
# *All* code is GPLv3+.
License: GPLv3+ and GFDL and BSD and Public Domain
URL: http://www.gnu.org/software/hello/
Source0: http://ftp.gnu.org/gnu/hello/hello-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
Logo abaixo, estão listadas as dependências de compilação
(BuildRequires) e as dependências de execução (Requires).
BuildRequires: gettext Requires(post): info Requires(preun): info |
É preciso uma descrição para o pacote, que está na seção %description.
Esta seção pode ter inúmeras linhas. Apenas o Summary deve conter apenas uma linha de descrição.
%description Hello prints a friendly greeting. It also serves as a sample GNU package, showing practices that may be useful for GNU projects. |
Na seções %prep e %setup são feitas a descompactação do código fonte
(Source0) e aplicação de patches (se necessário).
%prep %setup -q |
A seção %build é o lugar onde devemos colocar todos os comandos necessários para compilar e gerar os binários do programa que se está
empacotando. Nela, é possível fazer uso da macro %configure (que executa
um ./configure no diretório fonte).
%build
%configure
make %{?_smp_mflags}
|
Logo mais na seção %install estão os comandos necessários para se fazer a instalação dos binários no diretório $RPM_BUILD_ROOT (simula o diretório raiz "/" onde os arquivos devem ser instalados).
%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT
rm -f $RPM_BUILD_ROOT%{_infodir}/dir
%find_lang hello
|
Na seção %check costuma-se executar os testes de unidade e outras coisas relevantes ao programa recém-compilado.
%check cd tests make check-TESTS |
A seção %clean remove os arquivos resultantes da compilação do pacote,para que, depois que o pacote seja criado, seu sistema de arquivos continue limpo.
%clean rm -rf $RPM_BUILD_ROOT |
Na seção %post vão os comandos necessários para serem executados depois que o pacote RPM for instalado no sistema. É comum que sejam adicionados comandos para inicializar um serviço do sistema (service e chkconfig).
%post
/sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || :
|
A seção %preun contém as ações que são executadas antes do pacote ser removido do sistema. Costuma-se remover serviços da inicialização do sistema (chkconfig).
%preun
if [ $1 = 0 ] ; then
/sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || :
fi
|
Umas das seções importantes do spec, é a seção %files, que contém a
lista de arquivos e suas permissões. É comum, durante a criação do spec,esquecer de adicionar o caminho dos arquivos nesta seção. Com as macros %defattr e %doc são definidas as permissões padrões e os arquivos referentes a documentação.
%files -f hello.lang
%defattr(-,root,root,-)
%doc COPYING
%{_mandir}/man1/hello.1*
%{_bindir}/hello
%{_infodir}/hello.info*
|
Geralmente, a seção %changelog fica por último mas não é menos importante. Nela estão os changelogs e é onde os empacotadores
dizem porque estão re-empacotando ou lançando uma versão nova do pacote.Atente-se para o formato correto de data, parecido com o seguinte:
%changelog * Wed Feb 09 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.6-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild |
Para visualizar o arquivo hello.spec na íntegra, consulte o Anexo 1 – hello.spec.
Uma macro RPM pode ser considerada uma variável que será expandida durante a construção do pacote.
Macros podem armazenar qualquer tipo de dados (strings, números e até a saída de comandos).
Elas podem ser definidas pelo usuário (dentro do arquivo spec), pelo sistema (nos arquivos de configuração do rpm), ou em tempo de compilação (passadas como parâmetros para o rpmbuild).
Vejamos algumas das macros básicas:
Macro Valor Significado
%_specdir ~/rpmbuild/SPECS Diretório dos arquivos spec
%_sourcedir ~/rpmbuild/SOURCES Diretório dos tarballs
%_builddir ~/rpmbuild/BUILD Diretório de compilação
%_buildrootdir ~/rpmbuild/BUILDROOT
Diretório aonde os arquivos são instalados durante o %install
%_rpmdir ~/rpmbuild/RPMS Diretório dos RPMs binários
%_srcrpmdir ~/rpmbuild/SRPMS Diretório dos RPMs fonte
|
Para visualizar todas as macros e valores que o rpmbuild está usando, execute:
# rpmbuild --showrc |
Antes de iniciar a construção de um pacote, é necessário ter as ferramentas corretas instaladas e prontas para usar.
É preciso instalar autotools, gcc e outras bibliotecas de desenvolvimento, juntamente com alguns scripts que auxiliam no empacotamento. Para isso, execute:
# yum groupinstall "Development Tools" # yum install rpmdevtools |
Depois de ter as ferramentas instaladas, criamos os diretórios, necessários no $HOME do usuário, executando:
$ rpmdev-setuptree |
O shell script acima, criará a seguinte estrutura de diretórios:
$HOME/rpmbuild $HOME/rpmbuild/BUILDROOT $HOME/rpmbuild/BUILD $HOME/rpmbuild/SOURCES $HOME/rpmbuild/SPECS $HOME/rpmbuild/RPMS $HOME/rpmbuild/SRPMS |
Se você quiser, pode criar esta estrutura em qualquer outro diretório, como por exemplo, no /tmp.
Tendo as ferramentas instaladas e o ambiente configurado, estamos prontos para construir nosso primeiro pacote.
Normalmente, o tarball contendo o código fonte do programa deverá ficar em ~/rpmbuild/SOURCES. E o spec deverá ficar em ~/rpmbuild/SPECS. Algo parecido com isso:
# ls -l $HOME/rpmbuild/{SOURCES,SPECS}
/root/rpmbuild/SOURCES:
total 584
-rw-rw-r--. 1 root root 594257 Jan 13 2011 hello-2.6.tar.gz
/root/rpmbuild/SPECS:
total 4
-rw-r--r--. 1 root root 1984 Feb 9 2011 hello.spec
|
É possível fazer download do código do hello no seguinte endereço: http://ftp.gnu.org/gnu/hello/hello-2.6.tar.gz.
Agora que temos o spec já preparado e o tarball dos fontes, usaremos o rpmbuild para construir nosso pacote.
Costuma-se executar o rpmbuild estando no diretório ~/rpmbuild/SPECS, portanto:
# cd $HOME/rpmbuild/SPECS # rpmbuild hello.spec -ba |
Você verá o rpmbuild executando todos os passos das seções %prep,
%setup, %build, %install, %clean. Se tudo ocorrer como o esperado, no final da compilação, serão gerados os pacotes RPM:
Wrote: /root/rpmbuild/SRPMS/hello-2.6-2.fc15.src.rpm Wrote: /root/rpmbuild/RPMS/i686/hello-2.6-2.fc15.i686.rpm Wrote: /root/rpmbuild/RPMS/i686/hello-debuginfo-2.6-2.fc15.i686.rpm |
Pronto! Agora você pode instalar o pacote hello que acabou de ser gerado. Simples, não?
No próximo artigo da série, veremos com aplicar patches e atualizaremos o pacote hello para a versão 2.7. Também utilizaremos o comando rpmlint para verificar erros que dificilmente são percebidos a olho nu. Não perca!
Name: hello
Version: 2.6
Release: 2%{?dist}
Summary: Prints a Familiar, Friendly Greeting
Group: Development/Tools
# Parts of the documentation are under GFDL, BSD, and Public Domain
# *All* code is GPLv3+.
License: GPLv3+ and GFDL and BSD and Public Domain
URL: http://www.gnu.org/software/hello/
Source0: http://ftp.gnu.org/gnu/hello/hello-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: gettext
Requires(post): info
Requires(preun): info
%description
Hello prints a friendly greeting. It also serves as a sample GNU
package, showing practices that may be useful for GNU projects.
%prep
%setup -q
%build
%configure
make %{?_smp_mflags}
%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT
rm -f $RPM_BUILD_ROOT%{_infodir}/dir
%find_lang hello
%check
cd tests
make check-TESTS
%clean
rm -rf $RPM_BUILD_ROOT
%post
/sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || :
%preun
if [ $1 = 0 ] ; then
/sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || :
fi
%files -f hello.lang
%defattr(-,root,root,-)
%doc COPYING
%{_mandir}/man1/hello.1*
%{_bindir}/hello
%{_infodir}/hello.info*
%changelog
* Wed Feb 09 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.6-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
|
http://en.wikipedia.org/wiki/RPM_Package_Manager
http://rpm.org/max-rpm-snapshot/s1-rpm-inside-macros.html
http://fedoraproject.org/wiki/Packaging:Guidelines
http://fedoraproject.org/wiki/How_to_create_an_RPM_package
http://fedoraproject.org/wiki/Packaging:ScriptletSnippets