Um ein Perl-Skript portabel zu machen, muß zusammen mit dem Skript auch die Perl Laufzeitumgebung sowie die benötigten Bibliotheken ausgeliefert werden.
Befragt man die Suchmaschine der Wahl, landet man meist bei der Empfehlung, einen Perl-Packer zu nehmen, von denen es im CPAN zwei Stück gibt: PAR-Packer und perlcc, wobei von der Verwendung von perlcc im produktiven Umfeld ganz klar abgeraten wird: “Use for production purposes is strongly discouraged.”.
Mit pp gibt es ein eigenes Skript, auf Basis von PAR ausführbare Dateien erzeugt und ein Skript mitsamt aller benötigter Bibliotheken in einer einzelnen .EXE-Datei verpackt.
Das Packen ist recht flexibel und schnell erledigt, die einzelnen Optionen können in der Dokumentation nachgeschlagen werden.
pp -o test.exe --gui --addfile=test.ini --addfile=test.ico test.pl -T test
Wer noch gerne ein schöne(re)s Icon für die erzeugte .EXE-Datei verwenden möchte, kann dies mit einem Einzeler hinzufügen:
perl -e "use Win32::Exe; $exe = Win32::Exe->new('test.exe'); $exe->set_single_group_icon('test.ico'); $exe->write;"
Als Ergebnis wird eine Datei “test.exe” erzeugt, die dann auf ein System ohne Perl-Laufzeitumgebung kopiert und dort ausgeführt werden kann. Die Beschreibung “perlcc that works without hassle” klingt erstmal gut und die Ergebnisse funktionieren, bringen aber leider in der Anwendung einige Probleme mit sich:
Technisch gesehen wandelt pp nicht wirklich das Skript in eine .EXE-Datei, sondern erzeugt ein selbstenpackendes Archiv, dessen Inhalt nach dem Entpacken letztendlich ausgeführt wird. Das Archiv wird standardmäßig ins TEMP-Verzeichnis des ausführenden Benutzers entpackt, was spätestens dann zu Problemen führt, wenn - aus guten Grund - unprivilegierten Benutzern das Ausführen von Code innerhalb des TEMP-Verzeichnis verboten ist.
Zum Entpacken wird ein Verzeichnis nach dem Muster “%TEMP%\par-USER\cache-GUID” angelegt, wobei USER durch eine Hex-Repräsentation des ausführenden Benutzers und GUID durch einen Hash der ausführbaren Datei ersetzt wird. Letzteres lässt sich mit Hilfe des Parameters “-T” durch einen festen Wert ersetzten, so daß der Pfad dann “%TEMP%\par-USER\cache-test” lautet.
Durch das Cachen der entpackten Dateien wird bei späteren Starts die Wartezeit deutlich verkürzt, je nach System und Anzahl der Benutzer können aber zahlreiche Dateileichen im Temp-Verzeichnis verbleiben.
Manuelle Paketierung
Abgesehen von der suboptimalen Ausführung erledigt pp das Sammeln aller benötigter Dateien sowie Erstellen des Pakets zuverlässig, so daß sich die Verwendung von pp als Zwischenschritt zum manuellen Packen anbietet.
Nach dem erstmaligen Ausführen der von pp erzeugten Datei werden folgende Inhalte des Verzeichnisses “%TEMP%\par-USER\cache-test” in ein Arbeitsverzeichnis kopiert:
- der komplette Ordner “inc” inklusive aller darin enthaltenen Unterverzeichnisse
- die Dateien “libgcc_s_seh-1.dll”, “libstdc++-6.dll”, “libwinpthread-1.dll” sowie “perl530.dll”
Anschließend kann noch etwas augeräumt werden:
- im Ordner “inc” können die Dateien “MANIFEST” sowie “META.yml” gelöscht werden
- im Ordner “inc/script” kann die Datei “main.pl” gelöscht werden
Zum Ausführen müssen aus der Perl-Installation noch zwei Dateien kopiert werden:
- die Datei “perl.exe” oder “wperl.exe” aus dem Ordner “perl/bin” ins Arbeitsverzeichnis - je nachdem, ob es sich um eine Kommandozeilen- oder GUI-Anwendung handelt
- die Datei “lib.pm” aus dem Ordner “perl/lib” in den Ordner “inc/lib”
Anschließend kann aus dem Ordner “inc” das Skript mit folgendem Aufruf gestartet werden:
..\perl.exe -I lib script\test.pl