ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Perl-LibExtractor/bin/perl-libextractor
Revision: 1.8
Committed: Mon Sep 23 13:03:48 2013 UTC (12 years, 11 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.7: +4 -0 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 root 1.8 The program should be installed in one of the standard paths for perl
119     programs - C<$Config{sitebin}>, C<$Config{vendorbin}> or C<$Config{bin}>,
120     or must be specified via an absolute path (starting with F</>).
121    
122 root 1.1 =item C<--eval> I<string>
123    
124     =item C<-e str> I<string>
125    
126     Compile and execute the givne perl code, and trace dependencies (e.g. F<-e
127     "use AnyEvent; AnyEvent::detect">). Same as C<add_eval> in L<Perl::LibExtractor>.
128    
129     =item C<--perl>
130    
131     Adds the perl interpreter itself, including libperl if required to run
132     perl. Same as C<add_perl> in L<Perl::LibExtractor>.
133    
134     =item C<--core-support>
135    
136     Add all support files needed to support built-in features of perl (such
137     as C<ucfirst>), which is usually the minimum you should add from the core
138     library. Same as C<add_core_support> in L<Perl::LibExtractor>.
139    
140     =item C<--unicore>
141    
142     Add the whole unicore database, which is big, contains many, many files
143     and is usually not needed to run a program. Same as C<add_unicore> in
144     L<Perl::LibExtractor>.
145    
146     =item C<--core>
147    
148     Add the complete perl core library, which includes everything added
149     by F<--core-support> and F<--unicore>. Same as C<add_core> in
150     L<Perl::LibExtractor>.
151    
152 root 1.2 Some especially broken perls (Debian GNU/Linux...) have missing files, so
153     this option doesn't work with them.
154    
155 root 1.1 =item C<--glob glob>
156    
157 root 1.7 Add all files from the perl library directories that match the given
158 root 1.1 extended glob pattern. Same as C<add_glob> in L<Perl::LibExtractor>, also
159     see there for the syntax of glob patterns.
160    
161     Example: add AnyEvent.pm and all AnyEvent::xxx modules installed.
162    
163     --glob Coro --glob "Coro::*"
164    
165     =item C<--filter pat,...>
166    
167     Apply a comma-separated series of extended glob patterns, prefixed by
168     C<+> (include) or C<-> (for exclude patterns). Same as C<filter> in
169     L<Perl::LibExtractor>, also see there for exact semantics and syntax.
170    
171     Example: remove all F<*.al> files in F<auto/POSIX>, except F<memset.al>.
172    
173     --filter "+/lib/auto/POSIX/memset.al,-/lib/auto/POSIX/*.al"
174    
175     =item C<--runtime-only>
176    
177 root 1.3 Remove all files not needed to run any scripts, such as debug info
178 root 1.1 files, link libraries, pod files and so on. Same as C<runtime_only> in
179     L<Perl::LibExtractor>.
180    
181     =back
182    
183     =head3 MODES
184    
185 root 1.4 These options select a specific work mode. Work modes might have specific
186 root 1.1 options to control them further.
187    
188     =over 4
189    
190     =item C<--list>
191    
192     Lists all selected files in two columns, first column is destination path,
193     second column is source path and first line is a header line.
194    
195     =item C<--dstlist>
196    
197     Same as C<--list>, but only list destination paths and has no header -
198     intended for scripts.
199    
200     =item C<--srclist>
201    
202     Same as C<--list>, but only list source paths and has no header -
203     intended for scripts.
204    
205     =item C<--copy> I<path>
206    
207     Copy all selected files to the respective position under the directory
208     I<path> - previous contents of the directory will be list.
209    
210     This mode has the following suboptions:
211    
212     =over 4
213    
214 root 1.5 =item C<--exedir> I<path>
215    
216     Specifies the subdirectory for binary executables (the perl interpreter itself), instead of
217     the default F<exe/>.
218    
219     =item C<--dlldir> I<path>
220    
221     Specifies the subdirectory for shared libraries, instead of
222     the default F<dll/>.
223    
224     =item C<--bindir> I<path>
225    
226     Specifies the subdirectry for perl scripts, instead of
227     the default F<bin/>.
228    
229     =item C<--libdir> I<path>
230    
231     Specifies the subdirectory for perl library files, instead of
232     the default F<lib/>.
233    
234 root 1.1 =item C<--strip>
235    
236     Strip all C<.pm>, C<.pl>, C<.al> files and perl executables, which
237     mostly means removal of unecessary whitespace and documentation - see
238     L<Perl::Strip> which is used.
239    
240     =item C<--cache-dir> I<path>
241    
242 root 1.3 Specify the cache dir to use - the default is F<~/.cache/perlstrip> for
243     cached stripped perl files (compatible to the C<perlstrip> program).
244 root 1.1
245     =item C<--binstrip> I<"...">
246    
247     Use the specified program and arguments to strip executables, shared libraries and shared objects.
248    
249     This is only necessary when your programs were compiled with debugging
250     info, but can be used to specify extra treatment for all binary files.
251    
252     =back
253    
254     =back
255    
256     =head1 EXAMPLE
257    
258 root 1.6 This is how the Deliantra client (L<http://www.deliantra.,net>) is being packages:
259 root 1.1
260 root 1.6 perl-libextractor \
261     --perl --core-support --script deliantra \
262     --runtime-only \
263     --copy distdir --strip --exedir . --dlldir . --bindir pm/bin --libdir pm \
264    
265     The first line of arguments adds perl, support for core functions (the
266     Deliantra client does need the full unicode database or perl core) and
267     tells F<perl-libextractor> to parse the installed F<deliantra> script and
268     trace all it's dependencies. The script is installed by installed the
269     C<Deliantra::Client> module from CPAN.
270    
271     This finds all required perl dependencies.
272    
273     The second line of arguments (F<--runtime-only>) then removes all files
274     not required for execution, slimming down the distribution.
275    
276     The last line tells F<perl-libextractor> to copy the resulting files to
277     the directory F<distdir>. The argument F<--strip> tells it to stirp all perl sources
278     (make them smaller by removing whitespace, comments and documentation, which saves about a megabyte).
279    
280     The remaining arguments override the default subdirectories for the files,
281     as L<Urlader>, which is used for the binary distribution, works best if
282     dll's and executables are in the top dir.
283    
284     After this, the script that builds the distribution does a lot more, for
285     example finding shared libraries (such as pango, SDL and so on), renaming
286     them on OS X to avoid the severe DLL Hell on that platform, and provides
287     a wrapper script that initialises perl so it loads its files from the
288     distribution dir and doesn't try to search anything anywhere else.
289    
290     On GNU/Linux, the binaries and libraries are also patched to remove any
291     rpath that Debian might have compiled in and that would keep perl from
292     ignoring C<LD_LIBRARY_PATH>.
293    
294     The wrapper script is called C<run>, and looks a bit like this:
295 root 1.1
296     @INC = ("pm", "."); # "." required by newer AutoLoader grrrr.
297     $ENV{PANGO_RC_FILE} = "pango.rc";
298     require "bin/deliantra";
299     exit 0;
300    
301 root 1.6 The most important line is the first one, which tells F<perl> where to
302     look for library files.
303    
304 root 1.1 =head1 SEE ALSO
305    
306 root 1.6 L<App::Staticperl>, L<Urlader>, L<Perl::Strip>.
307 root 1.1
308     =head1 AUTHOR
309    
310     Marc Lehmann <schmorp@schmorp.de>
311     http://software.schmorp.de/pkg/staticperl.html
312    
313     =cut
314    
315     use common::sense;
316    
317     use Getopt::Long;
318     use List::Util ();
319 root 1.3 use File::Path ();
320     use File::Basename ();
321     use File::Copy ();
322 root 1.1
323     use Perl::LibExtractor;
324     use Perl::Strip;
325    
326     our @INC;
327    
328     my $USE_PACKLISTS = 1;
329     my $VERBOSE;
330    
331     my $STRIP;
332     my $BINSTRIP;
333     my $CACHE;
334     my $CACHEDIR;
335    
336     my %DIR = qw(exe exe dll dll bin bin lib lib);
337    
338     $|=1;
339    
340     sub usage {
341     require Pod::Usage;
342    
343     Pod::Usage::pod2usage (-output => *STDOUT, -verbose => 1, -exitval => 1, -noperldoc => 1);
344     }
345    
346     @ARGV
347     or usage;
348    
349     Getopt::Long::Configure ("bundling", "no_auto_abbrev", "no_ignore_case");
350    
351     my $ex;
352     my $set;
353     my (@phase0, @phase1, @phase2);
354    
355     GetOptions
356 root 1.3 "verbose|v" => sub { ++$VERBOSE },
357 root 1.1 "version" => sub {
358     warn "This is perl-libextractor version $Perl::LibExtractor::VERSION\n";
359     },
360    
361     "exedir=s" => \$DIR{exe},
362     "dlldir=s" => \$DIR{dll},
363     "bindir=s" => \$DIR{bin},
364     "libdir=s" => \$DIR{lib},
365    
366     "I=s" => sub {
367     my $arg = $_[1];
368     unshift @phase0, sub { unshift @INC, $arg };
369     },
370     "no-packlists" => sub { $USE_PACKLISTS = 0 },
371    
372     "M=s" => sub {
373     my $arg = $_[1];
374     push @phase1, sub { $ex->add_mod ($arg) };
375     },
376     "script=s" => sub {
377     my $arg = $_[1];
378     push @phase1, sub { $ex->add_bin ($arg) };
379     },
380     "eval|e=s" => sub {
381     my $arg = $_[1];
382     push @phase1, sub { $ex->add_eval ($arg) };
383     },
384     "perl" => sub {
385     push @phase1, sub { $ex->add_perl };
386     },
387     "core-support" => sub {
388     push @phase1, sub { $ex->add_core_support };
389     },
390     "unicore" => sub {
391     push @phase1, sub { $ex->add_unicore };
392     },
393     "core" => sub {
394     push @phase1, sub { $ex->add_core };
395     },
396     "glob=s" => sub {
397     my $arg = $_[1];
398     push @phase1, sub { $ex->add_glob ($arg) };
399     },
400     "filter=s" => sub {
401     my $arg = $_[1];
402     push @phase1, sub { $ex->filter (split /,/, $arg) };
403     },
404     "runtime-only" => sub {
405     push @phase1, sub { $ex->runtime_only };
406     },
407    
408     "list" => sub {
409     push @phase2, \&mode_list;
410     },
411     "dstlist" => sub {
412     push @phase2, \&mode_dstlist;
413     },
414     "srclist" => sub {
415     push @phase2, \&mode_srclist;
416     },
417     "copy=s" => sub {
418     my $arg = $_[1];
419     push @phase2, sub { &mode_copy ($arg) };
420     },
421    
422     "strip" => \$STRIP,
423     "cache-dir=s" => \$CACHEDIR,
424     "binstrip=s" => \$BINSTRIP,
425    
426 root 1.3 or die "try $0 --help\n";
427 root 1.1
428     @phase2
429     or usage;
430    
431 root 1.3 # for strip_copy
432     my $STRIPPER = do {
433     my @cache;
434    
435     unless (defined $CACHEDIR) {
436     mkdir "$ENV{HOME}/.cache";
437     $CACHEDIR = "$ENV{HOME}/.cache/perlstrip";
438     }
439    
440     new Perl::Strip cache => $CACHEDIR, optimise_size => 1
441     };
442    
443     sub strip_copy($$) {
444     my ($src, $dst) = @_;
445    
446     my $text = do {
447     open my $fh, "<:perlio", $src
448     or die "$src: $!\n";
449    
450     local $/;
451     <$fh>
452     };
453    
454     printf "$dst: %d ", length $text if $VERBOSE >= 2;
455    
456     $text = $STRIPPER->strip ($text);
457    
458     printf "to %d bytes... ", length $text if $VERBOSE >= 2;
459    
460     open my $fh, ">:perlio", $dst
461     or die "$dst: $!\n";
462     length $text == syswrite $fh, $text
463     or die "$dst: $!\n";
464     close $fh;
465    
466     print "ok\n" if $VERBOSE >= 2;
467     }
468    
469 root 1.1 sub mode_list {
470     my @keys = sort keys %$set;
471     my $width = List::Util::max map length, @keys;
472    
473     printf "%-*.*s %s\n", $width, $width, "SRC", "DST";
474     for (@keys) {
475     printf "%-*.*s %s\n", $width, $width, $_, $set->{$_}[0];
476     }
477     }
478    
479     sub mode_dstlist {
480     print map "$_\n", sort keys %$set;
481     }
482    
483     sub mode_srclist {
484     print map "$set->{$_}[0]\n", sort keys %$set;
485     }
486    
487     sub mode_copy {
488 root 1.3 my $dst = shift;
489     print "deleting $dst.\n" if $VERBOSE;
490     File::Path::rmtree $dst, $VERBOSE >= 2, 0;
491    
492     print "populating $dst...\n" if $VERBOSE;
493    
494     my %mkdir;
495    
496     while (my ($path, $info) = each %$set) {
497     $path =~ m%^([^/]+)(.*)/([^/]+)$%
498     or die "$path: malformed destination path, please report.\n";
499    
500     my ($p1, $p2, $f) = ($1, $2, $3);
501    
502     my $dstdir = "$dst/$DIR{$p1}$p2";
503    
504     File::Path::mkpath $dstdir, $VERBOSE >= 2, 0777
505     unless $mkdir{$dstdir}++;
506    
507     my $src = $info->[0];
508    
509     if (
510     $STRIP
511     && ($f =~ /\.(?:pm|pl|ix|al)$/
512     || $p1 eq "bin")
513     ) {
514     strip_copy $src, "$dstdir/$f";
515    
516     } else {
517     File::Copy::cp $src, "$dstdir/$f"
518     or die "$src => $dstdir/$f: $!";
519    
520     if (
521 root 1.4 $f =~ /\.(?:bundle|dyld|so|dll|sl)$/ # TODO
522     || $p1 eq "exe"
523     || $p1 eq "dll"
524 root 1.3 ) {
525 root 1.4 if (defined $BINSTRIP) {
526     system "$BINSTRIP \Q$dstdir/$f";
527     }
528    
529     chmod 0777 & ~umask, "$dstdir/$f";
530 root 1.3 }
531     }
532     }
533 root 1.1 }
534    
535 root 1.7 $_->() for @phase0;
536    
537 root 1.1 $ex = new Perl::LibExtractor use_packlists => $USE_PACKLISTS;
538    
539     $_->() for @phase1;
540    
541     $set = $ex->set;
542    
543     $_->() for @phase2;