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.)
#!/bin/sh
# 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: http://data.plan9.de/ppwin
# 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
GTK2="/cygdrive/c/Progra~1/Common~1/Gtk/2.0"
(
cat <<EOF
c:\Perl\site\lib\auto\Cairo\Cairo.dll;root/Cairo.dll
c:\Perl\site\lib\auto\Glib\Glib.dll;root/Glib.dll
c:\Perl\site\lib\auto\Gtk2\Gtk2.dll;root/Gtk2.dll
# 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
EOF
cd "$GTK2/bin" || exit
for dll in *.dll; do
echo "`cygpath -w $GTK2/bin/$dll`;root/$dll"
done
) >addlist
trap "/cygwin/bin/rm addlist" 0
PATH=/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/perl/bin
/cygdrive/c/perl/bin/perl /perl/bin/pp -o test.exe -I lib -A addlist test.pl
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: 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";
}
}
# 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";
}
}
1;
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!
The contents of this blog are licensed under the Creative Commons “Attribution-Noncommercial-Share Alike 3.0″ license.