Hello List,

I am maintaining a perl/Tk database app and use PAR::Packer to create binaries.
Works perfect on Linux/ MacOS /Windows - thanks for a great tool.
There are a lot of dependencies in my app therefore the packing takes some
minutes. Now I was making up my mind about the possibility to add a dependencies
cache - most of the time my dependencies do not change - and just tried it.
It's a quick hack: uses Storable to store/retrieve state inside the
pack_manifest_hash method. However it works and I'd like to share it here, maybe
as a feature suggestion rather than a patch...
It speeds packing up from minutes to seconds in my case.
Btw sorry: Diff is against $VERSION = '0.982' I didn't check before I started...

Cheers, Christoph

--- C:\Dokumente und Einstellungen\chris\Desktop\oper_wc\PAR\Packer-ori.pm      
Di Jul 29 17:36:44 2008
+++ C:\Dokumente und Einstellungen\chris\Desktop\oper_wc\PAR\Packer.pm  Fr Jun 
26 01:22:32 2009
@@ -33,6 +33,7 @@
 use File::Spec ();
 use File::Temp ();
 use Module::ScanDeps ();
+use Storable;
 use PAR ();
 use PAR::Filter ();
 
@@ -69,6 +70,8 @@
     'vv|verbose2',   => 'Verbosity level 2',
     'vvv|verbose3',  => 'Verbosity level 3',
     'z|compress:i'   => 'Compression level',
+    'D|savedeps:s'   => 'Save detected dependencies to a file',
+    'U|usedeps:s'    => 'Read dependencies from a file',
 };
 
 my $ValidOptions = {};
@@ -453,7 +456,7 @@
     my $opt  = $self->{options};
 
     my $par_file = $self->get_par_file();
-
+    
     $self->_add_pack_manifest();
     $self->_add_add_manifest();
     $self->_make_manifest();
@@ -470,7 +473,6 @@
 
 sub _write_zip {
     my ($self) = @_;
-
     my $old_member   = $self->{pack_attrib}{old_member};
     my $oldsize      = $self->{pack_attrib}{old_size};
     my $par_file     = $self->{par_file};
@@ -538,7 +540,6 @@
 
 sub _make_manifest {
     my ($self) = @_;
-
     my $full_manifest = $self->{full_manifest};
 
     my $opt      = $self->{options};
@@ -665,100 +666,127 @@
     my $par_file = $self->{par_file};
     my (@modules, @data, @exclude);
 
-    foreach my $name (@{ $opt->{M} || [] }) {
-        $self->_name2moddata($name, \...@modules, \...@data);
-    }
+    my %map;
+    my %text;
+    
+    if ($opt->{usedeps}) {
+        my $file = $opt->{usedeps};
+        my $stored = retrieve($file)
+            or die "Couldn't retrieve from file[$file]\n";
+        my ($stored_obj,$stored_data) = @$stored;
+        my $pack_attrib = delete $stored_obj->{pack_attrib};
+        # compare deeply here and croak if settings differ?
+        for my $slot (qw/text
+                         map
+                         shared_libs
+                        /) {
+            $self->{pack_attrib}{$slot} = $pack_attrib->{$slot};
+        }
+        %map        = %{$pack_attrib->{map}};
+        %text       = %{$pack_attrib->{text}};
+        @SharedLibs = @{$pack_attrib->{shared_libs}};
+        @data       = @$stored_data;
+    } else {
+        
+        foreach my $name (@{ $opt->{M} || [] }) {
+            $self->_name2moddata($name, \...@modules, \...@data);
+        }
 
-    # Skip either
-    # a) all files from a .par file or
-    # b) A module
-    foreach my $name ('PAR', @{ $opt->{X} || [] }) {
-        if (-f $name and my $dep_zip = Archive::Zip->new($name)) {
-            for ($dep_zip->memberNames()) {
-                next if ( /MANIFEST/ or /META.yml/ or /^script\// );
-                $dep_zip_files{$_} ||= $name;
+        # Skip either
+        # a) all files from a .par file or
+        # b) A module
+        foreach my $name ('PAR', @{ $opt->{X} || [] }) {
+            if (-f $name and my $dep_zip = Archive::Zip->new($name)) {
+                for ($dep_zip->memberNames()) {
+                    next if ( /MANIFEST/ or /META.yml/ or /^script\// );
+                    $dep_zip_files{$_} ||= $name;
+                }
+            } else {
+                $self->_name2moddata($name, \...@exclude, \...@exclude);
             }
         }
-        else {
-            $self->_name2moddata($name, \...@exclude, \...@exclude);
-        }
-    }
 
-    my %map;
+      
+        unshift(@INC, @{ $opt->{I} || [] });
+        unshift(@SharedLibs,
+                map $self->_find_shlib($_, $sn), @{ $opt->{l} || [] });
 
-    unshift(@INC, @{ $opt->{I} || [] });
-    unshift(@SharedLibs, map $self->_find_shlib($_, $sn), @{ $opt->{l} || [] 
});
+        my $inc_find = $self->_obj_function($fe, '_find_in_inc');
 
-    my $inc_find = $self->_obj_function($fe, '_find_in_inc');
+        my %skip = map { $_, 1 } map &$inc_find($_), @exclude;
+        if ($^O eq 'MSWin32') {
+            %skip = (%skip, map { s{\\}{/}g; lc($_), 1 } @SharedLibs);
+        } else {
+            %skip = (%skip, map { $_, 1 } @SharedLibs);
+        }
 
-    my %skip = map { $_, 1 } map &$inc_find($_), @exclude;
-    if ($^O eq 'MSWin32') {
-        %skip = (%skip, map { s{\\}{/}g; lc($_), 1 } @SharedLibs);
-    }
-    else {
-        %skip = (%skip, map { $_, 1 } @SharedLibs);
-    }
+        my $add_deps = $self->_obj_function($fe, 'add_deps');
 
-    my $add_deps = $self->_obj_function($fe, 'add_deps');
-
-    my @files; # files to scan
-    # Apply %Preload to the -M'd modules and add them to the list of
-    # files to scan
-    foreach my $module (@modules) {
-        my $file = &$inc_find($module);
-        push @files, $file;
+        my @files;              # files to scan
+        # Apply %Preload to the -M'd modules and add them to the list of
+        # files to scan
+        foreach my $module (@modules) {
+            my $file = &$inc_find($module);
+            push @files, $file;
         
-        my $preload = Module::ScanDeps::_get_preload($module) or next;
+            my $preload = Module::ScanDeps::_get_preload($module) or next;
         
-        $add_deps->(
-            used_by => $file,
-            rv      => \%map,
-            modules => $preload,
-            skip    => \%skip,
-#            warn_missing => $args->{warn_missing},
-        );
-        push @files, map {&$inc_find($_)} @$preload;
-    }
-    push @files, @$input;
+            $add_deps->(
+                        used_by => $file,
+                        rv      => \%map,
+                        modules => $preload,
+                        skip    => \%skip,
+                        #            warn_missing => $args->{warn_missing},
+                    );
+            push @files, map {&$inc_find($_)} @$preload;
+        }
+        push @files, @$input;
 
-    # Search for scannable code in all -I'd paths
-    push @Module::ScanDeps::IncludeLibs, @{$opt->{I}} if $opt->{I};
+        # Search for scannable code in all -I'd paths
+        push @Module::ScanDeps::IncludeLibs, @{$opt->{I}} if $opt->{I};
     
-    my $scan_dispatch =
-      $opt->{n}
-      ? $self->_obj_function($fe, 'scan_deps_runtime')
-      : $self->_obj_function($fe, 'scan_deps');
+        my $scan_dispatch =
+            $opt->{n}
+                ? $self->_obj_function($fe, 'scan_deps_runtime')
+                    : $self->_obj_function($fe, 'scan_deps');
 
-    $scan_dispatch->(
-        rv      => \%map,
-        files   => \...@files,
-        execute => $opt->{x},
-        compile => $opt->{c},
-        skip    => \%skip,
-        ($opt->{n}) ? () : (
-            recurse => 1,
-            first   => 1,
-        ),
-    );
+        $scan_dispatch->(
+                         rv      => \%map,
+                         files   => \...@files,
+                         execute => $opt->{x},
+                         compile => $opt->{c},
+                         skip    => \%skip,
+                         ($opt->{n}) ? () : (
+                                             recurse => 1,
+                                             first   => 1,
+                                         ),
+                     );
 
-    %skip = map { $_, 1 } map &$inc_find($_), @exclude;
-    %skip = (%skip, map { $_, 1 } @SharedLibs);
+        %skip = map { $_, 1 } map &$inc_find($_), @exclude;
+        %skip = (%skip, map { $_, 1 } @SharedLibs);
 
-    &$add_deps(
-        rv      => \%map,
-        modules => \...@modules,
-        skip    => \%skip,
-    );
+        &$add_deps(
+                   rv      => \%map,
+                   modules => \...@modules,
+                   skip    => \%skip,
+               );
 
-    my %text;
 
-    $text{$_} = ($map{$_}{type} =~ /^(?:module|autoload)$/) for keys %map;
-    $map{$_} = $map{$_}{file} for keys %map;
+        $text{$_} = ($map{$_}{type} =~ /^(?:module|autoload)$/) for keys %map;
+        $map{$_} = $map{$_}{file} for keys %map;
 
-    $self->{pack_attrib}{text}        = \%text;
-    $self->{pack_attrib}{map}         = \%map;
-    $self->{pack_attrib}{shared_libs} = \...@sharedlibs;
+        $self->{pack_attrib}{text}        = \%text;
+        $self->{pack_attrib}{map}         = \%map;
+        $self->{pack_attrib}{shared_libs} = \...@sharedlibs;
 
+        #print Dumper \%text, \%map, \...@sharedlibs, \%skip;
+        if ($opt->{savedeps}) {
+            my $file = $opt->{savedeps};
+            store([$self,\...@data], $file)
+                or die "Can't store $self in file [$file\\n";
+        }
+    }
+    
     my $size = 0;
     my $old_member;
 

Reply via email to