Using Par::Packer (pp) with WxWidgets on Windows

After spending a considerable amount of time trying to package a Gtk2 app with pp, I decided to try a different gui toolkit, and was successful packaging a Wx app.

Again, most of this kludge is based on bug reports from Marc Lehmann regarding Gtk. Thanks Marc!

First off, we need to create a list of all the Wx files that aren’t picked up automatically by pp. I use this script to create the list and run pp. Note that I am running the script under cygwin, but I want to use the ActiveState Perl to run pp so we end up with a native Windows app. (BTW, I tried our Strawberry Perl, but it had issues with some of the dependencies due to a lack of pkgconfig.)

#!/bin/sh

# ppkludge - Automatically package the Wx dependencies with pp

WX="/cygdrive/c/Perl/site/lib/auto/Wx"
MODS=""

(
 cat <<EOF
icons/test.bmp;root/icons/test.bmp
templates;root/templates
EOF

        cd "$WX" || exit
        for dll in *.dll; do
                echo "`cygpath -w $WX/$dll`;root/$dll"
        done

) >addlist

cdir=`pwd`
cd "$WX" || exit
for dir in *; do
        if [ -d $dir ] ; then
                MODS="$MODS -M Wx::$dir"
        fi
done
cd $cdir || exit

trap "/bin/rm addlist" 0

# unset BASH_ENV CLASSPATH COLORFGBG GTK_BASEPATH HOME INFOPATH INPUTRC KAPSRES PKG_CONFIG_PATH
PATH=/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/perl/bin
/cygdrive/c/perl/bin/perl /perl/bin/pp --gui -o test.exe -I lib $MODS -A addlist test.pl

This will add the required files to the par/exe archive under the root/ directory. Now when you start your script, you need to unzip these files into the par cache directory. Use the following package, PAR::Kludge, in you script to do so.

package PAR::Kludge;

# This is a package implementing the fix discovered by Marc Lehmann. Thanks
# for sharing this solution; I would have never figured this out!
# The original can be found at: http://txt.schmorp.de/2629b6fdba568e7cda3ed953cbaf8613.txt

use strict;
use warnings;

our $VERSION = '0.30';

BEGIN {
    my $dbg; for(@ARGV){ $dbg++ if /^-d|^--debug/;}

    print "Running kludge\n" if $dbg;
    if (%PAR::LibCache) {
        print "kludging\n" if $dbg;
        @INC = grep ref, @INC; # weed out all paths except pars loader refs

            while (my ($filename, $zip) = each %PAR::LibCache) {
                for ($zip->memberNames) {
                    next unless m!^root/(.*)!;
                    print "zip: $_\n" if $dbg;
                    $zip->extractMember ($_, "$ENV{PAR_TEMP}/$1")
                        unless -e "$ENV{PAR_TEMP}/$1";
                }
            }

        print "Inc:\n", join("\n",@INC),"\n" if $dbg;
        print "Temp:\n", $ENV{PAR_TEMP},"\n" if $dbg;
        print "Path:\n", $ENV{PATH},"\n" if $dbg;

        # print "Chdir to $ENV{PAR_TEMP}\n" if $dbg;
        # chdir $ENV{PAR_TEMP} if $ENV{PAR_TEMP};
        # use lib "$ENV{PAR_TEMP}/inc/lib";
    }
}

1;

The included script and PAR::Kludge packages can downloaded here. Hopefully this save someone else a bunch of time!

Published

June 28, 2007 12:26PM

Tags

License

The contents of this blog are licensed under the Creative Commons “Attribution-Noncommercial-Share Alike 3.0″ license.