Ako na CPAN-like modul
slovenská verzia | english version
CPAN moduly sú distribuované vo forme .tar.gz kde sú zkomprimované a uložené
jednotlivé súbory. Takto pripravené modulu si môžu užiť širokú paletu open
source nástrojov ako je napríklad dh-make-perl, ktorý z nich
vytvorí Debian balíček. Moduly nemusia byť použité len pre upload na CPAN ale
aj na "interné" - closed source použitie. Zjednodušia organizovanie a
inštalovanie.
Na "naštartovanie" je najjednoduchšie použiť
Module::Starter. Takže
apt-get install libmodule-starter-perl alebo cpan -i Module::Starter
pridá do systému module-starter skriptík. Tento vie vytvoriť celú
súborovú štruktúru pre modul. Napríklad chceme vytvoriť modul ktorý reprezentuje
vlak. ;-) Nepýtajte sa ma prečo. (pretože nič dômyselnejšie ma momentálne nenapadlo)
$ module-starter --builder=Module::Build --module=Acme::DopravnyProstriedok::Vlak \
--author="Jozef Kutej" --email=jozef@kutej.net
Created starter directories and files
$ tree Acme-DopravnyProstriedok-Vlak/
Acme-DopravnyProstriedok-Vlak/
|-- Build.PL
|-- Changes
|-- MANIFEST
|-- README
|-- lib
| `-- Acme
| `-- DopravnyProstriedok
| `-- Vlak.pm
`-- t
|-- 00-load.t
|-- boilerplate.t
|-- pod-coverage.t
`-- pod.t
Čo znamenajú jednotlivé súbory:
Build.PL
use strict;
use warnings;
use Module::Build;
my $builder = Module::Build->new(
module_name => 'Acme::DopravnyProstriedok::Vlak',
license => 'perl',
dist_author => 'Jozef Kutej <jozef@kutej.net>',
dist_version_from => 'lib/Acme/DopravnyProstriedok/Vlak.pm',
build_requires => {
'Test::More' => 0,
},
add_to_cleanup => [ 'Acme-DopravnyProstriedok-Vlak-*' ],
create_makefile_pl => 'traditional',
);
$builder->create_build_script();
Build.PL pomocou `perl Build.PL` vytvorí Build ktorý sa dá spustiť.
Build má veľa argumentov:
$ ./Build help Usage: ./Build <action> arg1=value arg2=value ... Example: ./Build test verbose=1 Actions defined: build manifest clean manpages code pardist config_data ppd diff ppmdist dist prereq_report distcheck pure_install distclean realclean distdir retest distmeta skipcheck distsign test disttest testall docs testcover fakeinstall testdb help testpod html testpodcoverage install versioninstall Run `Build help <action>` for details on an individual action. See `perldoc Module::Build` for complete documentation.
Najdôležitejšie sú - build, test, install, clean. "build" pripraví všetky potrebné súbory pre inštalovanie modulu a skopíruje ich do adresára blib. "test" spustí na týchto súboroch všetky testy nachádzajúce sa v adresári t/. "install" nainštaluje modul do systému. A "clean" poupratuje/zmaže súbory ktoré Build vytvoril.
Bežný návod ako nainštalovať module pozostáva z
`perl Build.PL && ./Build && ./Build test && ./Build install`, v prípade
že konfigurácia/inštalácia (ako nášho module) je postavená na
Module::Build. Druhá možnosť
je ExtUtils::MakeMaker.
V tom prípade sa inštaluje pomocou
`perl Makefile.PL && make && make test && make install`. Ak je v Build.PL
zapnuté create_makefile_pl => 'traditional' tak Module::Build
vytvorí aj Makefile.PL takže sa dá inštalovať aj druhým spôsobom. Okolo toho
či používať Module::Build, alebo ExtUtils::MakeMaker sa vedú vojny, pričom
existuje ešte Module::Install a iné...
Changes
Revision history for Acme-DopravnyProstriedok-Vlak
0.01 Date/time
First version, released on an unsuspecting world.
súbor obsahuje zmeny ktoré boli urobené v konkrétnej verzií modulu.
MANIFEST
Build.PL Changes MANIFEST README lib/Acme/DopravnyProstriedok/Vlak.pm t/00-load.t t/pod-coverage.t t/pod.t
MANIFEST obsahuje zoznam súborov ktoré patria k modulu. Ostatné
súbory budú pri vytváraní distribúcie (Acme-DopravnyProstriedok-Vlak-0.01.tar.gz)
zignorované. MANIFEST treba udržiavať "up-to-date". Ľahko sa stane že sa pridá nový
súbor do distribúcie a zabudne sa na MANIFEST. Ako pomôcka slúži `./Build distcheck`
ktorý upozorní že existujú nejaké súbory ktoré sa nenachádzajú v MANIFEST-e.
Dobré je si pridať súbor MANIFEST.SKIP v ktorom sa nachádza zoznam súborov ktoré sa majú pri tomto teste ignorovať.
MANIFEST.SKIP
# Avoid version control files. \bRCS\b \bCVS\b ,v$ \B\.svn\b # Avoid Makemaker generated and utility files. \bMakefile$ \bblib \bMakeMaker-\d \bpm_to_blib$ \bblibdirs$ ^MANIFEST\.SKIP$ # Avoid Module::Build generated and utility files. \bBuild$ \b_build \bcover_db # Avoid temp and backup files. ~$ \.tmp$ \.old$ \.bak$ \#$ \b\.# \.cvsignore \.svnignore
README
Keď sa do Build.PL pridá create_readme => 1, vyupdatuje sa tento
súbor pri vytváraní distribúcie z PODu hlavného .pm súboru. V našom
prípade lib/Acme/DopravnyProstriedok/Vlak.pm. Update teda
nastane pri `./Build dist` alebo pri `./Build distmeta`.
Okrem README sa vytvoria aj nové verzie META.yml a Makefile.PL.
META.yml
Tento súbor obsahuje základné údaje
o module v YAML formáte. Je automaticky
generovaný pri `./Build dist` alebo pri `./Build distmeta` z informácií
v Build.PL .
.cvsignore
Obsahuje príklad toho čo ignorovať ak sa na revisioning control
používa CVS. Ak používate Subversion dá sa použiť -
`svn propset svn:ignore "`cat .cvsignore`" . && svn rm .cvsignore`.
Alebo pre GIT `mv .cvsignore .gitignore`.
t/ adresár
v tomto adresáre sa nachádzajú testy. Každý dobrý module/distribúcia by mala obsahovať testy. Tieto zaručia jednak pri vývoji, ale hlavne pri prerábaní, veľkých fixoch a iných zmenách, že funkcionalita zostane zachovaná. Aj vďaka testom vďačia Perl moduly za svoju kvalitu. Keď autor modulu nahrá novú verziu na CPAN, automaticky si to "všimnú" smoke testing servery a zbehnú tieto testy. Výsledky o tom či prešli, alebo neprešli a pre ktoré verzie Perl-u a ktoré operačné systémy sa dajú nájsť opäť na CPAN-e.
t/00-load.t je jednoduchý test ktorý zistí či sa dá náš
nový modul skompilovať.
t/pod-coverage.t prejde všetky súbory a zistí či sú všetky
funkcie okomentované.
t/pod.t otestuje či je pod dokumentácie bez syntaktických
chýb. Tieto posledné dva sú pomôcka pre autora modulu
a je dobre si ich nechať. Ďalej je dobre si pridať nasledujúce testy:
00-compile.t skontroluje či všetky moduly v distribúcií
sa skompilujú v poriadku -
use strict;
use Test::More;
eval "use Test::Compile 0.08";
plan skip_all => "Test::Compile 0.08 required for testing compilation"
if $@;
my @pmdirs = qw(lib blib sbin bin);
all_pm_files_ok(all_pm_files(@pmdirs));
pod-spell.t skontroluje spelling v pod dokumentácií -
use strict;
use Test::More;
if (!$ENV{TEST_SPELLING}) {
plan skip_all =>
"Set the environment variable TEST_SPELLING to enable this test.";
}
eval 'use Test::Spelling;';
plan skip_all => "Test::Spelling required for testing POD spelling"
if $@;
add_stopwords(qw(
Jozef
));
all_pod_files_spelling_ok();
distribution.t otestuje či všetky súbory distribúcie sú
v poriadku -
use Test::More; eval 'use Test::Distribution not => "sig"'; plan( skip_all => 'Test::Distribution not installed') if $@;
signature.t otestuje digitálny podpis od autora
modulu. Spustí sa len keď je nastavené $ENV{TEST_SIGNATURE} a keď
existuje SIGNATURE súbor. Tento sa dá automaticky generovať
ak sa do Build.PL pridá sign => 1, -
#!/usr/bin/perl
use strict;
use Test::More;
if (!$ENV{TEST_SIGNATURE}) {
plan skip_all =>
"Set the environment variable TEST_SIGNATURE to enable this test.";
}
elsif (!eval { require Module::Signature; 1 }) {
plan skip_all =>
"Next time around, consider installing Module::Signature, ".
"so you can verify the integrity of this distribution.";
}
elsif ( !-e 'SIGNATURE' ) {
plan skip_all => "SIGNATURE not found";
}
elsif ( -s 'SIGNATURE' == 0 ) {
plan skip_all => "SIGNATURE file empty";
}
elsif (!eval { require Socket; Socket::inet_aton('pgp.mit.edu') }) {
plan skip_all => "Cannot connect to the keyserver to check module ".
"signature";
}
else {
plan tests => 1;
}
my $ret = Module::Signature::verify();
SKIP: {
skip "Module::Signature cannot verify", 1
if $ret eq Module::Signature::CANNOT_VERIFY();
cmp_ok $ret, '==', Module::Signature::SIGNATURE_OK(), "Valid signature";
}
lib/Acme/DopravnyProstriedok/Vlak.pm
Konečne sme sa dostali k dôvodu prečo sme robili všetku túto parádu :-) , a to vytvoriť modul k všeobecnému blahobytu. Tu má každý voľnu ruku a môže sa do sýtosti zrealizovať. O tom čo je to modul a ako vyzerá z vnútra napíšem v inom návode.
Výcuc ;-)
Rýchly štart:
module-starter --builder=Module::Build --module=Acme::DopravnyProstriedok::Vlak::Rychlik \
--author="Jozef Kutej" --email=jozef@kutej.net
cp MANIFEST.SKIP Acme-DopravnyProstriedok-Vlak-Rychlik/
cp 00-compile distribution.t pod-spell.t signature.t \
Acme-DopravnyProstriedok-Vlak-Rychlik/t/
rm Acme-DopravnyProstriedok-Vlak-Rychlik/t/boilerplate.t
cd Acme-DopravnyProstriedok-Vlak-Rychlik/
vim Build.PL
# pridat
# create_readme => 1,
# sign => 1,
vim lib/Acme/DopravnyProstriedok/Vlak/Rychlik.pm
# nieco zmysluplne nakodit
# zmenit verziu v hlavnom .pm, vyplnit Changes
perl Build.PL; ./Build clean; perl Build.PL && ./Build distcheck && ./Build disttest && ./Build dist
# upload => pause.cpan.org
Slovo na záver. Netreba sa báť pridať niečo na CPAN. Pokiaľ to nekoliduje s iným modulom bude to indexované a pretrvá to tam na veky vekov. Treba rešpektovať niektoré namespace ako DateTime ktoré sa ho snažia mať upratané, ale v takých prípadoch sa niekto ozve, že mu tam robíte bordel. ;-)
Linky: Čo skrýva CPAN
24. Jun 2008
Jozef
How to make CPAN-like module
slovenská verzia | english version
Perl modules are distributed in form of .tar.gz. In this form they can be
uploaded to CPAN or used with wide range of ready made open source utilities
like for example dh-make-perl that will make debian package out
of them. This form makes the modules organization and instalation really easy.
For a "quick start" the most easiest way is to use
Module::Starter.
So either do apt-get install libmodule-starter-perl or
cpan -i Module::Starter. This will add a module-starter
script to the system, which can create the whole file structure for us.
For example we want to make a module representing train. ;-) Don't ask me
why. (nothing more clever camed to my mind)
$ module-starter --builder=Module::Build --module=Acme::DopravnyProstriedok::Vlak \
--author="Jozef Kutej" --email=jozef@kutej.net
Created starter directories and files
$ tree Acme-DopravnyProstriedok-Vlak/
Acme-DopravnyProstriedok-Vlak/
|-- Build.PL
|-- Changes
|-- MANIFEST
|-- README
|-- lib
| `-- Acme
| `-- DopravnyProstriedok
| `-- Vlak.pm
`-- t
|-- 00-load.t
|-- boilerplate.t
|-- pod-coverage.t
`-- pod.t
What is a meaning of the files:
Build.PL
use strict;
use warnings;
use Module::Build;
my $builder = Module::Build->new(
module_name => 'Acme::DopravnyProstriedok::Vlak',
license => 'perl',
dist_author => 'Jozef Kutej <jozef@kutej.net>',
dist_version_from => 'lib/Acme/DopravnyProstriedok/Vlak.pm',
build_requires => {
'Test::More' => 0,
},
add_to_cleanup => [ 'Acme-DopravnyProstriedok-Vlak-*' ],
create_makefile_pl => 'traditional',
);
$builder->create_build_script();
Build.PL using `perl Build.PL` command will create a file
called "Build" that is it self a Perl script and is executable. Build has many arguments:
$ ./Build help Usage: ./Build <action> arg1=value arg2=value ... Example: ./Build test verbose=1 Actions defined: build manifest clean manpages code pardist config_data ppd diff ppmdist dist prereq_report distcheck pure_install distclean realclean distdir retest distmeta skipcheck distsign test disttest testall docs testcover fakeinstall testdb help testpod html testpodcoverage install versioninstall Run `Build help <action>` for details on an individual action. See `perldoc Module::Build` for complete documentation.
The most importat are - build, test, install, clean. "build" will prepare all files necessary for a module instalation by copying them to the blib folder. "test" will run all the test scripts that can be found in t/ folder. "install" will install all the files to the system. And "clean" will cleanup files after previous Build executions.
Common guide to install a module is
`perl Build.PL && ./Build && ./Build test && ./Build install`,
that is in case that the instalation (like this example one) is based on
Module::Build.
Second options is
ExtUtils::MakeMaker.
In this case the instalation procedure is
`perl Makefile.PL && make && make test && make install`.
If there is create_makefile_pl => 'traditional' in the
Build.PL then Module::Build will create Makefile.PL in the time of creating
distribution. A wars are fought if to use Module::Build or ExtUtils::MakeMaker
and of course those are not all options. There is also Module::Install and ...
Changes
Revision history for Acme-DopravnyProstriedok-Vlak
0.01 Date/time
First version, released on an unsuspecting world.
Changes holds changes that occure between version releases.
MANIFEST
Build.PL Changes MANIFEST README lib/Acme/DopravnyProstriedok/Vlak.pm t/00-load.t t/pod-coverage.t t/pod.t
MANIFEST holds a list of files which belong to the module. The rest of the
files will be ignored at the time a distribution
(Acme-DopravnyProstriedok-Vlak-0.01.tar.gz) is created. MANIFEST should be kept
up to date. It's easy to add a file to a folder and forget to update MANIFEST.
As a helper there is `./Build distcheck` that will "complain" if
there is some extra file.
It's good to add MANIFEST.SKIP where is the list of files that should be really ignored. (mostly the extra files autogenerated by `Build`)
MANIFEST.SKIP
# Avoid version control files. \bRCS\b \bCVS\b ,v$ \B\.svn\b # Avoid Makemaker generated and utility files. \bMakefile$ \bblib \bMakeMaker-\d \bpm_to_blib$ \bblibdirs$ ^MANIFEST\.SKIP$ # Avoid Module::Build generated and utility files. \bBuild$ \b_build \bcover_db # Avoid temp and backup files. ~$ \.tmp$ \.old$ \.bak$ \#$ \b\.# \.cvsignore \.svnignore
README
When there is create_readme => 1, in the Build.PL, then
README file is autogenerated from the POD of the main .pm file. In our
case lib/Acme/DopravnyProstriedok/Vlak.pm. This update will
happend by `./Build dist` or by `./Build distmeta`.
META.yml
This file holds
basic
information about the module in YAML
format. It is automaticaly
generated by `./Build dist` or by `./Build distmeta`
from the information found in Build.PL .
.cvsignore
Holds examples what can be ignored when using revisioning control system
for module development. In this for can be directly used by CVS. Subversion
users can do `svn propset svn:ignore "`cat .cvsignore`" . && svn rm .cvsignore`
or GIT users `mv .cvsignore .gitignore`.
t/ folder
A test scripts are in t/ folder. Every good module/distribution has a couple of them. They will guarranty as during the development time, but mainly when fixing or refactoring code that the functionality stay unchanged. Also thanks to these test most modules are high quality. When author upload new module version to the CPAN, this is automaticaly tracked by smoke testing servers that will run these tests. The output are the reports about passed/failed tests for different versions of Perl and different operating systems. This reports can then be see along other module information.
t/00-load.t is a basic test that will check if the module
compiles.
t/pod-coverage.t will go through the code and check if all
functions has a pod documentation.
t/pod.t will check if the pod documentation is without errors.
It's good to add also following tests:
00-compile.t checks if all modules in the folder structure
will compile. -
use strict;
use Test::More;
eval "use Test::Compile 0.08";
plan skip_all => "Test::Compile 0.08 required for testing compilation"
if $@;
my @pmdirs = qw(lib blib sbin bin);
all_pm_files_ok(all_pm_files(@pmdirs));
pod-spell.t checks pod spelling -
use strict;
use Test::More;
if (!$ENV{TEST_SPELLING}) {
plan skip_all =>
"Set the environment variable TEST_SPELLING to enable this test.";
}
eval 'use Test::Spelling;';
plan skip_all => "Test::Spelling required for testing POD spelling"
if $@;
add_stopwords(qw(
Jozef
));
all_pod_files_spelling_ok();
distribution.t checks if all distribution files are ok -
use Test::More; eval 'use Test::Distribution not => "sig"'; plan( skip_all => 'Test::Distribution not installed') if $@;
signature.t checks digital signature of the module
author. This test will run only if $ENV{TEST_SIGNATURE} will
be set and if SIGNATURE file is present. SIGNATURE can be automaticaly generated
by Build.PL by adding sign => 1, -
#!/usr/bin/perl
use strict;
use Test::More;
if (!$ENV{TEST_SIGNATURE}) {
plan skip_all =>
"Set the environment variable TEST_SIGNATURE to enable this test.";
}
elsif (!eval { require Module::Signature; 1 }) {
plan skip_all =>
"Next time around, consider installing Module::Signature, ".
"so you can verify the integrity of this distribution.";
}
elsif ( !-e 'SIGNATURE' ) {
plan skip_all => "SIGNATURE not found";
}
elsif ( -s 'SIGNATURE' == 0 ) {
plan skip_all => "SIGNATURE file empty";
}
elsif (!eval { require Socket; Socket::inet_aton('pgp.mit.edu') }) {
plan skip_all => "Cannot connect to the keyserver to check module ".
"signature";
}
else {
plan tests => 1;
}
my $ret = Module::Signature::verify();
SKIP: {
skip "Module::Signature cannot verify", 1
if $ret eq Module::Signature::CANNOT_VERIFY();
cmp_ok $ret, '==', Module::Signature::SIGNATURE_OK(), "Valid signature";
}
lib/Acme/DopravnyProstriedok/Vlak.pm
Finaly we are at the purpouse of doing all this parade :-) , and that is to create a module for a general purpouse. Here everyone has a free hand and can let his fantazy fly. What it is a module and how does it look inside will be a scope of a differen tutorial.
Resume
Quick start:
module-starter --builder=Module::Build --module=Acme::DopravnyProstriedok::Vlak::Rychlik \
--author="Jozef Kutej" --email=jozef@kutej.net
cp MANIFEST.SKIP Acme-DopravnyProstriedok-Vlak-Rychlik/
cp 00-compile distribution.t pod-spell.t signature.t \
Acme-DopravnyProstriedok-Vlak-Rychlik/t/
rm Acme-DopravnyProstriedok-Vlak-Rychlik/t/boilerplate.t
cd Acme-DopravnyProstriedok-Vlak-Rychlik/
vim Build.PL
# pridat
# create_readme => 1,
# sign => 1,
vim lib/Acme/DopravnyProstriedok/Vlak/Rychlik.pm
# code something that makes sence
# change version in .pm, fill out the Changes
perl Build.PL; ./Build clean; perl Build.PL && ./Build distcheck && ./Build disttest && ./Build dist
# upload => pause.cpan.org
Word at the end. Don't worry what you upload to CPAN too much. If it's not coliding with a different module it will be indexed and will stay for ever. Even it is good to respekt some namespaces like DateTime that try to have the house tidy, but in those case you'll be contacted that you should stop doing the mess... ;-)
Links: CPAN - Comprehensive Perl Archive Network
24. Jun 2008
Jozef
en