#!/usr/bin/env perl require 5.008; use warnings; use strict; use File::Basename; use File::Path qw(make_path); my $whoami = basename($0); usage() unless @ARGV == 3; my ($file, $libqpdf, $destdir) = @ARGV; my $filedir = dirname($file); my $sep = ($^O eq 'MSWin32' ? ';' : ':'); my @path = ($filedir, '.', split($sep, $ENV{'PATH'})); foreach my $var (qw(LIB)) { if (exists $ENV{$var}) { push(@path, split($sep, $ENV{$var})); } } my $format = undef; my @to_find = get_dlls($file); my %final = (); my @notfound = (); while (@to_find) { my $dll = shift(@to_find); my $found = 0; foreach my $dir ($libqpdf, @path) { if ((-f "$dir/$dll") && is_format("$dir/$dll", $format)) { if (! exists $final{$dll}) { if ($dir ne $libqpdf) { $final{$dll} = "$dir/$dll"; } push(@to_find, get_dlls("$dir/$dll")); } $found = 1; last; } } if (! $found) { push(@notfound, $dll); } } if (@notfound) { die "$whoami: can't find the following dlls: " . join(', ', @notfound), "\n"; } make_path($destdir); foreach my $dll (sort keys (%final)) { my $f = $final{$dll}; $f =~ s,\\,/,g; print "Copying $f to $destdir\n"; system("cp -p '$f' '$destdir'") == 0 or die "$whoami: copy $f to $destdir failed\n"; } sub get_dlls { my @result = (); my $exe = shift; open(O, "objdump -p \"$exe\"|") or die "$whoami: can't run objdump\n"; while () { if (m/^\s+DLL Name:\s+(.+\.dll)/i) { my $dll = $1; $dll =~ tr/A-Z/a-z/; next if $dll =~ m/^(kernel32|user32|msvcrt|advapi32)\.dll$/; next if $dll =~ m/^(api-ms-win.*|ws2_32|crypt32|bcrypt)\.dll$/; push(@result, $dll); } elsif (m/^Magic.*\((PE.+?)\)/) { $format = $1; } } close(O); if (! defined $format) { die "$whoami: can't determine format of $exe\n"; } @result; } sub is_format { my ($file, $format) = @_; $file =~ s,\\,/,g; # Special case: msvc*.dll seem to be able to behave both as 32-bit # and 64-bit DLLs. Either that, or this logic is wrong for those # DLLs and it doesn't matter because they're already installed on # my test system (which doesn't have msvc installed on it). if ($file =~ m,/msvc,i) { return 1; } my $result = 0; my $file_format = `file "$file"`; print "$file $format $file_format\n"; if ($? == 0) { if ($file_format =~ m/\Q${format}\E executable/) { $result = 1; } } $result; } sub usage { die "Usage: $whoami {exe|dll} libqpdf-dir destdir\n"; }