Tutorial Autopackage GNOME Launch Box
Construindo o pacote
Nós preparamos o software: o fizemos relocável, auditamos suas dependências, relaxamos uma problemática e agora nós podemos fazer o autopackage. Esta parte é a mais fácil.
Como a maioria dos sistemas de pacote, autopackage utiliza um specfile
para descrever como fazer o resultado final. Para criar um, faça um diretório
chamado "autopackage" na árvore do fonte e gere um specfile "template" (modelo)
com o comando makeinstaller --mkspec >default.apspec.in.
É um "template" do autoconf: o campo @VERSION@ será expandido do script de
configuração para especificar a versão do software.
$ mkdir autopackage $ makeinstaller --mkspec >autopackage/default.apspec.in (agora modifique configure.ac) $ ./autogen.sh
Ok, vamos customizar nosso specfile. No topo está a seção [Meta]. Esta seção contém alguns "metadata" (informações) sobre o pacote.
[Meta]
[Meta] RootName: @imendio.com/gnome-launch-box:$SOFTWAREVERSION DisplayName: Launch Box ShortName: gnome-launch-box Maintainer: Richard HultPackager: Mike Hearn Summary: Launch Box is a fast way to activate programs, contacts and bookmarks URL: http://developer.imendio.com/wiki/GNOME_Launch_Box License: GNU General Public License, Version 2 SoftwareVersion: @VERSION@ PackageVersion: 1 AutopackageTarget: 1.0 # InterfaceVersion: 0.0
Alguns dos campos devem ser auto explicativos. Alguns não são, então os explicaremos.
- RootName
-
Um noem raiz versionado é um idenficador único para seu pacote. Autopackage utiliza nomes riaz para nomear pacotes sem requerer um repositório central. O nome raiz consiste de:
- um símbolo @, seguido de um nome de domínio que é pertencente a quem mantém o software sendo empacotado. Isto é utilizado com um "namespace", para que empacotadores que tenham o mesmo nome de software não entrem em conflito entre si.
- Deve ter ao menos uma barra (/) e não deve ter terminar em barra.
- O nome do software, seguindo após a última barra.
Aqui estão alguns exemplos:
- @gaim.sourceforge.net/gaim:1.4 - correto
- @www.lilypond.org/lilypond:1.0 - incorreto devido ao prefixo www
- @http://www.lilypond.org/ - incorreto, nomes raiz não são URLs então não devem ter um identificador de protocolo, também está faltando a parte da versão (depois dos dois pontos)
- @lilypond.org/index.html:2.4 - incorreto, nomes raiz não são URLs então não devem apontar para páginas da web
- @lilypond.org - incorreto, você tem que ter ao menos uma barra, seguindo um nome, e deve terminar em:VERSION
- @coolsite.net/projects/project cool:0.99 - incorreto, espaços e outras letras "estranhas" não são permitidas
- @mozilla.org/firefox:deerpark - incorreto, versão do software deve estar em uma forma que o autopackage possa comparar. O "parser" é bastante flexível, mas codinomes não vão funcionar.
Normalmente, selecionar um nome raiz é fácil. Se não você é quem faz a manutenção do que estiver empacotando, tenha certeza que os desenvolvedores saibam que você produziu um pacote e qual nome raiz foi alocado. Se você acha que alguém produziu um autopackage antes, verifique com quem mantém o software atualmente para descobrir o nome raiz que foi utilizado.
- AutopackageTarget
-
AutopackageTarget identifica a versão do autopackage para
qual você está escrevendo. Este mecanismo de versão permite a você
escolher como e quando novas funcionalidades potencialmente incompatíveis
são feitas em seu pacote. Este é um valor na forma X.Y, aonde X e Y são
inteiros. Em outras palavras, você não pode requisitar um "patchlevel"
(versão) mínimo do "runtime" (ambiente de execução) do autopackage,
somente um novo lançamento nas séries 1.x (ex, 1.2, 1.4, 1.6).
Se um usuário possui um autopackage 1.o e instalar um pacote que requer
1.2 então ele será atualizado. Se você não utiliza as funcionalidades novas,
o usuário não terá que esperar enquanto o "runtime" é atualizado.
Geralmente, você deve adotar o padrão aqui. Quando uma nova versão importante do autopackage for lançada, será acompanhada por um pequeno documento de migração. Isto irá cobrir quaisquer questões que você precise estar alerta, como maneiras de melhorar seu specfile. Algumas vezes novas funcionalidades serão livres - a mudança para compressão LZMA no autopackage 1.2 é um exemplo disso. Outras vezes, você precisará modificar seu pacote para tirar vantagens das funcionalidades.
- InterfaceVersion
-
A interface version identifica qual interface este pacote exporta,
se for o caso. Uma "interface" neste contexto é qualquer coisa que outro
pacote vá necessitar. Aplicações geralmente não expõem nenhuma interface,
a não ser que elas possuam um sistema de plugin. Bibliotecas, por outro lado,
geralmente o fazem. Versões de interface são abordadas em mais detalhes no
guia dos empacotadores, é suficiente dizer que você precisa decidir como
alocar versões de interface baseado no histórico de versões da API de
sua biblioteca/plugin. Se não é você que mantém, coordene-se com quem o faz
para garantir que este valor faça sentido.
Neste caso, Launch Box não exporta nenhuma interface para outras partes do sistema (interfaces de usuário não contam!). Então nós podemos deixar este campo comentado ou deletá-lo.
[BuildPrepare/BuildUnprepare]
Essas partes do specfile descrevem como compilar o programa pronto
para ser empacotad. Porque a maioria dos projetos utiliza o sistema
de compilação GNU e são padrão, nós fornecemos duas API auxiliares,
prepareBuild()
e unprepareBuild().
prepareBuild cuida de invocar configure, make e make install para você, enquanto
unprepareBuild lida com a limpeza.
Se você não quer utilizar isto por quaisquer razões, a tarefa essencial dos scripts
é criar uma árvore instalada no diretório apontado por $build_root.
Nota: o diretório de trabalho nesta seção é a pasta na qual makeinstaller é invocado.
prepareBuild executa make install de tal forma que tudo é instalado
em $build_root.
Para Launch Box podemos deixar essas seções com os valores padrão:
[BuildPrepare] prepareBuild [BuildUnprepare] unprepareBuild
[Imports]
Frequentemente o sistema de construção de um programa irá instalar mais arquivos do que realmente faz sentido ter em um pacote. Por exemplo, ele pode instalar cabeçalhos ou "ChangeLogs" os quais não são de utilidade para o usuário médio. A seção [Imports] deixa você escolher quais arquivos do "build root" você irá inserir no pacote. O normal é importar tudo.
Nota: o diretório de trabalho nesta seção é $build_root!
O diretório no qual makeinstaller foi invocado é referenciado por $source_dir.
A maneira mais fácil de utilizar esta seção é deletar o que você não quer antes da chamada "import". Para Launch Box, queremos importar tudo, então podemos deixar a seção como o padrão:
[Imports] echo '*' | import
[Prepare]
Autopackages instala em dois estágios. Primeiro, todos os pacotes na cadeia de dependências são preparados. Uma vez que todos os pacotes tenham sido preparados com sucesso eles são instalados em sequência. Na seção Prepare você deve realizar quaisquer verificações que poderiam afetar se a instalação procederá ou não. Verificação de dependências é a coisa mais comum para colocar aqui, mas você a partir do autopackage 1.2 também pode desinstalar pacotes nativos se eles conflitarem com o que você está instalando (ex, se o usuário está atualizando de uma instalação do Launch Box baseada em RPM para autopackage).
Uma vez que verificação (e resolução) de dependências é algo tão comum para ser fazer aqui, autopackage provê muita infra-estrutura para suporte. Isto gira em torno dos "skeleton files" (arquivos esqueleto). Um autopackage funciona de uma forma similar ao script configure padrão: ele utiliza uma biblioteca de testes para descobrir se o sistema possui o que precisa. Arquivos esqueletos são equivalentes às macros M4 que o autoconf utiliza, excetuando que eles funcionam de uma forma diferente.
Para cada dependência que o seu progama tem, deve haver um arquivo esqueleto. Se não há, você precisará escrever um. Felizmente, autopackage vem com uma grande biblioteca de esqueletos prontos para usar, e estamos felizes em aceitar quaisquer outros que você escrever. No futuro é esperado que projetos irão instalar arquivos esqueletos como instalam arquivos .pc ou cabeçalhos hoje em dia. Esqueletos são copiados dentro do próprio pacote, e você pode colocar esqueletos customizados dentro do diretório autopackage junto com seu specfile.
O propósito de um arquivo esqueleto é mapear o estado do sistema para um conjunto de versões de interface. As versões de interface escolhidas são arbitrárias e de acordo com o autor do esqueleto. Geralmente o mapeamento será óbvio ou intuitivo, mas algumas vezes pode não ser. Consulte a seção de notas dos esquletos relevantes para mais informação.
O script de preparação do Launch Box é assim:
# Dependency checking require @gtk.org/gtk 2.4 require @gnome.org/libgnomevfs 2.10 require @gnome.org/libgnomeui 2.0 # let's assume for now that if gnome-vfs 2.10 is installed, the rest of gnome 2.10 is also recommend @gnome.org/evolution/libebook 3
Como você pode ser, autopackage suporta tanto "hard dependencies" (requesitos obrigatórios) como "soft dependecies" (requesito recomendados). A diferença é que enquanto ambos os tipos irão tentar resolver a dependência, se "require" falhar irá abortar a instalação. "Recommended", por outro lado, nunca falha. Se o usuário estiver sem um pacote que é recomendado, a instalação irá continuar, mas no fim ele será lembrado que instalar este pacote lhe dará funcionalidade extra.
O número ao final é a versão. Para as bilbiotecas GNOME/GTK+, deve ser óbvio de onde vem o número. Para as bibliotecas libebook não é óbvio. Na verdade, eu tive que escrever um esqueleto para libebook especificamente para GNOME Launch Box, já que não estava na biblioteca autopackage. Vamos ver como eu fiz isso.
Esqueletos
[Meta] RootName: @gnome.org/evolution/libebook DisplayName: Evolution Address Book Library ShortName: libebook Skeleton-Author: Mike HearnSkeleton-Version: 1 [Notes] O versionamento e-d-s, em geral, é estranho e bagunçado, este esqueleto pode ser totalmente impreciso ou errado. Você foi avisado. Versões de "soname" diferentes são mapeadas para diferentes versões de interface "major". [Test] INTERFACE_VERSIONS=`testForLib -v libebook-1.2.so` if [[ "$INTERFACE_VERSIONS" != "" ]]; then SOFTWARE_VERSIONS="1.2" fi
Este texto deve ser colocado em um arquivo chamado "skeleton.1", em "/usr/share/autopackage/skeletons/@gnome.org/evolution/libebook". Pode ser colocado no diretório autopackage específico do projeto também.
Como você pode ver, isto consiste em várias partes. A primeira e a
familiar seção Meta. Pacotes não são as únicas coisas que possuem
um nome raiz: eles também identificam unicamente interfaces lógicas.
Neste caso, nós atribuímos o nome raiz @gnome.org/evolution/libebook
para a biblioteca libebook. Nós também associamos este nome raiz com um nome
de exibição (que pode ser local), e um nome curto. O nome de exibição
será usar nas mensagens "Checking for ...." (Procurando por ....) na
interace do usuário. Finalmente, um pouco de metadados sobre o
esqueleto em si são fornecidos. Esqueletos são versionados também,
mas esta funcionalidade raramente é necessária e iremos ignorá-la aqui.
A seção "Notes" (Notas) é livre. Autopackage não se importa com o que vai aqui, então é útil para comunicar ao empacotador como seu esqueleto representa o estado do sistema. Neste caso, nós lembramos sobre o confuso e não tão bem documentado estado do número de versão da libebook: este esqueleto provavelmente mudará no futuro.
A seção "Test" é onde o trabalho é feito. Este código deve ser "set" (atribuir valor) a duas variáveis, INTERFACE_VERSIONS e SOFTWARE_VERSIONS. INTERFACE_VERSIONS é necessária mas SOFTWARE_VERSIONS é opcional - é utilizada pelas funções requireExact/requireAtLeast.
A função testForLib retorna o número de versão após a
extensão .so para um dado "soname". Em meu sistema, isto retorna
"3.1.1" porque eu possuo libebook-1.2.so.3.1.1 instalado.
Enquanto tecnicamente versões de interface devem ser precisamente
dois inteiros, X.Y, autopackage irá descartar o último componente
se somente um for fornecido. Este é o motivo para você poder
diretamente alimentar os resultados da função testForLib na variável
INTERFACE_VERSIONS.
Neste caso, nós simlpesmente usamos o fato de que detectamos somente bibliotecas da versão de API 1.2 para atribuir à SOFTWARE_VERSIONS. Um pouco de "cop-out" (truqe evasivo), mas lá vai você.
Instalação
Agora que verificamos que nosso pacote pode ser instalado OK, é hora de realmente fazer isso.
Você instalaou os arquivos que são importados anteriormente utilizando a API install*. Há uma API para cada tipo de arquivo que você vai copiar. Neste caso, Launch Box é muito simples e possui somente dois tipos de arquivo:
[Install] installExe bin/* installData share/lb
Como você pode ver, nós combinamos a API para o tipo do arquivo. No futuro, escrever seções [Install] provavelmente será automático. Por enquanto você deve fazer isso você mesmo. Há uma tabela de tipos de arquivos para a API correspondente no documento "developer quickstart".
Para arquivos que não possuem uma API específica, nós podemos utilizar copyFiles. Nós utilizamos estas funções em vez do "cp" regular porque elas tomam conta de detalhes para nós. Por exemplo, nós não precisamos especificar o destino porque autopackage irá descobrir para nós baseado no prefixo escolhido pelo usuário, "defaults" (padrões), "layout" de distribuição e tipo de arquivo. As APIs também podem realizar várias transformações no arquivo para coisas como itens de menu, entre outras, para lidar com as diferenças nas distribuições.
Passos finais
A seção [Uninstall] pode ser deixada como é. Nós precisamos somente transformar nosso specfile completo e software em um delicioso pacote que o usuário pode pegar e instalar com facilidade. Este é o trabalho de makeinstaller.
Para construir o pacote, nós simplesmente executamos o comando makeinstaller no raiz de sua árvore de desenvolvimento. O arquivo autopackage/default.apspec será automaticamente utilizado. Makeinstaller sabe regenerar o specfile através do modelo do autoconf se um existir, então você não precisa ter que fazer isso você mesmo quando modificando o spec. Antes de você executar o makeinstaller, certifique-se de fazer um "make clean" para limpar quaisquer compilações anteriores que você tenha feito. É importante que uma compilação limpa seja feita porque, caso contrário, apbuild (a ferramenta de portabilidade de binário) não será complemtamente efetivo.
Se nós tivermos quaisquer avisos no fim, nós precisamos voltar e arrumá-los. Caso contrário, nosso pacote está pronto! Tudo o que precisamos fazer é testá-lo e estaremos bem.
Encapsulando
Há alguns detalhes que eu escolhi ignorar. O primeiro é que GNOME Launch Box é bastante incompleto como um programa - por exemplo, não há entrada de menu. Autopackage somente mostra ao usuário pacotes que forneçam entradas de menu no desinstalador gráfico, para que o usuário não possua somente uma forma gráfica de iniciar o programa, mas também de desintalá-lo se eles ficarem entediados. Arrumar isso é fácil, nós precisamos somente prover um arquivo .desktop e um ícone para ele. Autopackage provê o script "makeicons" em apbuild para integrar ícones SVG dentro do sistema de criação de seu software mais fácil.
O segundo é suporte C++. Launc Box é escrito em C, então nós podemos ignorar isso agora. Suporte C++ está mudando radicalmente em autopackage 1.2, o que não está pronto ainda, então faz sentido trabalhar nisso até que as coisas acalmem. Um novo tutorial irá cobrir o que fazer com aplicações C++ qaundo o suporte estiver pronto. Por enquanto, lembre-se da regra básica: está OK ditribuir aplicações C++ enquanto elas não liguem com nenhuma biblioteca C++. Por exemplo, AbiWord está OK porque ele "stands alone" (firma-se sozinho) e não utiliza nenhuma biblioteca C++. Inkscape também está OK uma vez que você tenha ligado estaticamente as amarrações GTKmm. Mas aplicações KDE/Qt não estão OK, pelo menos, não por enquanto.

