… | |
… | |
67 | |
67 | |
68 | Creates a new extractor object. Each extractor object stores some |
68 | Creates a new extractor object. Each extractor object stores some |
69 | configuration options and a subset of files that can be queried at any |
69 | configuration options and a subset of files that can be queried at any |
70 | time,. |
70 | time,. |
71 | |
71 | |
|
|
72 | Binary executables (such as the perl interpreter) are stored inside |
|
|
73 | F<bin/>, perl scripts are stored under F<script/>, perl library files are |
|
|
74 | stored under F<lib/> and shared libraries are stored under F<dll/>. |
|
|
75 | |
72 | The following key-value pairs exist, with default values as specified. |
76 | The following key-value pairs exist, with default values as specified. |
73 | |
77 | |
74 | =over 4 |
78 | =over 4 |
75 | |
|
|
76 | =item exedir => "bin" |
|
|
77 | |
|
|
78 | The prefix to use for the suggested target path for perl executables |
|
|
79 | (scripts). Defaults to F<bin>. |
|
|
80 | |
|
|
81 | =item libdir => "lib" |
|
|
82 | |
|
|
83 | The prefix to use for the suggested target path of perl library |
|
|
84 | files (F<.pm>, F<.pl>, dynamic objects, autoloader index and files |
|
|
85 | etc.). Defaults to F<lib>. |
|
|
86 | |
|
|
87 | =item bindir => "bin" |
|
|
88 | |
|
|
89 | The prefix to use for the suggested target path for (non-perl) |
|
|
90 | executables. Defaults to F<bin>. |
|
|
91 | |
|
|
92 | =item dlldir => "bin" |
|
|
93 | |
|
|
94 | The prefix to use for the suggested target path of any shared |
|
|
95 | libraries. Defaults to F<bin>. |
|
|
96 | |
79 | |
97 | =item inc => \@INC without "." |
80 | =item inc => \@INC without "." |
98 | |
81 | |
99 | An arrayref with paths to perl library directories. The default is |
82 | An arrayref with paths to perl library directories. The default is |
100 | C<\@INC>, with F<.> removed. |
83 | C<\@INC>, with F<.> removed. |
… | |
… | |
117 | |
100 | |
118 | sub new { |
101 | sub new { |
119 | my ($class, %kv) = @_; |
102 | my ($class, %kv) = @_; |
120 | |
103 | |
121 | my $self = bless { |
104 | my $self = bless { |
122 | exedir => "bin", |
|
|
123 | libdir => "lib", |
|
|
124 | bindir => "bin", |
|
|
125 | dlldir => "bin", |
|
|
126 | inc => [grep $_ ne ".", @INC], |
105 | inc => [grep $_ ne ".", @INC], |
127 | use_packlist => 1, |
106 | use_packlist => 1, |
128 | %kv, |
107 | %kv, |
129 | set => {}, |
108 | set => {}, |
130 | }, $class; |
109 | }, $class; |
131 | |
110 | |
… | |
… | |
299 | |
278 | |
300 | my $lib = $self->{lib}; |
279 | my $lib = $self->{lib}; |
301 | my $path; |
280 | my $path; |
302 | |
281 | |
303 | for (@$add) { |
282 | for (@$add) { |
304 | $path = "$self->{libdir}/$_"; |
283 | $path = "lib/$_"; |
305 | |
284 | |
306 | $self->{set}{$path} ||= do { |
285 | $self->{set}{$path} ||= do { |
307 | my @info; |
286 | my @info; |
308 | |
287 | |
309 | $info[I_SRC] = $lib->{$_} |
288 | $info[I_SRC] = $lib->{$_} |
310 | or croak "$_: unable to locate file in perl library"; |
289 | or croak "$_: unable to locate file in perl library"; |
311 | |
290 | |
312 | if ($self->{use_packlist} && exists $self->{packlist}{$_}) { |
291 | if ($self->{use_packlist} && exists $self->{packlist}{$_}) { |
313 | $self->{set}{"$self->{libdir}/$_"} ||= [$self->{lib}{$_} or die] |
292 | $self->{set}{"lib/$_"} ||= [$self->{lib}{$_} or die] |
314 | for @{ $self->{packlist}{$_} }; |
293 | for @{ $self->{packlist}{$_} }; |
315 | |
294 | |
316 | # for (grep /\.pm$/, @{ $self->{packlist}{$_} }) { |
295 | # for (grep /\.pm$/, @{ $self->{packlist}{$_} }) { |
317 | # s/\.pm$//; |
296 | # s/\.pm$//; |
318 | # s%/%::%g; |
297 | # s%/%::%g; |
… | |
… | |
333 | # auto dir exists, scan it for cool stuff |
312 | # auto dir exists, scan it for cool stuff |
334 | |
313 | |
335 | # 1. shared object, others are of no interest to us |
314 | # 1. shared object, others are of no interest to us |
336 | my $so = "$auto$base.$Config{dlext}"; |
315 | my $so = "$auto$base.$Config{dlext}"; |
337 | if (my $src = $lib->{$so}) { |
316 | if (my $src = $lib->{$so}) { |
338 | $so = "$self->{libdir}/$so"; |
317 | $so = "lib/$so"; |
339 | push @{ $info[I_DEP] }, $so; $self->{set}{$so} = [$src]; |
318 | push @{ $info[I_DEP] }, $so; $self->{set}{$so} = [$src]; |
340 | } |
319 | } |
341 | |
320 | |
342 | # 2. autoloader/autosplit |
321 | # 2. autoloader/autosplit |
343 | my $ix = "${auto}autosplit.ix"; |
322 | my $ix = "${auto}autosplit.ix"; |
344 | if (my $src = $lib->{$ix}) { |
323 | if (my $src = $lib->{$ix}) { |
345 | $ix = "$self->{libdir}/$ix"; |
324 | $ix = "lib/$ix"; |
346 | push @{ $info[I_DEP] }, $ix; $self->{set}{$ix} = [$src]; |
325 | push @{ $info[I_DEP] }, $ix; $self->{set}{$ix} = [$src]; |
347 | |
326 | |
348 | open my $fh, "<:perlio", $src |
327 | open my $fh, "<:perlio", $src |
349 | or croak "$src: $!"; |
328 | or croak "$src: $!"; |
350 | |
329 | |
… | |
… | |
354 | if (/^\s*sub\s+ ([^[:space:];]+) \s* (?:\([^)]*\))? \s*;?\s*$/x) { |
333 | if (/^\s*sub\s+ ([^[:space:];]+) \s* (?:\([^)]*\))? \s*;?\s*$/x) { |
355 | my $al = "auto/$package/$1.al"; |
334 | my $al = "auto/$package/$1.al"; |
356 | my $src = $lib->{$al} |
335 | my $src = $lib->{$al} |
357 | or croak "$al: autoload file not found, but should be there."; |
336 | or croak "$al: autoload file not found, but should be there."; |
358 | |
337 | |
359 | $al = "$self->{libdir}/$al"; |
338 | $al = "lib/$al"; |
360 | push @{ $info[I_DEP] }, $al; $self->{set}{$al} = [$src]; |
339 | push @{ $info[I_DEP] }, $al; $self->{set}{$al} = [$src]; |
361 | |
340 | |
362 | } elsif (/^\s*package\s+([^[:space:];]+)\s*;?\s*$/) { |
341 | } elsif (/^\s*package\s+([^[:space:];]+)\s*;?\s*$/) { |
363 | ($package = $1) =~ s/::/\//g; |
342 | ($package = $1) =~ s/::/\//g; |
364 | } elsif (/^\s*(?:#|1?\s*;?\s*$)/) { |
343 | } elsif (/^\s*(?:#|1?\s*;?\s*$)/) { |
… | |
… | |
457 | $self->_trace ("use $_", "{ package $pkg; use $_ }") |
436 | $self->_trace ("use $_", "{ package $pkg; use $_ }") |
458 | unless $self->{add_mod}{$_}++; |
437 | unless $self->{add_mod}{$_}++; |
459 | } |
438 | } |
460 | } |
439 | } |
461 | |
440 | |
462 | =item $extractor->add_script ($name[, $name...]) |
441 | =item $extractor->add_bin ($name[, $name...]) |
463 | |
442 | |
464 | Adds the given (perl) program(s) to the file set, that is, a program |
443 | Adds the given (perl) program(s) to the file set, that is, a program |
465 | installed by some perl module, written in perl (an example would be the |
444 | installed by some perl module, written in perl (an example would be the |
466 | L<perl-libextract> program that is part of the C<Perl::LibExtractor> |
445 | L<perl-libextract> program that is part of the C<Perl::LibExtractor> |
467 | distribution). |
446 | distribution). |
468 | |
447 | |
469 | Example: add the deliantra client program installed by the |
448 | Example: add the deliantra client program installed by the |
470 | L<Deliantra::Client> module. |
449 | L<Deliantra::Client> module and put it under F<bin/deliantra>. |
471 | |
450 | |
472 | $extractor->add_script ("deliantra"); |
451 | $extractor->add_bin ("deliantra"); |
473 | |
452 | |
474 | =cut |
453 | =cut |
475 | |
454 | |
476 | sub add_script { |
455 | sub add_bin { |
477 | my $self = shift; |
456 | my $self = shift; |
478 | |
457 | |
479 | exe: |
458 | exe: |
480 | for my $exe (@_) { |
459 | for my $exe (@_) { |
481 | for my $dir ($Config{sitebinexp}, $Config{vendorbinexp}, $Config{binexp}) { |
460 | for my $dir ($Config{sitebinexp}, $Config{vendorbinexp}, $Config{binexp}) { |
482 | if (open my $fh, "<:perlio", "$dir/$exe") { |
461 | if (open my $fh, "<:perlio", "$dir/$exe") { |
483 | |
462 | if (-f $fh) { |
484 | my $file = do { local $/; readline $fh }; |
463 | my $file = do { local $/; readline $fh }; |
485 | |
464 | |
486 | $self->_trace_flush if exists $self->{trace_check}; |
465 | $self->_trace_flush if exists $self->{trace_check}; |
487 | $self->{trace_check} = $file; |
466 | $self->{trace_check} = $file; |
488 | |
467 | |
489 | $self->{set}{"$self->{bindir}/$exe"} = ["$dir/$exe"]; |
468 | $self->{set}{"bin/$exe"} = ["$dir/$exe"]; |
490 | next exe; |
469 | next exe; |
|
|
470 | } |
491 | } |
471 | } |
492 | } |
472 | } |
493 | |
473 | |
494 | croak "add_script ($exe): executable not found"; |
474 | croak "add_bin ($exe): executable not found"; |
495 | } |
475 | } |
496 | } |
476 | } |
497 | |
477 | |
498 | =item $extractor->add_eval ($string) |
478 | =item $extractor->add_eval ($string) |
499 | |
479 | |
… | |
… | |
531 | =item $extractor->add_perl |
511 | =item $extractor->add_perl |
532 | |
512 | |
533 | Adds the perl binary itself to the file set, including the libperl dll, if |
513 | Adds the perl binary itself to the file set, including the libperl dll, if |
534 | needed. |
514 | needed. |
535 | |
515 | |
536 | For example, on UNIX systems, this usually adds a F<bin/perl> and possibly |
516 | For example, on UNIX systems, this usually adds a F<exe/perl> and possibly |
537 | some F<lib/libperl.so.XXX>. |
517 | some F<dll/libperl.so.XXX>. |
538 | |
518 | |
539 | =cut |
519 | =cut |
540 | |
520 | |
541 | sub add_perl { |
521 | sub add_perl { |
542 | my ($self) = @_; |
522 | my ($self) = @_; |
543 | |
523 | |
544 | $self->{set}{"$self->{exedir}/perl$Config{_exe}"} = [_perl_path]; |
524 | $self->{set}{"exe/perl$Config{_exe}"} = [_perl_path]; |
545 | |
525 | |
546 | # on debian, we have the special case of a perl binary linked against |
526 | # on debian, we have the special case of a perl binary linked against |
547 | # a static libperl.a (which is not available), but the Config says to use |
527 | # a static libperl.a (which is not available), but the Config says to use |
548 | # a shared library, which is in the wrong directory, too (which breaks |
528 | # a shared library, which is in the wrong directory, too (which breaks |
549 | # every other perl installation on the system - they are so stupid). |
529 | # every other perl installation on the system - they are so stupid). |
… | |
… | |
564 | } else { |
544 | } else { |
565 | $libperl = $Config{libperl}; |
545 | $libperl = $Config{libperl}; |
566 | $libpath = $self->{lib}{"CORE/$libperl"}; |
546 | $libpath = $self->{lib}{"CORE/$libperl"}; |
567 | } |
547 | } |
568 | |
548 | |
569 | $self->{set}{"$self->{dlldir}/$libperl"} = $libpath |
549 | $self->{set}{"dll/$libperl"} = $libpath |
570 | if length $libpath && -e $libpath; |
550 | if length $libpath && -e $libpath; |
571 | } |
551 | } |
572 | } |
552 | } |
573 | |
553 | |
574 | =item $extractor->add_core_support |
554 | =item $extractor->add_core_support |
… | |
… | |
648 | |
628 | |
649 | for (@{ |
629 | for (@{ |
650 | $self->_read_packlist ($Config{privlibexp}, ".packlist") |
630 | $self->_read_packlist ($Config{privlibexp}, ".packlist") |
651 | }) { |
631 | }) { |
652 | $self->{set}{$_} ||= [ |
632 | $self->{set}{$_} ||= [ |
653 | "$self->{libdir}/" |
633 | "lib/" |
654 | . ($lib->{$_} or croak "$_: unable to locate file in perl library") |
634 | . ($lib->{$_} or croak "$_: unable to locate file in perl library") |
655 | ]; |
635 | ]; |
656 | } |
636 | } |
657 | } |
637 | } |
658 | |
638 | |
… | |
… | |
672 | path inside the file set, almost the same as in the shell. For example, |
652 | path inside the file set, almost the same as in the shell. For example, |
673 | F</bin/perl*> would match all files whose names starting with F<perl> |
653 | F</bin/perl*> would match all files whose names starting with F<perl> |
674 | inside the F<bin> directory in the set. |
654 | inside the F<bin> directory in the set. |
675 | |
655 | |
676 | If the F</> is missing, then the pattern is interpreted as a module name |
656 | If the F</> is missing, then the pattern is interpreted as a module name |
677 | (a F<.pm> file). For example, F<Coro> matches the file F<libdir/Coro.pm> |
657 | (a F<.pm> file). For example, F<Coro> matches the file F<lib/Coro.pm> , |
678 | (where F<libdir> is the perl library directory), while F<Coro::*> would |
658 | while F<Coro::*> would match F<lib/Coro/*.pm>. |
679 | match F<libdir/Coro/*.pm>. |
|
|
680 | |
659 | |
681 | =item * |
660 | =item * |
682 | |
661 | |
683 | A single star matches anything inside a single directory component. For |
662 | A single star matches anything inside a single directory component. For |
684 | example, F</lib/Coro/*.pm> would match all F<.pm> files inside the |
663 | example, F</lib/Coro/*.pm> would match all F<.pm> files inside the |
… | |
… | |
704 | s/\\\*/[^\/]*/g; |
683 | s/\\\*/[^\/]*/g; |
705 | s/\\\?/[^\/]/g; |
684 | s/\\\?/[^\/]/g; |
706 | |
685 | |
707 | unless (s%^\\/%%) { |
686 | unless (s%^\\/%%) { |
708 | s%\\:\\:%/%g; |
687 | s%\\:\\:%/%g; |
709 | $_ = (quotemeta $_[0]{libdir}) . "/$_\\.pm"; |
688 | $_ = "lib/$_\\.pm"; |
710 | } |
689 | } |
711 | |
690 | |
712 | $_ .= '$'; |
691 | $_ .= '$'; |
713 | s/(?: \[\^\/\] | \. ) \*\$$//x; # remove ** at end |
692 | s/(?: \[\^\/\] | \. ) \*\$$//x; # remove ** at end |
714 | |
693 | |
… | |
… | |
756 | |
735 | |
757 | Any files not matched by any expression will simply stay in the set. |
736 | Any files not matched by any expression will simply stay in the set. |
758 | |
737 | |
759 | For example, to remove most of the useless autoload functions by the POSIX |
738 | For example, to remove most of the useless autoload functions by the POSIX |
760 | module (they either do the same thing as a builtin or always raise an |
739 | module (they either do the same thing as a builtin or always raise an |
761 | error), you would use this (assuming a default C<libdir>): |
740 | error), you would use this: |
762 | |
741 | |
763 | $extractor->filter ("-/lib/auto/POSIX/*.al"); |
742 | $extractor->filter ("-/lib/auto/POSIX/*.al"); |
764 | |
743 | |
765 | This does not remove all autoload files, only the ones not defined by a |
744 | This does not remove all autoload files, only the ones not defined by a |
766 | subclass (e.g. it leaves C<POSIX::SigRt::xxx> alone). |
745 | subclass (e.g. it leaves C<POSIX::SigRt::xxx> alone). |
… | |
… | |
812 | $self->_trace_flush; |
791 | $self->_trace_flush; |
813 | |
792 | |
814 | my $set = $self->{set}; |
793 | my $set = $self->{set}; |
815 | |
794 | |
816 | # delete all static libraries, also windows stuff |
795 | # delete all static libraries, also windows stuff |
817 | delete @$set{ grep m%^\Q$self->{libdir}\E/auto/(?:.+/)?([^\/]+)/\1(?:\Q$Config{_a}\E|\.pdb|\.exp)$%s, keys %$set }; |
796 | delete @$set{ grep m%^lib/auto/(?:.+/)?([^\/]+)/\1(?:\Q$Config{_a}\E|\.pdb|\.exp)$%s, keys %$set }; |
818 | |
797 | |
819 | # delete all extralibs.ld and extralibs.all (no clue what the latter is for) |
798 | # delete all extralibs.ld and extralibs.all (no clue what the latter is for) |
820 | delete @$set{ grep m%^\Q$self->{libdir}\E/auto/.*/extralibs\.(?:ld|all)$%s, keys %$set }; |
799 | delete @$set{ grep m%^lib/auto/.*/extralibs\.(?:ld|all)$%s, keys %$set }; |
821 | |
800 | |
822 | # delete all .pod, .h, .html files (hopefully none of them are used at runtime) |
801 | # delete all .pod, .h, .html files (hopefully none of them are used at runtime) |
823 | delete @$set{ grep m%^\Q$self->{libdir}\E/.*\.(?:pod|h|html)$%s, keys %$set }; |
802 | delete @$set{ grep m%^lib/.*\.(?:pod|h|html)$%s, keys %$set }; |
824 | |
803 | |
825 | # delete unneeded unicore files |
804 | # delete unneeded unicore files |
826 | delete @$set{ grep m%^\Q$self->{libdir}\E/unicore/(?:mktables(?:\.lst)?|.*\.txt)$%s, keys %$set }; |
805 | delete @$set{ grep m%^lib/unicore/(?:mktables(?:\.lst)?|.*\.txt)$%s, keys %$set }; |
827 | } |
806 | } |
828 | |
807 | |
829 | =back |
808 | =back |
830 | |
809 | |
831 | =head2 RESULT SET |
810 | =head2 RESULT SET |
… | |
… | |
879 | |
858 | |
880 | To package he deliantra client (L<Deliantra::Client>), finding all |
859 | To package he deliantra client (L<Deliantra::Client>), finding all |
881 | (perl) files needed to run it is a first step. This can be done by using |
860 | (perl) files needed to run it is a first step. This can be done by using |
882 | something like the following code snippet: |
861 | something like the following code snippet: |
883 | |
862 | |
884 | my $ex = new Perl::LibExtractor |
863 | my $ex = new Perl::LibExtractor; |
885 | exedir => ".", dlldir => ".", |
|
|
886 | libdir => "pm", bindir => "pm/bin"; |
|
|
887 | |
864 | |
888 | $ex->add_perl; |
865 | $ex->add_perl; |
889 | $ex->add_core_support; |
866 | $ex->add_core_support; |
890 | $ex->add_script ("deliantra"); |
867 | $ex->add_bin ("deliantra"); |
891 | $ex->add_mod ("AnyEvent::Impl::EV"); |
868 | $ex->add_mod ("AnyEvent::Impl::EV"); |
892 | $ex->add_mod ("AnyEvent::Impl::Perl"); |
869 | $ex->add_mod ("AnyEvent::Impl::Perl"); |
893 | $ex->add_mod ("Urlader"); |
870 | $ex->add_mod ("Urlader"); |
894 | $ex->filter ("-/*/auto/POSIX/**.al"); |
871 | $ex->filter ("-/*/auto/POSIX/**.al"); |
895 | $ex->runtime_only; |
872 | $ex->runtime_only; |
896 | |
873 | |
897 | Let's first find out about the choice of paths for the subset. The |
|
|
898 | Deliantra client binary packages use L<Urlader> nowadays, and there it is |
|
|
899 | convenient to have F<perl> and any shared libraries directly in the root |
|
|
900 | of the distribution. |
|
|
901 | |
|
|
902 | The perl library files are put into a directory named F<pm>, simply |
|
|
903 | because it's shorter than F<lib>, and in the future, some files might go |
|
|
904 | into F<lib>. |
|
|
905 | |
|
|
906 | And finally, the F<deliantra> script itself is put into the perl library |
|
|
907 | directory, because it is not run directly - the installed client uses the |
|
|
908 | system fonts and other resources, while the binary package is supposed |
|
|
909 | to use the files packaged with it. To achieve this, a wrapper script is |
|
|
910 | created, called F<run>; which displays a splash screen and configures the |
|
|
911 | environment. A simplified version of it could look like this: |
|
|
912 | |
|
|
913 | @INC = ("pm", "."); # "." required by newer AutoLoader grrrr. |
|
|
914 | $ENV{PANGO_RC_FILE} = "pango.rc"; |
|
|
915 | require "bin/deliantra"; |
|
|
916 | exit 0; |
|
|
917 | |
|
|
918 | First it sets the perl library directory to F<pm> and F<.> (the latter |
874 | First it sets the perl library directory to F<pm> and F<.> (the latter |
919 | to work around some AutoLoader bugs), so perl uses only the perl library |
875 | to work around some AutoLoader bugs), so perl uses only the perl library |
920 | files that came with the binary package. |
876 | files that came with the binary package. |
921 | |
877 | |
922 | Then it sets some environment variable to override the system default |
878 | Then it sets some environment variable to override the system default |