Perl ist eine freie, plattformunabhängige und interpretierte Programmiersprache. Als Stärken dieser Programmiersprache gelten die Bearbeitung von Texten mit Hilfe regulärer Ausdrücke sowie die Verfügbarkeit von vielen freien Modulen, die über CPAN an einem zentralen Ort gesammelt sind.
Wenn in einem Programm die gleichen Zeilen mehrfach auftreten ist es Sinnvoll, diese in eine Funktion auszulagern. Wird eine solche Funktion in mehreren Programmen verwendet, sollte diese in ein Modul ausgelagert werden um an einer zentralen Stelle gepflegt werden zu können. Wie ein solches Modul erstellt und über CPAN veröffentlicht wird, möchte ich in diesem Blog-Beitrag zeigen.
Damit ein Perl-Modul über CPAN veröffentlicht werden kann, muss dieses Modul bestimmte Voraussetzung erfüllen. Dadurch wird der Aufbau der Module vereinheitlicht und eine Mindestanforderung an Qualität (Abhängigkeiten, Tests, Dokumentation) eingehalten. In Perl gibt es das CPAN-Modul Module::Starter, welches dem Programmierer die Einhaltung dieser Voraussetzungen erleichtert. Unter Debian kann dieses Modul einfach über die Paketverwaltung installiert werden:
aptitude install libmodule-starter-perl
Alternativ kann das Modul auch direkt mit dem cpan
-Befehl installiert werden:
cpan -i Module::Starter
Zuerst legen wir uns ein Verzeichnis an, in dem wir unser Modul erstellen möchten:
mkdir /home/username/CPAN cd /home/username/CPAN
Danach kann das einheitliche Grundgerüst eines CPAN-Moduls mittels Module::Starter
erzeugt werden:
module-starter -mb --module=Mein::Modul --author="Max Mustermann" --email=max.mustermann@example.org
Die Parameter module
, author
und email
sind Pflichtangaben. Der Parameter mb
bewirkt, dass Module::Starter
anstatt standardmäßig ExtUtils::MakeMaker das Modul Module::Build verwendet. Weitere Parameter können aus der Dokumentation des Moduls Module::Starter entnommen werden.
Durch die letzte Anweisung wurde folgende Struktur angelegt, die mit dem Kommandozeilen-Befehl tree
grafisch ausgegeben werden kann:
Mein-Modul ├── Build.PL ├── Changes ├── ignore.txt ├── lib │ └── Mein │ └── Modul.pm ├── MANIFEST ├── README └── t ├── 00-load.t ├── boilerplate.t ├── manifest.t ├── pod-coverage.t └── pod.t
In der Datei Build.PL
werden Parameter für das kompilieren des Moduls eingetragen. Unter anderem werden dort die Abhängigkeiten zu anderen Modulen (falls vorhanden) ergänzt:
use strict; use warnings; use Module::Build; my $builder = Module::Build->new( module_name => 'Mein::Modul', license => 'perl', dist_author => q{Max Mustermann}, dist_version_from => 'lib/Mein/Modul.pm', build_requires => { 'Test::More' => 0, }, requires => { 'Anderes::Modul' => 4.00, 'Noch::Ein::Anderes::Modul' => 0, }, add_to_cleanup => [ 'Mein-Modul-*' ], create_makefile_pl => 'traditional', create_readme => 1, meta_merge => { resources => { repository => 'https://github.com/bitbetrieb/CGI-Session-ID-crypt_openssl' } }, ); $builder->create_build_script();
In der Datei Changes
werden alle Veränderungen am Modul festgehalten. Diese Datei sollte gut gepflegt werden, damit Veränderungen nachvollzogen werden können.
Revision history for Mein-Modul 1.00 08. September 2011 First version created by Module::Starter
Die Datei ignore.txt
kann gelöscht werden. Diese wird nur benötigt, wenn zum kompilieren das Modul ExtUtils::MakeMaker verwendet wird.
Für das Modul selbst wurde ein Grundgerüst unter Mein-Modul/lib/Mein/Modul.pm
erstellt. Dieses Grundgerüst dient als Vorlage für das Modul selbst und kann nun für die eigenen Funktionen angepasst werden. Will man Konflikte mit einer gleichnamigen Variable $VERSION
im Programm vermeiden, sollte die Variable $VERSION
um den Paketnamen ergänzt werden:
$Mein::Modul::VERSION = '1.00';
In der Datei MANIFEST
werden alle Dateien aufgelistet, die für das Modul notwendig sind. Alle anderen Dateien in dem Modul-Verzeichnis werden beim Kompilieren des Moduls ignoriert. Diese Datei sollte immer aktuell gehalten werden, und kann während dem Kompilieren geprüft sowie bei Bedarf angepasst werden. Dazu später jedoch mehr.
Neben der Datei MANIFEST
ist es hilfreich, eine Datei MANIFEST.SKIP
anzulegen, in der Dateien enthalten sind die auf jeden Fall ignoriert werden können (z.B. Dateien für die Versionsverwaltung oder ähnliches).
# Dateien für die Versionsverwaltung ignorieren \bRCS\b \bCVS\b ,v$ \B\.svn\b # Dateien die durch Makemaker erzeugt wurden ignorieren \bMakefile$ \bblib \bMakeMaker-\d \bpm_to_blib$ \bblibdirs$ ^MANIFEST\.SKIP$ # Dateien die durch Module::Build erzeugt wurden ignorieren \bBuild$ \b_build \bcover_db # Temporäre- und Backup-Dateien ignorieren ~$ \.tmp$ \.old$ \.bak$ \#$ \b\.# \.cvsignore \.svnignore \ignore.txt
Es wurde eine README
-Datei angelegt, in der bereits der Grundaufbau der Dokumentation für das Modul enthalten ist. Diese Datei kann nach Belieben ergänzt werden.
Im Ordner t
werden Test-Skripte abgelegt, Welche die Funktionalität des Moduls beim Installieren prüfen. Durch das Anlegen des Moduls mit Module::Starter
wurden bereits einfache Testfunktionen integriert. Je komplexer das Modul aufgebaut wird, desto umfangreicher sollten auch die dazugehörigen Test-Skripte sein.
Das Generieren des Moduls geschieht in mehreren Schritten und beginnt mit folgender Anweisung:
perl Build.PL
Aktualisieren der MANIFEST-Datei:
./Build manifest
Feststellen, ob Dateien im Verzeichnis enthalten sind, jedoch nicht in der MANIFEST
-Datei und anders herum:
./Build distcheck
Testen, ob der Build-Prozess funktionieren würde:
./Build disttest
Wenn alle Befehle erfolgreich abgeschlossen wurden, kann nun mittels folgendem Befehl eine .tar.gz
-Datei des Moduls erzeugt werden:
./Build dist
Nun wurde eine Datei Mein-Modul-1.00.tar.gz
erstellt, die per PAUSE in CPAN übertragen werden kann. Nach dem Anmelden bei PAUSE kann dort über die Funktion Upload a file to CPAN
das gerade Erstellte Modul hochgeladen werden. Nach kurzer Zeit sollte dieses Modul dann über CPAN für jeden Perl-Programmierer verfügbar sein. Herzlichen Glückwunsch!
Diese Dokumentation habe ich während der Erstellung meines ersten CPAN-Moduls CGI::Session::ID::crypt_openssl erstellt. Dieses Modul musste ich Erstellen, da das Modul CGI::Session für die Erzeugung der Sitzungs-ID keine ausreichend generierte Zufallszahl implementiert hat. Nach Kontaktaufnahme mit dem Betreuer des Moduls Mark Stosberg hat er mich dazu ermutigt, hierfür ein eigenes Modul zu erstellen, und dies unter CPAN zu veröffentlichen. Für diesen Anstoß möchte ich mich bei Mark recht herzlich bedanken.
Für das Erstellen eines CPAN-Moduls sowie für die Erzeugung dieser Dokumentation, haben mir folgenden Seiten maßgeblich geholfen:
http://www.rainboxx.de/2008/10/schreib-deinen-code-als-wurde.html
http://cpansearch.perl.org/src/XSAWYERX/Module-Starter-1.58/getting-started.html
http://wiki.perl-community.de/foswiki/bin/view/Wissensbasis/WieErstelleIchEinModul
http://bratislava.pm.org/en/tutorial/new-module.html
https://sites.google.com/site/arjunwebworld/Home/programming/create-cpan-module