ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Perl-LibExtractor/bin/perl-libextractor
Revision: 1.7
Committed: Mon Sep 23 07:57:55 2013 UTC (13 years ago) by root
Branch: MAIN
Changes since 1.6: +3 -2 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #!/opt/bin/perl
2    
3     =head1 NAME
4    
5     perl-libextractor - determine perl library subsets for building distributions
6    
7     =head1 SYNOPSIS
8    
9     perl-libextractor ...
10    
11     General Options:
12    
13     -v verbose
14     --version display version
15     -I path prepend path to @INC
16     --no-packlists do not use packlists
17    
18     Selection:
19    
20     -Mmodule load and trace module
21     --script progname add executable script
22     --eval | -e str trace execution of perl string
23     --perl add perl interpreter itself
24     --core-support add core support
25     --unicore add unicore database
26     --core add perl core library
27     --glob glob add library files select by glob
28     --filter pat,... apply include/exclude patterns
29 root 1.3 --runtime-only remove files not needed for execution
30 root 1.1
31     Modes:
32    
33     --list list source and destination paths
34    
35     --dstlist list destination paths
36    
37     --srclist list source paths
38    
39     --copy path copy files to a target path
40 root 1.5 --bindir path perl executable target ("exe")
41     --dlldir path shared library target ("dll")
42     --scriptdir path executable script target ("bin")
43     --libdir path perl library target ("lib")
44 root 1.1 --strip strip .pl and .pm files
45     --cache-dir path cache directory to use
46     --binstrip "..." strip binaries and dlls
47    
48     =head1 DESCRIPTION
49    
50     This program can be used to extract a subset of your perl installation,
51     with the intention of building software distributions. Or in other words,
52     this module finds all files necessary to run a perl program (library
53     files, perl executable, scripts).
54    
55     The resulting set can then be displayed or copied to another directory,
56     while optionally stripping the perl sources to make them smaller.
57    
58     =head2 OPTIONS
59    
60     This manpage gives only rudimentary documentation for options that have an
61     equivalent in L<Perl::LibExtractor>, so look there for details.
62    
63     Options are not processed in order specified on the commandline, but in
64     multiple phases (e.g., C<-I> gets executed before any C<-M> option).
65    
66     =head3 GENERAL OPTIONS
67    
68     These options configure basic settings.
69    
70     =over 4
71    
72     =item C<--verbose>
73    
74     =item C<-v>
75    
76     Increases verbosity - highly recommended for interactive use.
77    
78     =item C<--version>
79    
80     Display the version of L<Perl::LibExtractor>.
81    
82     =item C<-I> I<path>
83    
84     Prepends the given path to C<@INC> when searching perl library directories
85     (the last C<-I> option is prepended first).
86    
87 root 1.2 =item C<--no-packlists>
88    
89     Packlists allow to package all of a distribution, including resource files
90     not found through the normal tracing mechanism. This option disaables use
91     of packlists (normally highly recommended).
92    
93     Some especially broken perls (Debian GNU/Linux...) have missing files,
94     so this option doesn't work with them, at least not for any packages
95     distributed by debian (packages installed through CPAN or any other
96     non-dpkg-mechanism work fine).
97    
98 root 1.1 =back
99    
100     =head3 SELECTION
101    
102     These options specify and modify module selections. They are executed in
103     the order stated on the commandline, and when in doubt, you should use
104     them in the order documented here.
105    
106     =over 4
107    
108     =item C<-M>I<module>
109    
110     Load the named module and trace direct dependencies
111     (e.g. F<-MCarp>). Same as C<add_mod> in L<Perl::LibExtractor>.
112    
113     =item C<--script> I<progname>
114    
115     Compile the (installed) script I<progname> and trace dependencies
116     (e.g. F<corelist>). Same as C<add_bin> in L<Perl::LibExtractor>.
117    
118     =item C<--eval> I<string>
119    
120     =item C<-e str> I<string>
121    
122     Compile and execute the givne perl code, and trace dependencies (e.g. F<-e
123     "use AnyEvent; AnyEvent::detect">). Same as C<add_eval> in L<Perl::LibExtractor>.
124    
125     =item C<--perl>
126    
127     Adds the perl interpreter itself, including libperl if required to run
128     perl. Same as C<add_perl> in L<Perl::LibExtractor>.
129    
130     =item C<--core-support>
131    
132     Add all support files needed to support built-in features of perl (such
133     as C<ucfirst>), which is usually the minimum you should add from the core
134     library. Same as C<add_core_support> in L<Perl::LibExtractor>.
135    
136     =item C<--unicore>
137    
138     Add the whole unicore database, which is big, contains many, many files
139     and is usually not needed to run a program. Same as C<add_unicore> in
140     L<Perl::LibExtractor>.
141    
142     =item C<--core>
143    
144     Add the complete perl core library, which includes everything added
145     by F<--core-support> and F<--unicore>. Same as C<add_core> in
146     L<Perl::LibExtractor>.
147    
148 root 1.2 Some especially broken perls (Debian GNU/Linux...) have missing files, so
149     this option doesn't work with them.
150    
151 root 1.1 =item C<--glob glob>
152    
153 root 1.7 Add all files from the perl library directories that match the given
154 root 1.1 extended glob pattern. Same as C<add_glob> in L<Perl::LibExtractor>, also
155     see there for the syntax of glob patterns.
156    
157     Example: add AnyEvent.pm and all AnyEvent::xxx modules installed.
158    
159     --glob Coro --glob "Coro::*"
160    
161     =item C<--filter pat,...>
162    
163     Apply a comma-separated series of extended glob patterns, prefixed by
164     C<+> (include) or C<-> (for exclude patterns). Same as C<filter> in
165     L<Perl::LibExtractor>, also see there for exact semantics and syntax.
166    
167     Example: remove all F<*.al> files in F<auto/POSIX>, except F<memset.al>.
168    
169     --filter "+/lib/auto/POSIX/memset.al,-/lib/auto/POSIX/*.al"
170    
171     =item C<--runtime-only>
172    
173 root 1.3 Remove all files not needed to run any scripts, such as debug info
174 root 1.1 files, link libraries, pod files and so on. Same as C<runtime_only> in
175     L<Perl::LibExtractor>.
176    
177     =back
178    
179     =head3 MODES
180    
181 root 1.4 These options select a specific work mode. Work modes might have specific
182 root 1.1 options to control them further.
183    
184     =over 4
185    
186     =item C<--list>
187    
188     Lists all selected files in two columns, first column is destination path,
189     second column is source path and first line is a header line.
190    
191     =item C<--dstlist>
192    
193     Same as C<--list>, but only list destination paths and has no header -
194     intended for scripts.
195    
196     =item C<--srclist>
197    
198     Same as C<--list>, but only list source paths and has no header -
199     intended for scripts.
200    
201     =item C<--copy> I<path>
202    
203     Copy all selected files to the respective position under the directory
204     I<path> - previous contents of the directory will be list.
205    
206     This mode has the following suboptions:
207    
208     =over 4
209    
210 root 1.5 =item C<--exedir> I<path>
211    
212     Specifies the subdirectory for binary executables (the perl interpreter itself), instead of
213     the default F<exe/>.
214    
215     =item C<--dlldir> I<path>
216    
217     Specifies the subdirectory for shared libraries, instead of
218     the default F<dll/>.
219    
220     =item C<--bindir> I<path>
221    
222     Specifies the subdirectry for perl scripts, instead of
223     the default F<bin/>.
224    
225     =item C<--libdir> I<path>
226    
227     Specifies the subdirectory for perl library files, instead of
228     the default F<lib/>.
229    
230 root 1.1 =item C<--strip>
231    
232     Strip all C<.pm>, C<.pl>, C<.al> files and perl executables, which
233     mostly means removal of unecessary whitespace and documentation - see
234     L<Perl::Strip> which is used.
235    
236     =item C<--cache-dir> I<path>
237    
238 root 1.3 Specify the cache dir to use - the default is F<~/.cache/perlstrip> for
239     cached stripped perl files (compatible to the C<perlstrip> program).
240 root 1.1
241     =item C<--binstrip> I<"...">
242    
243     Use the specified program and arguments to strip executables, shared libraries and shared objects.
244    
245     This is only necessary when your programs were compiled with debugging
246     info, but can be used to specify extra treatment for all binary files.
247    
248     =back
249    
250     =back
251    
252     =head1 EXAMPLE
253    
254 root 1.6 This is how the Deliantra client (L<http://www.deliantra.,net>) is being packages:
255 root 1.1
256 root 1.6 perl-libextractor \
257     --perl --core-support --script deliantra \
258     --runtime-only \
259     --copy distdir --strip --exedir . --dlldir . --bindir pm/bin --libdir pm \
260    
261     The first line of arguments adds perl, support for core functions (the
262     Deliantra client does need the full unicode database or perl core) and
263     tells F<perl-libextractor> to parse the installed F<deliantra> script and
264     trace all it's dependencies. The script is installed by installed the
265     C<Deliantra::Client> module from CPAN.
266    
267     This finds all required perl dependencies.
268    
269     The second line of arguments (F<--runtime-only>) then removes all files
270     not required for execution, slimming down the distribution.
271    
272     The last line tells F<perl-libextractor> to copy the resulting files to
273     the directory F<distdir>. The argument F<--strip> tells it to stirp all perl sources
274     (make them smaller by removing whitespace, comments and documentation, which saves about a megabyte).
275    
276     The remaining arguments override the default subdirectories for the files,
277     as L<Urlader>, which is used for the binary distribution, works best if
278     dll's and executables are in the top dir.
279    
280     After this, the script that builds the distribution does a lot more, for
281     example finding shared libraries (such as pango, SDL and so on), renaming
282     them on OS X to avoid the severe DLL Hell on that platform, and provides
283     a wrapper script that initialises perl so it loads its files from the
284     distribution dir and doesn't try to search anything anywhere else.
285    
286     On GNU/Linux, the binaries and libraries are also patched to remove any
287     rpath that Debian might have compiled in and that would keep perl from
288     ignoring C<LD_LIBRARY_PATH>.
289    
290     The wrapper script is called C<run>, and looks a bit like this:
291 root 1.1
292     @INC = ("pm", "."); # "." required by newer AutoLoader grrrr.
293     $ENV{PANGO_RC_FILE} = "pango.rc";
294     require "bin/deliantra";
295     exit 0;
296    
297 root 1.6 The most important line is the first one, which tells F<perl> where to
298     look for library files.
299    
300 root 1.1 =head1 SEE ALSO
301    
302 root 1.6 L<App::Staticperl>, L<Urlader>, L<Perl::Strip>.
303 root 1.1
304     =head1 AUTHOR
305    
306     Marc Lehmann <schmorp@schmorp.de>
307     http://software.schmorp.de/pkg/staticperl.html
308    
309     =cut
310    
311     use common::sense;
312    
313     use Getopt::Long;
314     use List::Util ();
315 root 1.3 use File::Path ();
316     use File::Basename ();
317     use File::Copy ();
318 root 1.1
319     use Perl::LibExtractor;
320     use Perl::Strip;
321    
322     our @INC;
323    
324     my $USE_PACKLISTS = 1;
325     my $VERBOSE;
326    
327     my $STRIP;
328     my $BINSTRIP;
329     my $CACHE;
330     my $CACHEDIR;
331    
332     my %DIR = qw(exe exe dll dll bin bin lib lib);
333    
334     $|=1;
335    
336     sub usage {
337     require Pod::Usage;
338    
339     Pod::Usage::pod2usage (-output => *STDOUT, -verbose => 1, -exitval => 1, -noperldoc => 1);
340     }
341    
342     @ARGV
343     or usage;
344    
345     Getopt::Long::Configure ("bundling", "no_auto_abbrev", "no_ignore_case");
346    
347     my $ex;
348     my $set;
349     my (@phase0, @phase1, @phase2);
350    
351     GetOptions
352 root 1.3 "verbose|v" => sub { ++$VERBOSE },
353 root 1.1 "version" => sub {
354     warn "This is perl-libextractor version $Perl::LibExtractor::VERSION\n";
355     },
356    
357     "exedir=s" => \$DIR{exe},
358     "dlldir=s" => \$DIR{dll},
359     "bindir=s" => \$DIR{bin},
360     "libdir=s" => \$DIR{lib},
361    
362     "I=s" => sub {
363     my $arg = $_[1];
364     unshift @phase0, sub { unshift @INC, $arg };
365     },
366     "no-packlists" => sub { $USE_PACKLISTS = 0 },
367    
368     "M=s" => sub {
369     my $arg = $_[1];
370     push @phase1, sub { $ex->add_mod ($arg) };
371     },
372     "script=s" => sub {
373     my $arg = $_[1];
374     push @phase1, sub { $ex->add_bin ($arg) };
375     },
376     "eval|e=s" => sub {
377     my $arg = $_[1];
378     push @phase1, sub { $ex->add_eval ($arg) };
379     },
380     "perl" => sub {
381     push @phase1, sub { $ex->add_perl };
382     },
383     "core-support" => sub {
384     push @phase1, sub { $ex->add_core_support };
385     },
386     "unicore" => sub {
387     push @phase1, sub { $ex->add_unicore };
388     },
389     "core" => sub {
390     push @phase1, sub { $ex->add_core };
391     },
392     "glob=s" => sub {
393     my $arg = $_[1];
394     push @phase1, sub { $ex->add_glob ($arg) };
395     },
396     "filter=s" => sub {
397     my $arg = $_[1];
398     push @phase1, sub { $ex->filter (split /,/, $arg) };
399     },
400     "runtime-only" => sub {
401     push @phase1, sub { $ex->runtime_only };
402     },
403    
404     "list" => sub {
405     push @phase2, \&mode_list;
406     },
407     "dstlist" => sub {
408     push @phase2, \&mode_dstlist;
409     },
410     "srclist" => sub {
411     push @phase2, \&mode_srclist;
412     },
413     "copy=s" => sub {
414     my $arg = $_[1];
415     push @phase2, sub { &mode_copy ($arg) };
416     },
417    
418     "strip" => \$STRIP,
419     "cache-dir=s" => \$CACHEDIR,
420     "binstrip=s" => \$BINSTRIP,
421    
422 root 1.3 or die "try $0 --help\n";
423 root 1.1
424     @phase2
425     or usage;
426    
427 root 1.3 # for strip_copy
428     my $STRIPPER = do {
429     my @cache;
430    
431     unless (defined $CACHEDIR) {
432     mkdir "$ENV{HOME}/.cache";
433     $CACHEDIR = "$ENV{HOME}/.cache/perlstrip";
434     }
435    
436     new Perl::Strip cache => $CACHEDIR, optimise_size => 1
437     };
438    
439     sub strip_copy($$) {
440     my ($src, $dst) = @_;
441    
442     my $text = do {
443     open my $fh, "<:perlio", $src
444     or die "$src: $!\n";
445    
446     local $/;
447     <$fh>
448     };
449    
450     printf "$dst: %d ", length $text if $VERBOSE >= 2;
451    
452     $text = $STRIPPER->strip ($text);
453    
454     printf "to %d bytes... ", length $text if $VERBOSE >= 2;
455    
456     open my $fh, ">:perlio", $dst
457     or die "$dst: $!\n";
458     length $text == syswrite $fh, $text
459     or die "$dst: $!\n";
460     close $fh;
461    
462     print "ok\n" if $VERBOSE >= 2;
463     }
464    
465 root 1.1 sub mode_list {
466     my @keys = sort keys %$set;
467     my $width = List::Util::max map length, @keys;
468    
469     printf "%-*.*s %s\n", $width, $width, "SRC", "DST";
470     for (@keys) {
471     printf "%-*.*s %s\n", $width, $width, $_, $set->{$_}[0];
472     }
473     }
474    
475     sub mode_dstlist {
476     print map "$_\n", sort keys %$set;
477     }
478    
479     sub mode_srclist {
480     print map "$set->{$_}[0]\n", sort keys %$set;
481     }
482    
483     sub mode_copy {
484 root 1.3 my $dst = shift;
485     print "deleting $dst.\n" if $VERBOSE;
486     File::Path::rmtree $dst, $VERBOSE >= 2, 0;
487    
488     print "populating $dst...\n" if $VERBOSE;
489    
490     my %mkdir;
491    
492     while (my ($path, $info) = each %$set) {
493     $path =~ m%^([^/]+)(.*)/([^/]+)$%
494     or die "$path: malformed destination path, please report.\n";
495    
496     my ($p1, $p2, $f) = ($1, $2, $3);
497    
498     my $dstdir = "$dst/$DIR{$p1}$p2";
499    
500     File::Path::mkpath $dstdir, $VERBOSE >= 2, 0777
501     unless $mkdir{$dstdir}++;
502    
503     my $src = $info->[0];
504    
505     if (
506     $STRIP
507     && ($f =~ /\.(?:pm|pl|ix|al)$/
508     || $p1 eq "bin")
509     ) {
510     strip_copy $src, "$dstdir/$f";
511    
512     } else {
513     File::Copy::cp $src, "$dstdir/$f"
514     or die "$src => $dstdir/$f: $!";
515    
516     if (
517 root 1.4 $f =~ /\.(?:bundle|dyld|so|dll|sl)$/ # TODO
518     || $p1 eq "exe"
519     || $p1 eq "dll"
520 root 1.3 ) {
521 root 1.4 if (defined $BINSTRIP) {
522     system "$BINSTRIP \Q$dstdir/$f";
523     }
524    
525     chmod 0777 & ~umask, "$dstdir/$f";
526 root 1.3 }
527     }
528     }
529 root 1.1 }
530    
531 root 1.7 $_->() for @phase0;
532    
533 root 1.1 $ex = new Perl::LibExtractor use_packlists => $USE_PACKLISTS;
534    
535     $_->() for @phase1;
536    
537     $set = $ex->set;
538    
539     $_->() for @phase2;