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

Well I haven’t completely got it working, but it is darn close. I ended up switching to WxWidgets, which will work with some coaxing. Most of this kludge is based on bug reports from Marc Lehmann. Thanks Marc!

First off, we need to create a list of all the Gtk2 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.)


# ppkludge - Automatically package the Gtk2 dependencies with pp
# This is a tweaked version of a script written by Marc Lehmann. Thanks
# for sharing this solution; I would have never figured this out!
# The original can be found at:
# Here is Marc Lehmann's original comment:
#  Convert a gtk2-perl program to a standalone .exe, including all 
# libraries and runtime files required for running as well as required 
# datafiles. I _literaly_ sold my soul to the devil and paid with blood 
# for this. Microsoft die die die die die die die die die die die die


   cat <<EOF
# Here down, needed for systems w/o gtk
`cygpath -w $GTK2/etc`;root/etc
`cygpath -w $GTK2/lib/pango`;root/lib/pango
`cygpath -w $GTK2/lib/gtk-2.0`;root/lib/gtk-2.0
`cygpath -w $GTK2/share/themes/MS-Windows/gtk-2.0`;root/share/themes/MS-Windows/gtk-2.0

   cd "$GTK2/bin" || exit
   for dll in *.dll; do
      echo "`cygpath -w $GTK2/bin/$dll`;root/$dll"
) >addlist

trap "/cygwin/bin/rm addlist" 0

/cygdrive/c/perl/bin/perl /perl/bin/pp -o test.exe -I lib -A addlist

This will add the required file 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:

use strict;
use warnings;

our $VERSION = '0.30';

    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";

        # if ($^O eq "MSWin32") {
        #     $ENV{GTK_RC_FILES} = "$ENV{PAR_TEMP}/share/themes/MS-Windows/gtk-2.0/gtkrc";
        # }

        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";


All this is all well and good, but it doesn’t actually work. I use glade to design the interface and Gtk2::GladeXML to render it. The packaged app will work fine until you try to hook up the events with the $gui->signal_autoconnect_from_package($self). Leave that command out and you have a beautifully packaged app (that doesn’t do anything). Add the line and kplow!

The included script and PAR::Kludge packages can downloaded here. If anyone figures out how to get this working, please let me know!


June 28, 2007 4:26AM



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