File Coverage

blib/lib/Wx/Perl/Packager.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             ###################################################################################
2             # Distribution Wx::Perl::Packager
3             # File Wx/Perl/Packager.pm
4             # Description: Assist packaging wxPerl applicatons
5             # File Revision: $Id: Packager.pm 48 2010-04-25 00:26:34Z $
6             # License: This program is free software; you can redistribute it and/or
7             # modify it under the same terms as Perl itself
8             # Copyright: Copyright (c) 2006 - 2010 Mark Dootson
9             ###################################################################################
10              
11             package Wx::Perl::Packager;
12 1     1   31183 use 5.008;
  1         5  
  1         101  
13 1     1   6 use strict;
  1         2  
  1         37  
14 1     1   5 use warnings;
  1         7  
  1         56  
15             require Exporter;
16 1     1   5 use base qw( Exporter );
  1         2  
  1         255  
17             our $VERSION = '0.27';
18 1     1   727 use Wx::Mini;
  0            
  0            
19              
20             our $_require_overwite = 0;
21             our $_debug_print_on = $ENV{WXPERLPACKAGER_DEBUGPRINT_ON} || 0;
22             our $handler;
23              
24             #-----------------------------------------------
25             # Flag to force some cleanup on MSW
26             #-----------------------------------------------
27              
28             $_require_overwite = 0;
29              
30             for (@ARGV) {
31             $_require_overwite = 1 if $_ eq '--force-overwrite-wx-libraries';
32             $_debug_print_on = 1 if $_ eq '--set-wx-perl-packager-debug-on';
33             }
34              
35             &_start;
36              
37             sub _start {
38             #-----------------------------------------------
39             # Main Handling
40             #-----------------------------------------------
41            
42             if ($^O =~ /^mswin/i) {
43             require Wx::Perl::Packager::MSWin;
44             $handler = Wx::Perl::Packager::MSWin->new;
45             } elsif($^O =~ /^linux/i) {
46             require Wx::Perl::Packager::Linux;
47             $handler = Wx::Perl::Packager::Linux->new;
48             } elsif($^O =~ /^darwin/i) {
49             require Wx::Perl::Packager::MacOSX;
50             $handler = Wx::Perl::Packager::MacOSX->new;
51             } else {
52             warn 'Wx::Perl:Packager is not implemented on this operating system';
53             }
54            
55             $handler->configure if $handler;
56            
57             $handler->post_configure if $handler;
58             }
59              
60             END {
61             my $mainthread = 1;
62             eval {
63             my $threadid = threads->tid();
64             $mainthread = ( $threadid ) ? 0 : 1;
65             print STDERR qq(Thread ID $threadid\n) if $_debug_print_on;
66             };
67             $handler->cleanup_on_exit if( $handler && $mainthread );
68             }
69              
70             #-----------------------------------------------
71             # Some utilities (retained for backwards compat)
72             #-----------------------------------------------
73              
74             sub runtime {
75             return $handler->get_config->get_runtime;
76             }
77              
78             sub packaged {
79             return $handler->get_config->get_packaged;
80             }
81              
82             sub get_wxpath {
83             return $handler->get_config->get_wx_load_path;
84             }
85              
86             sub get_wxlibraries {
87             my @libfiles = ();
88             return @libfiles if packaged();
89             my $libpath = get_wxpath();
90             if( $libpath && (-d $libpath) ) {
91             opendir(WXDIR, $libpath) or die qq(Could not open Wx Library Path : $libpath: $!);
92             my @files = grep { /\.(so|dll)$/ } readdir(WXDIR);
93             closedir(WXDIR);
94             for (@files) {
95             push( @libfiles, qq($libpath/$_) ) if($_ ne 'gdiplus.dll' );
96             }
97             }
98             return @libfiles;
99             }
100              
101             sub get_wxboundfiles {
102             my @libfiles = ();
103             return @libfiles if packaged();
104             my @files = get_wxlibraries();
105            
106             for (@files) {
107             my $filepath = $_;
108             my @vals = split(/[\\\/]/, $filepath);
109             my $filename = pop(@vals);
110            
111             push( @libfiles, { boundfile => $filename,
112             autoextract => 1,
113             file => $filepath,
114             }
115             );
116             }
117             return @libfiles;
118             }
119              
120              
121             =head1 NAME
122              
123             Wx::Perl::Packager
124              
125             =head1 VERSION
126              
127             Version 0.27
128              
129             =head1 SYNOPSIS
130              
131             For PerlApp/PDK and PAR
132            
133             At the start of your script ...
134            
135             #!/usr/bin/perl
136             use Wx::Perl::Packager;
137             use Wx;
138             .....
139            
140             or if you use threads with your application
141             #!/usr/bin/perl
142             use threads;
143             use threads::shared;
144             use Wx::Perl::Packager;
145             use Wx;
146              
147             =head1 Description
148              
149             Assist packaging wxPerl applications on Linux (GTK) and MSWin
150              
151             Wx::Perl::Packager must be loaded before any part of Wx so should appear at the
152             top of your main script. If you load any part of Wx in a BEGIN block, then you
153             must load Wx::Perl::Packager before it in your first BEGIN block. This may cause
154             you problems if you use threads within your Wx application. The threads
155             documentation advises against loading threads in a BEGIN block - so don't do it.
156              
157             =head1 For PerlApp on MS Windows
158              
159             putting Wx::Perl:Packager at the top of your script as described above may be
160             all that is required for recent versions of PerlApp. However, using an x64
161             64 bit version on PerlApp and 64 bit Wx PPMs, you may encounter a fault on exit
162             when closing the application. This will be apparant when testing the app. You can
163             work around this by binding the Wx.dll file as wxmain.dll. That is:
164            
165             bind somepath..../auto/Wx/Wx.dll
166             as
167             wxmain.dll
168            
169             This will fix this issue.
170            
171             Note that PerlApp 8.0 and greater may report incorrect msvcrtXX.dll dependencies
172             for the wxWidgets dll's. These errors can be ignored. The libraries link only
173             against the known msvcrt.dll and require no additional MSVCRTXX runtimes.
174            
175             Windows 2000
176            
177             Your distributed applications can run on Windows 2000, but you will have to include
178             the redistributable gdiplus.dll from Microsoft. Search MSDN for
179             'gdiplus redistributable'.
180             Once downloaded and extracted, you can simply bind the gdiplus.dll to your
181             PerlApp executable.
182            
183             =head1 For PerlApp on Linux
184              
185             if you are using the PPMs from http://www.wxperl.co.uk/repository ( add this
186             to your repository list), packaging with PerlApp is possible.
187            
188             You must add each wxWidgets dll that you use as a bound file.
189             e.g. /site/lib/Alien../wxbase28u_somename.so.0
190             should be bound simply as 'wxbase28u_somename.so.0' and should be
191             set to extract automatically.
192            
193             YOU MUST also bind /site/lib/auto/Wx/Wx.so as
194             'wxmain.so' alongside your wxwidgets modules. This is the current work around
195             for a segmentation fault when PerlApp exits. Hopefully there will be
196             a better solution soon.
197              
198             =head1 For PerlApp on MacOSX
199              
200             The Wx distribution available as a PPM from http://www.wxperl.co.uk/repository ( add this
201             to your repository list), can be packaged using PerlApp and Perl510
202            
203             For PerlApp packaging and testing, you must set the DYLD_LIBRARY_PATH to the wxWidgets
204             dylib files before running PerlApp. If you have installed PPMS and the PDK in default
205             locations, the two required commands will look like:
206            
207             export DYLD_LIBRARY_PATH=/Users/yourusername/Library/ActivePerl-5.10/lib/auto/Wx/wxPerl.app/Contents/Frameworks
208             /usr/bin/open "/Applications/ActiveState Perl Dev Kit/PerlApp.app"
209            
210             Creating and testing the app will work because you have set the DYLD_LIBRARY_PATH environment variable.
211            
212             Once you have finished working in PerlApp, you will have to make some additions to your created .app .
213            
214             If your new app is located at mydir/myapp.app, the necessary procedure is
215            
216             cd mydir.app/Contents
217             mkdir Frameworks
218             cp -p /Users/yourusername/Library/ActivePerl-5.10/lib/auto/Wx/wxPerl.app/Contents/Frameworks/* Frameworks
219            
220             and that should be it. Your app should now be distributable and run without the need for a DYLD_LIBRARY_PATH
221            
222             This works because the Wx .bundle files and wxWidgets dylib files in the PPM distribution are built to find
223             dependencies relative to the executable that loads them. If you already have a different packaging method that
224             relies on setting DYLD_LIBRARY_PATH at run time, then that too should work without problems.
225            
226             When run on some MacOSX version / architecture combinations (behaviour has been noted on a MacOSX 10.4 G4 ppc machine)
227             your PerlApp application may cause error dialogs on exit ("Application Quit Unexpectedly")
228            
229             You can fix this by binding the Wx.bundle file as wxmain.bundle. That is, bind
230             pathtoyourppminstall/site/lib/auto/Wx/Wx.bundle
231             as
232             wxmain.bundle
233            
234             You may wish to apply this fix to all your .app packages.
235            
236              
237             =head1 PerlApp General
238              
239             Wx::Perl::Packager does not support the --dyndll option for PerlApp.
240            
241             Wx::Perl::Packager does not support the --clean option for PerlApp
242            
243             Wx::Perl::Packager works with PerlApp by moving the following bound or included
244             wxWidgets files to a separate temp directory on MSWin and Linux (and Mac OSX
245             for wxmain.dylib).
246            
247             base
248             core
249             adv
250             mingwm10.dll if present for 32 bit executables
251             libgcc_s_sjlj-1.dll if present for 64 bit executables
252             gdiplus.dll if needed by OS.
253             wxmain.(dll|so.0|dylib)
254            
255             The name of the directory is created using the logged in username, and the full path
256             of the executable. This ensures that your application gets the correct Wx dlls whilst
257             also ensuring that only one permanent temp directory is ever created for a unique set
258             of wxWidgets DLLs
259            
260             All the wxWidgets dlls, mingwm10.dll and /or libgcc_s_sjlj-1.dll should be bound as 'dllname.dll'.
261             (i.e. not in subdirectories)
262              
263             =head1 For PAR
264              
265             PAR assistant
266            
267             run 'wxpar' exactly as you would run pp.
268            
269             e.g. wxpar --gui --icon=myicon.ico -o myprog.exe myscript.pl
270              
271             At the start of your script ...
272            
273             #!c:/path/to/perl.exe
274             use Wx::Perl::Packager;
275             use Wx;
276             .....
277            
278             or if you use threads with your application
279             #!c:/path/to/perl.exe
280             use threads;
281             use threads::shared;
282             use Wx::Perl::Packager;
283             use Wx
284            
285             Wx::Perl::Packager must be loaded before any part of Wx so should appear at the
286             top of your main script. If you load any part of Wx in a BEGIN block, then you
287             must load Wx::Perl::Packager before it in your first BEGIN block. This may cause
288             you problems if you use threads within your Wx application. The threads
289             documentation advises against loading threads in a BEGIN block - so don't do it.
290            
291             wxpar will accept a single named argument that allows you to define how the
292             wxWidgets libraries are named on GTK.
293             wxpar ordinarily packages the libraries as wxbase28u_somename.so
294             This will always work if using Wx::Perl::Packager.
295             However, it maybe that you don't want to use Wx::Perl::Packager, in which case
296             you need the correct extension.
297            
298             If you want librararies packaged as wxbase28u_somename.so.0, then pass the first
299             two arguments to wxpar as
300            
301             wxpar wxextension .0
302            
303             If you want wxbase28u_somename.so.0.6.0 , for example
304            
305             wxpar wxextension .0.6.0
306            
307             which would mean a full line something like
308            
309             wxpar wxextension .0.6.0 -o myprog.exe myscript.pl
310            
311             NOTE: the arguments must be FIRST and will break Wx::Perl::Packager (which should
312             not be needed in this case).
313            
314             OF COURSE - the symlinks must actually exist. :-)
315              
316             =head1 Nasty Internals
317              
318             As Commented in Wx:Perl::Packager::Linux the packager is configured with several
319             options. Mix and match if you think there's a better way.
320            
321             $self->set_so_module_suffix(''); # different linux dists symlink the .so libraries differently
322             # BAH. the loaders in Wx::Perl::Packager will look for
323             # modules ending in '.so' - If your modules get packaged
324             # differently, put the suffix here.
325             # e.g. if your module when packaged is
326             # wxlibs_gcc_base.so.0.6.0
327             # you should $self->set_so_module_suffix('.0.6.0')
328            
329             $self->set_relocate_pdkcheck(0); # relocate the Wx dlls during PDK Check - never necessary it seems
330            
331             $self->set_relocate_packaged(1); # relocate the Wx Dlls when running as PerlApp
332            
333             $self->set_relocate_wx_main(1); # if set_relocate_packaged is true and we find 'wxmain.so'
334             # as a bound file, we load it as Wx.so ( which it should be
335             # if user as bound it). This is the current fix for PerlApp
336             # segmentation fault on exit in Linux. Makes no difference
337             # in MSWin
338            
339             $self->set_unlink_relocated(1); # delete the extracted files - ensures relocated are loaded
340            
341             $self->set_loadmode_pdkcheck('packload'); # standard | nullsub | packload during pdkcheck
342             # standard uses normal Wx loading
343             # nullsub - no extensions are loaded
344             # packload - extensions are loaded by Wx::Perl::Packager
345              
346             $self->set_loadmode_packaged('packload');# as above, when running as PerlApp
347            
348             $self->set_loadcore_pdkcheck(1); # use DynaLoader to load wx modules listed by
349             # get_core_modules method (below)during pdkcheck
350            
351             $self->set_loadcore_packaged(1); # as above, when running as PerlApp
352            
353             $self->set_unload_loaded_core(1);# unload any librefs we loaded
354             # (uses DynaLoader in an END block )
355            
356             $self->set_unload_loaded_plugins(1); # unload plugins ( html, stc, gl .. etc) that are
357             # loaded via 'packload'. This seems to be necessary
358             # to ensure correct unloading order.
359             # Note - plugins are loaded using
360             # Wx::_load_plugin (not DynaLoader);
361            
362             $self->set_pdkcheck_exit(1); # because of the current seg fault on exit in linux
363             # you can't package using PerlApp
364             # this setting calls 'exit(0)' after
365             # Wx has loaded.
366             # Drastic - but it is the current hack for this failure on linux
367              
368             =head1 Packaging Test Script
369              
370             There is a test script at Wx/Perl/Packager/resource/packtest.pl that you can
371             use to test your packaging method. (i.e. package it and check if it runs);
372              
373             =head1 Methods
374              
375             =item Wx::Perl::Packager::runtime()
376              
377             returns PERLAPP, PARLEXE, or PERL to indicate how the script was executed.
378             (Under PerlApp, pp packaged PAR, or as a Perl script.
379              
380             my $env = Wx::Perl::Packager::runtime();
381              
382             =item Wx::Perl::Packager::packaged()
383              
384             returns 1 or 0 (for true / false ) to indicate if script is running packaged or as
385             a Perl script.
386              
387             my $packaged = Wx::Perl::Packager::packaged();
388              
389             =item Wx::Perl::Packager::get_wxpath()
390              
391             returns the path to the directory where wxWidgets library modules are stored.
392             Only useful when packaging a script.
393              
394             my $wxpath = Wx::Perl::Packager::get_wxpath();
395              
396             =item Wx::Perl::Packager::get_wxboundfiles()
397              
398             returns a list of hashrefs where the key value pairs are:
399            
400             boundfile => the relative name of the file when bound (e.g myfile.dll)
401             file => the source file on disc
402             autoextract => 0/1 should the file be extracted on startup
403            
404             Only useful when packaging a script. If called within a packaged script,
405             returns an empty list. In addition to the wxWidgets dlls, this function
406             will also return the external and required bound location of the
407             gdiplus.dll if present in Alien::wxWidgets. If bound to the packaged
408             executable at the required location, Wx::Perl::Packager will ensure that
409             gdiplus.dll is on the path if your packaged executable is run on an
410             operating system that requires it.
411            
412             my %wxlibs = Wx::Perl::Packager::get_wxboundfiles();
413              
414             =item Wx::Perl::Packager::get_wxlibraries()
415              
416             This function is deprecated. Use get_wxboundfiles() instead.
417            
418             returns a list of the full path names of all wxWidgets library modules.
419             Only useful when packaging a script. If called within a packaged script,
420             returns an empty list.
421            
422             Use Wx::Perl::Packager::get_wxlibraries();
423             my @wxlibs = Wx::Perl::Packager::get_wxlibraries();
424              
425              
426             =head1 AUTHOR
427              
428             Mark Dootson, C<< >>
429              
430             =head1 DOCUMENTATION
431              
432             You can find documentation for this module with the perldoc command.
433              
434             perldoc Wx::Perl::Packager
435              
436             =head1 ACKNOWLEDGEMENTS
437              
438             Mattia Barbon for wxPerl.
439              
440             =head1 COPYRIGHT & LICENSE
441              
442             Copyright 2006 - 2010 Mark Dootson, all rights reserved.
443              
444             This program is free software; you can redistribute it and/or modify it
445             under the same terms as Perl itself.
446              
447             =cut
448              
449             1;
450              
451             # End of Wx::Perl::Packager
452              
453             __END__