[Cascavel-pm] LibZip - crie executáveis bem leves dos seus scripts

Graciliano M. P. gmpowers em terra.com.br
Sábado Junho 12 16:53:18 CDT 2004


E aí pessoal,

Acabei de publicar nesses dias o módulo LibZip no CPAN, e como o pessoal vem
discutindo uma maneira de criar executáveis de um script (compilar), cá está
uma solução:
http://search.cpan.org/~gmpassos/LibZip-0.04/

Exitem também outros módulos similares: PAR, App::Packer e PerlBin.

A história por trás destes módulos se cruzam. Tudo começou (eu acho) com o
projeto HWX, onde era possível criar um executável do Perl que permitia
adicionar um script no fim dele, e o próprio executável percebia a diferença
de tamanho no exe e executava o código extra. Depois o Mattia Barbon (autor
do wxPerl), criou o App::Packer, permitindo então carregar módulos, mas
passar o gerenciamento da localização dos módulos para uma função, então foi
possível carregar os módulos de um único arquivo que continha td o código
agrupado. Em seguida PodMaster criou o módulo PerlBin, vindo diretamente do
HWX, não sendo necessário compilar todo o Perl para criar o executável
modificado.

Depois veio o PAR, que baseou muita coisa no App::Packer e adicionou a
possibilidade de carregar os módulos Perl de um arquivo PAR, que é um
arquivo zip com alguns recursos extras. Mas úm pouco antes do PAR veio o
TinyPerl (http://tinyperl.sf.net), onde se tinha o básico do Perl em apenas
600Kb, permitindo uma instalação rápida do Perl. O TinyPerl carregava os
módulos diretamente de um arquivo lib.zip, tratando esse arquivo como a lib
do Perl, e também utilizava alguma compressão sobre os executáveis. O que
poucos sabem é que o TinyPerl utiliza internamente um módulo chamado LibZip
para carregar arquivos diretamente do arquivo lib.zip.

Recentemente eu e Autrijus (autor do PAR) estávamos discutindo uma maneira
de fazer a próxima versão do TinyPerl com o PAR, permitindo então fazer o
TinyPerl para outros SO, já q eu apenas publiquei o TinyPerl para Win32. O
problema é que o PAR foi criado não apenas para criar executáveis, mas
também para criar distribuições e pacotes independentes para a execução d um
script. Em resumo, muita coisa da sua arquitetura teria que ser modificada.
Então decidi recriar o LibZip desde o início. O resultado final é um LibZip
que criar executáveis e o arquivo lib.zip automaticamente, sem contar com
várias técnicas de compressão para diminuir td o pacote.

Mas o mais difícil foi criar o código inicial, que carrega td o ambiente que
ativa o uso do arquivo lib.zip como biblioteca. E o maior problema é que
este código não pode carregar nenhum módulo, já que a biblioteca de módulos
está dentro do lib.zip. Ou seja, nem strict, nem warnings, nem exporter, nem
nada pode ser chamado. Mas como fazer isso se um módulo complexo com o
Arqchive::Zip e o Compress::Zlib têm q ser ativados para podermos ler
arquivos ZIP. A solução foi refazer esse 2 módulos, mas apenas com os
recursos de extração (decompressão).

O desafio final foi o XS do Compress::Zlib, o coração para se ler arquivos
ZIP. Como vcs sabem um XS é um arquivo externo (dll) carregado pelo
Dynaloader. Bom, a solução foi criar um Dynaloader simples que conseguice
carregar uma DLL padrão. Mas depois consegui fazer algo melhor, deixar a dll
dentro do executável do Perl, não sendo necessário um arquivo externo ou um
Dynaloader para carrega-lo.

OK, agora temos a possibilidade de ler arquivos ZIP, mas temos que ter o
módulo que gerencia a extração dos arquivos para serem carregados em tempo
de executácão. Essa parte então precisa ser em Perl, e carregada antes de
td. No fim o código de inicialização fica td comprimido em zip internamente
no executável, reduzindo ainda mais o pacote.

E como extra para reduzir ainda mais:

1 - É utilizado UPX (http://upx.sf.net) sobre PerlLib (perl56.dll) e o
executável (perl.exe), diminuindo 40% do seu tamanho.
2 - Os arquivos inseridos dentro da lib.zip têm a sua documentação removida
do código com o Pod::Stripper.

No fim, um script simples (Hello World) fica com 330 Kb, contra 1200Kb com o
PAR.

Em alguns dias irei publicar o TinyPerl para vários SO e versões do Perl, só
preciso esperar o feedback d alguns testes q estão sendo feitos. E com o
TinyPerl vcs poderão criar os executaveis sem um compilador. ;-P

Atenciosamente,
Graciliano M. P.





Mais detalhes sobre a lista de discussão Cascavel-pm