Commit d7ec8d2771aa9ce654b379f666e694336a554509

Authored by Jay Berkenbilt
1 parent 8fe48ace

create copy_dlls

git-svn-id: svn+q:///qpdf/trunk@863 71b93d88-0707-0410-a8cf-f5a4172ac649
Showing 1 changed file with 127 additions and 0 deletions
copy_dlls 0 → 100755
  1 +#!/usr/bin/env perl
  2 +
  3 +require 5.008;
  4 +BEGIN { $^W = 1; }
  5 +use strict;
  6 +use File::Basename;
  7 +
  8 +my $whoami = basename($0);
  9 +
  10 +usage() unless @ARGV == 2;
  11 +my ($file, $destdir) = @ARGV;
  12 +my $filedir = dirname($file);
  13 +
  14 +my %dlls = ();
  15 +open(O, "objdump -p $file|") or die "$whoami: can't run objdump\n";
  16 +while (<O>)
  17 +{
  18 + if (m/^\s+DLL Name:\s+(.+\.dll)/i)
  19 + {
  20 + my $dll = $1;
  21 + $dll =~ tr/A-Z/a-z/;
  22 + next if $dll =~ m/^(kernel32|msvcr)\.dll$/;
  23 + $dlls{$dll} = 1;
  24 + }
  25 +}
  26 +close(O);
  27 +
  28 +# Search the file's directory, the current directory, and the path for
  29 +# dlls since that's what Windows does.
  30 +my $sep = ($^O eq 'MSWin32' ? ';' : ':');
  31 +my @path = ($filedir, '.', split($sep, $ENV{'PATH'}));
  32 +if (-f "$file.manifest")
  33 +{
  34 + unshift(@path, get_manifest_dirs("$file.manifest"));
  35 +}
  36 +my @final = ();
  37 +my @notfound = ();
  38 +dll_loop:
  39 +foreach my $dll (sort keys %dlls)
  40 +{
  41 + my $found = 0;
  42 + foreach my $dir (@path)
  43 + {
  44 + if (-f "$dir/$dll")
  45 + {
  46 + push(@final, "$dir/$dll");
  47 + $found = 1;
  48 + last;
  49 + }
  50 + }
  51 + if (! $found)
  52 + {
  53 + push(@notfound, $dll);
  54 + }
  55 +}
  56 +
  57 +if (@notfound)
  58 +{
  59 + die "$whoami: can't find the following dlls: " .
  60 + join(', ', @notfound), "\n";
  61 +}
  62 +
  63 +foreach my $f (@final)
  64 +{
  65 + $f =~ s,\\,/,g;
  66 + print "Copying $f to $destdir\n";
  67 + system("cp -p $f $destdir") == 0 or
  68 + die "$whoami: copy $f to $destdir failed\n";
  69 + print $f, "\n";
  70 +}
  71 +
  72 +sub get_manifest_dirs
  73 +{
  74 + # Find all system directories in which to search for DLLs based on
  75 + # the contents of a Visual Studio manifest file.
  76 +
  77 + my $manifest_file = shift;
  78 +
  79 + require XML::Parser;
  80 + my $sysroot = $ENV{'SYSTEMROOT'} or die "$whoami: can't get \$SYSTEMROOT\n";
  81 + $sysroot =~ s,\\,/,g;
  82 + if ($^O eq 'cygwin')
  83 + {
  84 + chop($sysroot = `cygpath $sysroot`);
  85 + die "$whoami: can't get system root" unless $? == 0;
  86 + }
  87 + my $winsxs = "$sysroot/WinSxS";
  88 + opendir(D, $winsxs) or die "$whoami: can't opendir $winsxs: $!\n";
  89 + my @entries = readdir(D);
  90 + closedir(D);
  91 +
  92 + my @candidates = ();
  93 +
  94 + my $readAssemblyIdentity = sub
  95 + {
  96 + my ($parser, $element, %attrs) = @_;
  97 + return unless $element eq 'assemblyIdentity';
  98 + my $type = $attrs{'type'};
  99 + my $name = $attrs{'name'};
  100 + my $version = $attrs{'version'};
  101 + my $processorArchitecture = $attrs{'processorArchitecture'};
  102 + my $publicKeyToken = $attrs{'publicKeyToken'};
  103 +
  104 + my $dir_start = join('_',
  105 + $processorArchitecture,
  106 + $name,
  107 + $publicKeyToken,
  108 + $version);
  109 + push(@candidates, $dir_start);
  110 + };
  111 +
  112 + my $p = new XML::Parser(Handlers => {'Start' => $readAssemblyIdentity});
  113 + $p->parsefile($manifest_file);
  114 +
  115 + my @dirs = ();
  116 + foreach my $c (@candidates)
  117 + {
  118 + push(@dirs, map { "$winsxs/$_" } (grep { m/^\Q$c\E/i } @entries));
  119 + }
  120 +
  121 + @dirs;
  122 +}
  123 +
  124 +sub usage
  125 +{
  126 + die "Usage: $whoami {exe|dll} destdir\n";
  127 +}
... ...