xref: /openbsd-src/gnu/usr.bin/perl/cpan/ExtUtils-Install/lib/ExtUtils/Install.pm (revision fac98b93b71777a71b1e912ccaf68ce33d7b87c4)
1b8851fccSafresh1package ExtUtils::Install;
2b8851fccSafresh1use strict;
3b8851fccSafresh1
4b8851fccSafresh1use Config qw(%Config);
5b8851fccSafresh1use Cwd qw(cwd);
69f11ffb7Safresh1use Exporter ();
7b8851fccSafresh1use File::Basename qw(dirname);
8b8851fccSafresh1use File::Copy;
9b8851fccSafresh1use File::Path;
10b8851fccSafresh1use File::Spec;
11b8851fccSafresh1
129f11ffb7Safresh1our @ISA = ('Exporter');
139f11ffb7Safresh1our @EXPORT = ('install','uninstall','pm_to_blib', 'install_default');
14b8851fccSafresh1
159f11ffb7Safresh1our $MUST_REBOOT;
16b8851fccSafresh1
17b8851fccSafresh1=pod
18b8851fccSafresh1
19b8851fccSafresh1=head1 NAME
20b8851fccSafresh1
21b8851fccSafresh1ExtUtils::Install - install files from here to there
22b8851fccSafresh1
23b8851fccSafresh1=head1 SYNOPSIS
24b8851fccSafresh1
25b8851fccSafresh1  use ExtUtils::Install;
26b8851fccSafresh1
27b8851fccSafresh1  install({ 'blib/lib' => 'some/install/dir' } );
28b8851fccSafresh1
29b8851fccSafresh1  uninstall($packlist);
30b8851fccSafresh1
31b8851fccSafresh1  pm_to_blib({ 'lib/Foo/Bar.pm' => 'blib/lib/Foo/Bar.pm' });
32b8851fccSafresh1
33b8851fccSafresh1=head1 VERSION
34b8851fccSafresh1
35e0680481Safresh12.22
36b8851fccSafresh1
37b8851fccSafresh1=cut
38b8851fccSafresh1
39e0680481Safresh1our $VERSION = '2.22';  # <-- do not forget to update the POD section just above this line!
40b8851fccSafresh1$VERSION = eval $VERSION;
41b8851fccSafresh1
42b8851fccSafresh1=pod
43b8851fccSafresh1
44b8851fccSafresh1=head1 DESCRIPTION
45b8851fccSafresh1
46b8851fccSafresh1Handles the installing and uninstalling of perl modules, scripts, man
47b8851fccSafresh1pages, etc...
48b8851fccSafresh1
49b8851fccSafresh1Both install() and uninstall() are specific to the way
50b8851fccSafresh1ExtUtils::MakeMaker handles the installation and deinstallation of
51b8851fccSafresh1perl modules. They are not designed as general purpose tools.
52b8851fccSafresh1
53b8851fccSafresh1On some operating systems such as Win32 installation may not be possible
54b8851fccSafresh1until after a reboot has occurred. This can have varying consequences:
55b8851fccSafresh1removing an old DLL does not impact programs using the new one, but if
56b8851fccSafresh1a new DLL cannot be installed properly until reboot then anything
57b8851fccSafresh1depending on it must wait. The package variable
58b8851fccSafresh1
59b8851fccSafresh1  $ExtUtils::Install::MUST_REBOOT
60b8851fccSafresh1
61b8851fccSafresh1is used to store this status.
62b8851fccSafresh1
63b8851fccSafresh1If this variable is true then such an operation has occurred and
64b8851fccSafresh1anything depending on this module cannot proceed until a reboot
65b8851fccSafresh1has occurred.
66b8851fccSafresh1
67b8851fccSafresh1If this value is defined but false then such an operation has
68eac174f2Safresh1occurred, but should not impact later operations.
69b8851fccSafresh1
70b8851fccSafresh1=begin _private
71b8851fccSafresh1
72eac174f2Safresh1=head2 _chmod($$;$)
73b8851fccSafresh1
74b8851fccSafresh1Wrapper to chmod() for debugging and error trapping.
75b8851fccSafresh1
76eac174f2Safresh1=head2 _warnonce(@)
77b8851fccSafresh1
78b8851fccSafresh1Warns about something only once.
79b8851fccSafresh1
80eac174f2Safresh1=head2 _choke(@)
81b8851fccSafresh1
82b8851fccSafresh1Dies with a special message.
83b8851fccSafresh1
84b8851fccSafresh1=end _private
85b8851fccSafresh1
86b8851fccSafresh1=cut
87b8851fccSafresh1
889f11ffb7Safresh1BEGIN {
89eac174f2Safresh1    *_Is_VMS        = $^O eq 'VMS'     ? sub(){1} : sub(){0};
90eac174f2Safresh1    *_Is_Win32      = $^O eq 'MSWin32' ? sub(){1} : sub(){0};
91eac174f2Safresh1    *_Is_cygwin     = $^O eq 'cygwin'  ? sub(){1} : sub(){0};
92eac174f2Safresh1    *_CanMoveAtBoot = ($^O eq 'MSWin32' || $^O eq 'cygwin') ? sub(){1} : sub(){0};
939f11ffb7Safresh1}
94b8851fccSafresh1
95b8851fccSafresh1my $Inc_uninstall_warn_handler;
96b8851fccSafresh1
97b8851fccSafresh1# install relative to here
98b8851fccSafresh1
99b8851fccSafresh1my $INSTALL_ROOT = $ENV{PERL_INSTALL_ROOT};
100b8851fccSafresh1my $INSTALL_QUIET = $ENV{PERL_INSTALL_QUIET};
1019f11ffb7Safresh1$INSTALL_QUIET = 1
1029f11ffb7Safresh1  if (!exists $ENV{PERL_INSTALL_QUIET} and
1039f11ffb7Safresh1      defined $ENV{MAKEFLAGS} and
1049f11ffb7Safresh1      $ENV{MAKEFLAGS} =~ /\b(s|silent|quiet)\b/);
105b8851fccSafresh1
106b8851fccSafresh1my $Curdir = File::Spec->curdir;
107*fac98b93Safresh1my $Perm_Dir = $ENV{PERL_CORE} ? 0770 : 0755;
108b8851fccSafresh1
109b8851fccSafresh1sub _estr(@) {
110b8851fccSafresh1    return join "\n",'!' x 72,@_,'!' x 72,'';
111b8851fccSafresh1}
112b8851fccSafresh1
113b8851fccSafresh1{my %warned;
114b8851fccSafresh1sub _warnonce(@) {
115b8851fccSafresh1    my $first=shift;
116b8851fccSafresh1    my $msg=_estr "WARNING: $first",@_;
117b8851fccSafresh1    warn $msg unless $warned{$msg}++;
118b8851fccSafresh1}}
119b8851fccSafresh1
120b8851fccSafresh1sub _choke(@) {
121b8851fccSafresh1    my $first=shift;
122b8851fccSafresh1    my $msg=_estr "ERROR: $first",@_;
1239f11ffb7Safresh1    require Carp;
124b8851fccSafresh1    Carp::croak($msg);
125b8851fccSafresh1}
126b8851fccSafresh1
1279f11ffb7Safresh1sub _croak {
1289f11ffb7Safresh1    require Carp;
1299f11ffb7Safresh1    Carp::croak(@_);
1309f11ffb7Safresh1}
1319f11ffb7Safresh1sub _confess {
1329f11ffb7Safresh1    require Carp;
1339f11ffb7Safresh1    Carp::confess(@_);
1349f11ffb7Safresh1}
1359f11ffb7Safresh1
1369f11ffb7Safresh1sub _compare {
137eac174f2Safresh1    # avoid loading File::Compare in the common case
138eac174f2Safresh1    if (-f $_[1] && -s _ == -s $_[0]) {
1399f11ffb7Safresh1        require File::Compare;
140eac174f2Safresh1        return File::Compare::compare(@_);
141eac174f2Safresh1    }
142eac174f2Safresh1    return 1;
1439f11ffb7Safresh1}
1449f11ffb7Safresh1
145b8851fccSafresh1
146b8851fccSafresh1sub _chmod($$;$) {
147b8851fccSafresh1    my ( $mode, $item, $verbose )=@_;
148b8851fccSafresh1    $verbose ||= 0;
149b8851fccSafresh1    if (chmod $mode, $item) {
150b8851fccSafresh1        printf "chmod(0%o, %s)\n",$mode, $item if $verbose > 1;
151b8851fccSafresh1    } else {
152b8851fccSafresh1        my $err="$!";
153b8851fccSafresh1        _warnonce sprintf "WARNING: Failed chmod(0%o, %s): %s\n",
154b8851fccSafresh1                  $mode, $item, $err
155b8851fccSafresh1            if -e $item;
156b8851fccSafresh1    }
157b8851fccSafresh1}
158b8851fccSafresh1
159b8851fccSafresh1=begin _private
160b8851fccSafresh1
161eac174f2Safresh1=head2 _move_file_at_boot( $file, $target, $moan  )
162b8851fccSafresh1
163b8851fccSafresh1OS-Specific, Win32/Cygwin
164b8851fccSafresh1
165b8851fccSafresh1Schedules a file to be moved/renamed/deleted at next boot.
166b8851fccSafresh1$file should be a filespec of an existing file
167b8851fccSafresh1$target should be a ref to an array if the file is to be deleted
168b8851fccSafresh1otherwise it should be a filespec for a rename. If the file is existing
169b8851fccSafresh1it will be replaced.
170b8851fccSafresh1
171b8851fccSafresh1Sets $MUST_REBOOT to 0 to indicate a deletion operation has occurred
172b8851fccSafresh1and sets it to 1 to indicate that a move operation has been requested.
173b8851fccSafresh1
174b8851fccSafresh1returns 1 on success, on failure if $moan is false errors are fatal.
175b8851fccSafresh1If $moan is true then returns 0 on error and warns instead of dies.
176b8851fccSafresh1
177b8851fccSafresh1=end _private
178b8851fccSafresh1
179b8851fccSafresh1=cut
180b8851fccSafresh1
1819f11ffb7Safresh1{
1829f11ffb7Safresh1    my $Has_Win32API_File;
183b8851fccSafresh1    sub _move_file_at_boot { #XXX OS-SPECIFIC
184b8851fccSafresh1        my ( $file, $target, $moan  )= @_;
1859f11ffb7Safresh1        _confess("Panic: Can't _move_file_at_boot on this platform!")
186eac174f2Safresh1             unless _CanMoveAtBoot;
187b8851fccSafresh1
188b8851fccSafresh1        my $descr= ref $target
189b8851fccSafresh1                    ? "'$file' for deletion"
190b8851fccSafresh1                    : "'$file' for installation as '$target'";
191b8851fccSafresh1
192eac174f2Safresh1        # *note* _CanMoveAtBoot is only incidentally the same condition as below
1939f11ffb7Safresh1        # this needs not hold true in the future.
194eac174f2Safresh1        $Has_Win32API_File = (_Is_Win32 || _Is_cygwin)
1959f11ffb7Safresh1            ? (eval {require Win32API::File; 1} || 0)
1969f11ffb7Safresh1            : 0 unless defined $Has_Win32API_File;
197b8851fccSafresh1        if ( ! $Has_Win32API_File ) {
198b8851fccSafresh1
199b8851fccSafresh1            my @msg=(
200b8851fccSafresh1                "Cannot schedule $descr at reboot.",
201b8851fccSafresh1                "Try installing Win32API::File to allow operations on locked files",
202b8851fccSafresh1                "to be scheduled during reboot. Or try to perform the operation by",
203b8851fccSafresh1                "hand yourself. (You may need to close other perl processes first)"
204b8851fccSafresh1            );
205b8851fccSafresh1            if ( $moan ) { _warnonce(@msg) } else { _choke(@msg) }
206b8851fccSafresh1            return 0;
207b8851fccSafresh1        }
208b8851fccSafresh1        my $opts= Win32API::File::MOVEFILE_DELAY_UNTIL_REBOOT();
209b8851fccSafresh1        $opts= $opts | Win32API::File::MOVEFILE_REPLACE_EXISTING()
210b8851fccSafresh1            unless ref $target;
211b8851fccSafresh1
212b8851fccSafresh1        _chmod( 0666, $file );
213b8851fccSafresh1        _chmod( 0666, $target ) unless ref $target;
214b8851fccSafresh1
215b8851fccSafresh1        if (Win32API::File::MoveFileEx( $file, $target, $opts )) {
216b8851fccSafresh1            $MUST_REBOOT ||= ref $target ? 0 : 1;
217b8851fccSafresh1            return 1;
218b8851fccSafresh1        } else {
219b8851fccSafresh1            my @msg=(
220b8851fccSafresh1                "MoveFileEx $descr at reboot failed: $^E",
221b8851fccSafresh1                "You may try to perform the operation by hand yourself. ",
222b8851fccSafresh1                "(You may need to close other perl processes first).",
223b8851fccSafresh1            );
224b8851fccSafresh1            if ( $moan ) { _warnonce(@msg) } else { _choke(@msg) }
225b8851fccSafresh1        }
226b8851fccSafresh1        return 0;
227b8851fccSafresh1    }
2289f11ffb7Safresh1}
229b8851fccSafresh1
230b8851fccSafresh1
231b8851fccSafresh1=begin _private
232b8851fccSafresh1
233eac174f2Safresh1=head2 _unlink_or_rename( $file, $tryhard, $installing )
234b8851fccSafresh1
235b8851fccSafresh1OS-Specific, Win32/Cygwin
236b8851fccSafresh1
237b8851fccSafresh1Tries to get a file out of the way by unlinking it or renaming it. On
238b8851fccSafresh1some OS'es (Win32 based) DLL files can end up locked such that they can
239b8851fccSafresh1be renamed but not deleted. Likewise sometimes a file can be locked such
240b8851fccSafresh1that it cant even be renamed or changed except at reboot. To handle
241b8851fccSafresh1these cases this routine finds a tempfile name that it can either rename
242b8851fccSafresh1the file out of the way or use as a proxy for the install so that the
243b8851fccSafresh1rename can happen later (at reboot).
244b8851fccSafresh1
245b8851fccSafresh1  $file : the file to remove.
246b8851fccSafresh1  $tryhard : should advanced tricks be used for deletion
247b8851fccSafresh1  $installing : we are not merely deleting but we want to overwrite
248b8851fccSafresh1
249b8851fccSafresh1When $tryhard is not true if the unlink fails its fatal. When $tryhard
250b8851fccSafresh1is true then the file is attempted to be renamed. The renamed file is
251b8851fccSafresh1then scheduled for deletion. If the rename fails then $installing
252b8851fccSafresh1governs what happens. If it is false the failure is fatal. If it is true
253b8851fccSafresh1then an attempt is made to schedule installation at boot using a
254b8851fccSafresh1temporary file to hold the new file. If this fails then a fatal error is
255b8851fccSafresh1thrown, if it succeeds it returns the temporary file name (which will be
256b8851fccSafresh1a derivative of the original in the same directory) so that the caller can
257b8851fccSafresh1use it to install under. In all other cases of success returns $file.
258b8851fccSafresh1On failure throws a fatal error.
259b8851fccSafresh1
260b8851fccSafresh1=end _private
261b8851fccSafresh1
262b8851fccSafresh1=cut
263b8851fccSafresh1
264b8851fccSafresh1sub _unlink_or_rename { #XXX OS-SPECIFIC
265b8851fccSafresh1    my ( $file, $tryhard, $installing )= @_;
266b8851fccSafresh1
267b8851fccSafresh1    # this chmod was originally unconditional. However, its not needed on
268b8851fccSafresh1    # POSIXy systems since permission to unlink a file is specified by the
269b8851fccSafresh1    # directory rather than the file; and in fact it screwed up hard- and
270b8851fccSafresh1    # symlinked files. Keep it for other platforms in case its still
271b8851fccSafresh1    # needed there.
272b8851fccSafresh1    if ($^O =~ /^(dos|os2|MSWin32|VMS)$/) {
273b8851fccSafresh1        _chmod( 0666, $file );
274b8851fccSafresh1    }
275b8851fccSafresh1    my $unlink_count = 0;
276b8851fccSafresh1    while (unlink $file) { $unlink_count++; }
277b8851fccSafresh1    return $file if $unlink_count > 0;
278b8851fccSafresh1    my $error="$!";
279b8851fccSafresh1
280b8851fccSafresh1    _choke("Cannot unlink '$file': $!")
281eac174f2Safresh1          unless _CanMoveAtBoot && $tryhard;
282b8851fccSafresh1
283b8851fccSafresh1    my $tmp= "AAA";
284b8851fccSafresh1    ++$tmp while -e "$file.$tmp";
285b8851fccSafresh1    $tmp= "$file.$tmp";
286b8851fccSafresh1
287b8851fccSafresh1    warn "WARNING: Unable to unlink '$file': $error\n",
288b8851fccSafresh1         "Going to try to rename it to '$tmp'.\n";
289b8851fccSafresh1
290b8851fccSafresh1    if ( rename $file, $tmp ) {
291b8851fccSafresh1        warn "Rename successful. Scheduling '$tmp'\nfor deletion at reboot.\n";
292b8851fccSafresh1        # when $installing we can set $moan to true.
293b8851fccSafresh1        # IOW, if we cant delete the renamed file at reboot its
294b8851fccSafresh1        # not the end of the world. The other cases are more serious
295b8851fccSafresh1        # and need to be fatal.
296b8851fccSafresh1        _move_file_at_boot( $tmp, [], $installing );
297b8851fccSafresh1        return $file;
298b8851fccSafresh1    } elsif ( $installing ) {
299b8851fccSafresh1        _warnonce("Rename failed: $!. Scheduling '$tmp'\nfor".
300b8851fccSafresh1             " installation as '$file' at reboot.\n");
301b8851fccSafresh1        _move_file_at_boot( $tmp, $file );
302b8851fccSafresh1        return $tmp;
303b8851fccSafresh1    } else {
304b8851fccSafresh1        _choke("Rename failed:$!", "Cannot proceed.");
305b8851fccSafresh1    }
306b8851fccSafresh1
307b8851fccSafresh1}
308b8851fccSafresh1
309eac174f2Safresh1=head1 Functions
310b8851fccSafresh1
311b8851fccSafresh1=begin _private
312b8851fccSafresh1
313eac174f2Safresh1=head2 _get_install_skip
314b8851fccSafresh1
315b8851fccSafresh1Handles loading the INSTALL.SKIP file. Returns an array of patterns to use.
316b8851fccSafresh1
317b8851fccSafresh1=cut
318b8851fccSafresh1
319b8851fccSafresh1sub _get_install_skip {
320b8851fccSafresh1    my ( $skip, $verbose )= @_;
321b8851fccSafresh1    if ($ENV{EU_INSTALL_IGNORE_SKIP}) {
322b8851fccSafresh1        print "EU_INSTALL_IGNORE_SKIP is set, ignore skipfile settings\n"
323b8851fccSafresh1            if $verbose>2;
324b8851fccSafresh1        return [];
325b8851fccSafresh1    }
326b8851fccSafresh1    if ( ! defined $skip ) {
327b8851fccSafresh1        print "Looking for install skip list\n"
328b8851fccSafresh1            if $verbose>2;
329b8851fccSafresh1        for my $file ( 'INSTALL.SKIP', $ENV{EU_INSTALL_SITE_SKIPFILE} ) {
330b8851fccSafresh1            next unless $file;
331b8851fccSafresh1            print "\tChecking for $file\n"
332b8851fccSafresh1                if $verbose>2;
333b8851fccSafresh1            if (-e $file) {
334b8851fccSafresh1                $skip= $file;
335b8851fccSafresh1                last;
336b8851fccSafresh1            }
337b8851fccSafresh1        }
338b8851fccSafresh1    }
339b8851fccSafresh1    if ($skip && !ref $skip) {
340b8851fccSafresh1        print "Reading skip patterns from '$skip'.\n"
341b8851fccSafresh1            if $verbose;
342b8851fccSafresh1        if (open my $fh,$skip ) {
343b8851fccSafresh1            my @patterns;
344b8851fccSafresh1            while (<$fh>) {
345b8851fccSafresh1                chomp;
346b8851fccSafresh1                next if /^\s*(?:#|$)/;
347b8851fccSafresh1                print "\tSkip pattern: $_\n" if $verbose>3;
348b8851fccSafresh1                push @patterns, $_;
349b8851fccSafresh1            }
350b8851fccSafresh1            $skip= \@patterns;
351b8851fccSafresh1        } else {
352b8851fccSafresh1            warn "Can't read skip file:'$skip':$!\n";
353b8851fccSafresh1            $skip=[];
354b8851fccSafresh1        }
355b8851fccSafresh1    } elsif ( UNIVERSAL::isa($skip,'ARRAY') ) {
356b8851fccSafresh1        print "Using array for skip list\n"
357b8851fccSafresh1            if $verbose>2;
358b8851fccSafresh1    } elsif ($verbose) {
359b8851fccSafresh1        print "No skip list found.\n"
360b8851fccSafresh1            if $verbose>1;
361b8851fccSafresh1        $skip= [];
362b8851fccSafresh1    }
363b8851fccSafresh1    warn "Got @{[0+@$skip]} skip patterns.\n"
364b8851fccSafresh1        if $verbose>3;
365b8851fccSafresh1    return $skip
366b8851fccSafresh1}
367b8851fccSafresh1
368eac174f2Safresh1=head2 _have_write_access
369b8851fccSafresh1
370b8851fccSafresh1Abstract a -w check that tries to use POSIX::access() if possible.
371b8851fccSafresh1
372b8851fccSafresh1=cut
373b8851fccSafresh1
374b8851fccSafresh1{
375b8851fccSafresh1    my  $has_posix;
376b8851fccSafresh1    sub _have_write_access {
377b8851fccSafresh1        my $dir=shift;
378b8851fccSafresh1        unless (defined $has_posix) {
379eac174f2Safresh1            $has_posix = (!_Is_cygwin && !_Is_Win32
3809f11ffb7Safresh1             && eval { local $^W; require POSIX; 1} ) || 0;
381b8851fccSafresh1        }
382b8851fccSafresh1        if ($has_posix) {
383b8851fccSafresh1            return POSIX::access($dir, POSIX::W_OK());
384b8851fccSafresh1        } else {
385b8851fccSafresh1            return -w $dir;
386b8851fccSafresh1        }
387b8851fccSafresh1    }
388b8851fccSafresh1}
389b8851fccSafresh1
390eac174f2Safresh1=head2 _can_write_dir(C<$dir>)
391b8851fccSafresh1
392b8851fccSafresh1Checks whether a given directory is writable, taking account
393b8851fccSafresh1the possibility that the directory might not exist and would have to
394b8851fccSafresh1be created first.
395b8851fccSafresh1
396b8851fccSafresh1Returns a list, containing: C<($writable, $determined_by, @create)>
397b8851fccSafresh1
398b8851fccSafresh1C<$writable> says whether the directory is (hypothetically) writable
399b8851fccSafresh1
400b8851fccSafresh1C<$determined_by> is the directory the status was determined from. It will be
401b8851fccSafresh1either the C<$dir>, or one of its parents.
402b8851fccSafresh1
403b8851fccSafresh1C<@create> is a list of directories that would probably have to be created
404b8851fccSafresh1to make the requested directory. It may not actually be correct on
405b8851fccSafresh1relative paths with C<..> in them. But for our purposes it should work ok
406b8851fccSafresh1
407b8851fccSafresh1=cut
408b8851fccSafresh1
409b8851fccSafresh1sub _can_write_dir {
410b8851fccSafresh1    my $dir=shift;
411b8851fccSafresh1    return
412b8851fccSafresh1        unless defined $dir and length $dir;
413b8851fccSafresh1
414b8851fccSafresh1    my ($vol, $dirs, $file) = File::Spec->splitpath($dir,1);
415b8851fccSafresh1    my @dirs = File::Spec->splitdir($dirs);
416b8851fccSafresh1    unshift @dirs, File::Spec->curdir
417b8851fccSafresh1        unless File::Spec->file_name_is_absolute($dir);
418b8851fccSafresh1
419b8851fccSafresh1    my $path='';
420b8851fccSafresh1    my @make;
421b8851fccSafresh1    while (@dirs) {
422eac174f2Safresh1        if (_Is_VMS) {
423b8851fccSafresh1            $dir = File::Spec->catdir($vol,@dirs);
424b8851fccSafresh1        }
425b8851fccSafresh1        else {
426b8851fccSafresh1            $dir = File::Spec->catdir(@dirs);
427b8851fccSafresh1            $dir = File::Spec->catpath($vol,$dir,'')
428b8851fccSafresh1                    if defined $vol and length $vol;
429b8851fccSafresh1        }
430b8851fccSafresh1        next if ( $dir eq $path );
431b8851fccSafresh1        if ( ! -e $dir ) {
432b8851fccSafresh1            unshift @make,$dir;
433b8851fccSafresh1            next;
434b8851fccSafresh1        }
435b8851fccSafresh1        if ( _have_write_access($dir) ) {
436b8851fccSafresh1            return 1,$dir,@make
437b8851fccSafresh1        } else {
438b8851fccSafresh1            return 0,$dir,@make
439b8851fccSafresh1        }
440b8851fccSafresh1    } continue {
441b8851fccSafresh1        pop @dirs;
442b8851fccSafresh1    }
443b8851fccSafresh1    return 0;
444b8851fccSafresh1}
445b8851fccSafresh1
446eac174f2Safresh1=head2 _mkpath($dir,$show,$mode,$verbose,$dry_run)
447b8851fccSafresh1
448b8851fccSafresh1Wrapper around File::Path::mkpath() to handle errors.
449b8851fccSafresh1
450b8851fccSafresh1If $verbose is true and >1 then additional diagnostics will be produced, also
451b8851fccSafresh1this will force $show to true.
452b8851fccSafresh1
453b8851fccSafresh1If $dry_run is true then the directory will not be created but a check will be
454b8851fccSafresh1made to see whether it would be possible to write to the directory, or that
455b8851fccSafresh1it would be possible to create the directory.
456b8851fccSafresh1
457b8851fccSafresh1If $dry_run is not true dies if the directory can not be created or is not
458b8851fccSafresh1writable.
459b8851fccSafresh1
460b8851fccSafresh1=cut
461b8851fccSafresh1
462b8851fccSafresh1sub _mkpath {
463b8851fccSafresh1    my ($dir,$show,$mode,$verbose,$dry_run)=@_;
464b8851fccSafresh1    if ( $verbose && $verbose > 1 && ! -d $dir) {
465b8851fccSafresh1        $show= 1;
466b8851fccSafresh1        printf "mkpath(%s,%d,%#o)\n", $dir, $show, $mode;
467b8851fccSafresh1    }
468b8851fccSafresh1    if (!$dry_run) {
469eac174f2Safresh1        my @created;
470eac174f2Safresh1        eval {
471eac174f2Safresh1            @created = File::Path::mkpath($dir,$show,$mode);
472eac174f2Safresh1            1;
473eac174f2Safresh1        } or _choke("Can't create '$dir'","$@");
474eac174f2Safresh1        # if we created any directories, we were able to write and don't need
475eac174f2Safresh1        # extra checks
476eac174f2Safresh1        if (@created) {
477eac174f2Safresh1            return;
478b8851fccSafresh1        }
479b8851fccSafresh1    }
480b8851fccSafresh1    my ($can,$root,@make)=_can_write_dir($dir);
481b8851fccSafresh1    if (!$can) {
482b8851fccSafresh1        my @msg=(
483b8851fccSafresh1            "Can't create '$dir'",
484b8851fccSafresh1            $root ? "Do not have write permissions on '$root'"
485b8851fccSafresh1                  : "Unknown Error"
486b8851fccSafresh1        );
487b8851fccSafresh1        if ($dry_run) {
488b8851fccSafresh1            _warnonce @msg;
489b8851fccSafresh1        } else {
490b8851fccSafresh1            _choke @msg;
491b8851fccSafresh1        }
492b8851fccSafresh1    } elsif ($show and $dry_run) {
493b8851fccSafresh1        print "$_\n" for @make;
494b8851fccSafresh1    }
495b8851fccSafresh1
496b8851fccSafresh1}
497b8851fccSafresh1
498eac174f2Safresh1=head2 _copy($from,$to,$verbose,$dry_run)
499b8851fccSafresh1
500b8851fccSafresh1Wrapper around File::Copy::copy to handle errors.
501b8851fccSafresh1
502b8851fccSafresh1If $verbose is true and >1 then additional diagnostics will be emitted.
503b8851fccSafresh1
504b8851fccSafresh1If $dry_run is true then the copy will not actually occur.
505b8851fccSafresh1
506b8851fccSafresh1Dies if the copy fails.
507b8851fccSafresh1
508b8851fccSafresh1=cut
509b8851fccSafresh1
510b8851fccSafresh1sub _copy {
511b8851fccSafresh1    my ( $from, $to, $verbose, $dry_run)=@_;
512b8851fccSafresh1    if ($verbose && $verbose>1) {
513b8851fccSafresh1        printf "copy(%s,%s)\n", $from, $to;
514b8851fccSafresh1    }
515b8851fccSafresh1    if (!$dry_run) {
516b8851fccSafresh1        File::Copy::copy($from,$to)
5179f11ffb7Safresh1            or _croak( _estr "ERROR: Cannot copy '$from' to '$to': $!" );
518b8851fccSafresh1    }
519b8851fccSafresh1}
520b8851fccSafresh1
521b8851fccSafresh1=pod
522b8851fccSafresh1
523eac174f2Safresh1=head2 _chdir($from)
524b8851fccSafresh1
525b8851fccSafresh1Wrapper around chdir to catch errors.
526b8851fccSafresh1
527b8851fccSafresh1If not called in void context returns the cwd from before the chdir.
528b8851fccSafresh1
529b8851fccSafresh1dies on error.
530b8851fccSafresh1
531b8851fccSafresh1=cut
532b8851fccSafresh1
533b8851fccSafresh1sub _chdir {
534b8851fccSafresh1    my ($dir)= @_;
535b8851fccSafresh1    my $ret;
536b8851fccSafresh1    if (defined wantarray) {
537b8851fccSafresh1        $ret= cwd;
538b8851fccSafresh1    }
539b8851fccSafresh1    chdir $dir
540b8851fccSafresh1        or _choke("Couldn't chdir to '$dir': $!");
541b8851fccSafresh1    return $ret;
542b8851fccSafresh1}
543b8851fccSafresh1
544b8851fccSafresh1=end _private
545b8851fccSafresh1
546eac174f2Safresh1=head2 install
547b8851fccSafresh1
548b8851fccSafresh1    # deprecated forms
549b8851fccSafresh1    install(\%from_to);
550b8851fccSafresh1    install(\%from_to, $verbose, $dry_run, $uninstall_shadows,
551b8851fccSafresh1                $skip, $always_copy, \%result);
552b8851fccSafresh1
553b8851fccSafresh1    # recommended form as of 1.47
554b8851fccSafresh1    install([
555b8851fccSafresh1        from_to => \%from_to,
556b8851fccSafresh1        verbose => 1,
557b8851fccSafresh1        dry_run => 0,
558b8851fccSafresh1        uninstall_shadows => 1,
559b8851fccSafresh1        skip => undef,
560b8851fccSafresh1        always_copy => 1,
561b8851fccSafresh1        result => \%install_results,
562b8851fccSafresh1    ]);
563b8851fccSafresh1
564b8851fccSafresh1
565b8851fccSafresh1Copies each directory tree of %from_to to its corresponding value
566b8851fccSafresh1preserving timestamps and permissions.
567b8851fccSafresh1
568b8851fccSafresh1There are two keys with a special meaning in the hash: "read" and
569b8851fccSafresh1"write".  These contain packlist files.  After the copying is done,
570b8851fccSafresh1install() will write the list of target files to $from_to{write}. If
571b8851fccSafresh1$from_to{read} is given the contents of this file will be merged into
572b8851fccSafresh1the written file. The read and the written file may be identical, but
573b8851fccSafresh1on AFS it is quite likely that people are installing to a different
574b8851fccSafresh1directory than the one where the files later appear.
575b8851fccSafresh1
576b8851fccSafresh1If $verbose is true, will print out each file removed.  Default is
577b8851fccSafresh1false.  This is "make install VERBINST=1". $verbose values going
578b8851fccSafresh1up to 5 show increasingly more diagnostics output.
579b8851fccSafresh1
580b8851fccSafresh1If $dry_run is true it will only print what it was going to do
581b8851fccSafresh1without actually doing it.  Default is false.
582b8851fccSafresh1
583b8851fccSafresh1If $uninstall_shadows is true any differing versions throughout @INC
584b8851fccSafresh1will be uninstalled.  This is "make install UNINST=1"
585b8851fccSafresh1
586b8851fccSafresh1As of 1.37_02 install() supports the use of a list of patterns to filter out
587b8851fccSafresh1files that shouldn't be installed. If $skip is omitted or undefined then
588b8851fccSafresh1install will try to read the list from INSTALL.SKIP in the CWD. This file is
589b8851fccSafresh1a list of regular expressions and is just like the MANIFEST.SKIP file used
590b8851fccSafresh1by L<ExtUtils::Manifest>.
591b8851fccSafresh1
592b8851fccSafresh1A default site INSTALL.SKIP may be provided by setting then environment
593b8851fccSafresh1variable EU_INSTALL_SITE_SKIPFILE, this will only be used when there isn't a
594b8851fccSafresh1distribution specific INSTALL.SKIP. If the environment variable
595b8851fccSafresh1EU_INSTALL_IGNORE_SKIP is true then no install file filtering will be
596b8851fccSafresh1performed.
597b8851fccSafresh1
598b8851fccSafresh1If $skip is undefined then the skip file will be autodetected and used if it
599b8851fccSafresh1is found. If $skip is a reference to an array then it is assumed the array
600b8851fccSafresh1contains the list of patterns, if $skip is a true non reference it is
601b8851fccSafresh1assumed to be the filename holding the list of patterns, any other value of
602b8851fccSafresh1$skip is taken to mean that no install filtering should occur.
603b8851fccSafresh1
604b8851fccSafresh1B<Changes As of Version 1.47>
605b8851fccSafresh1
606b8851fccSafresh1As of version 1.47 the following additions were made to the install interface.
607b8851fccSafresh1Note that the new argument style and use of the %result hash is recommended.
608b8851fccSafresh1
609b8851fccSafresh1The $always_copy parameter which when true causes files to be updated
610b8851fccSafresh1regardless as to whether they have changed, if it is defined but false then
611b8851fccSafresh1copies are made only if the files have changed, if it is undefined then the
612b8851fccSafresh1value of the environment variable EU_INSTALL_ALWAYS_COPY is used as default.
613b8851fccSafresh1
614b8851fccSafresh1The %result hash will be populated with the various keys/subhashes reflecting
615b8851fccSafresh1the install. Currently these keys and their structure are:
616b8851fccSafresh1
617b8851fccSafresh1    install             => { $target    => $source },
618b8851fccSafresh1    install_fail        => { $target    => $source },
619b8851fccSafresh1    install_unchanged   => { $target    => $source },
620b8851fccSafresh1
621b8851fccSafresh1    install_filtered    => { $source    => $pattern },
622b8851fccSafresh1
623b8851fccSafresh1    uninstall           => { $uninstalled => $source },
624b8851fccSafresh1    uninstall_fail      => { $uninstalled => $source },
625b8851fccSafresh1
626b8851fccSafresh1where C<$source> is the filespec of the file being installed. C<$target> is where
627b8851fccSafresh1it is being installed to, and C<$uninstalled> is any shadow file that is in C<@INC>
628b8851fccSafresh1or C<$ENV{PERL5LIB}> or other standard locations, and C<$pattern> is the pattern that
629b8851fccSafresh1caused a source file to be skipped. In future more keys will be added, such as to
630b8851fccSafresh1show created directories, however this requires changes in other modules and must
631b8851fccSafresh1therefore wait.
632b8851fccSafresh1
633b8851fccSafresh1These keys will be populated before any exceptions are thrown should there be an
634b8851fccSafresh1error.
635b8851fccSafresh1
636b8851fccSafresh1Note that all updates of the %result are additive, the hash will not be
637b8851fccSafresh1cleared before use, thus allowing status results of many installs to be easily
638b8851fccSafresh1aggregated.
639b8851fccSafresh1
640b8851fccSafresh1B<NEW ARGUMENT STYLE>
641b8851fccSafresh1
642b8851fccSafresh1If there is only one argument and it is a reference to an array then
643b8851fccSafresh1the array is assumed to contain a list of key-value pairs specifying
644b8851fccSafresh1the options. In this case the option "from_to" is mandatory. This style
645b8851fccSafresh1means that you do not have to supply a cryptic list of arguments and can
646b8851fccSafresh1use a self documenting argument list that is easier to understand.
647b8851fccSafresh1
648b8851fccSafresh1This is now the recommended interface to install().
649b8851fccSafresh1
650b8851fccSafresh1B<RETURN>
651b8851fccSafresh1
652b8851fccSafresh1If all actions were successful install will return a hashref of the results
653b8851fccSafresh1as described above for the $result parameter. If any action is a failure
654b8851fccSafresh1then install will die, therefore it is recommended to pass in the $result
655b8851fccSafresh1parameter instead of using the return value. If the result parameter is
656b8851fccSafresh1provided then the returned hashref will be the passed in hashref.
657b8851fccSafresh1
658b8851fccSafresh1=cut
659b8851fccSafresh1
660b8851fccSafresh1sub install { #XXX OS-SPECIFIC
661b8851fccSafresh1    my($from_to,$verbose,$dry_run,$uninstall_shadows,$skip,$always_copy,$result) = @_;
662b8851fccSafresh1    if (@_==1 and eval { 1+@$from_to }) {
663b8851fccSafresh1        my %opts        = @$from_to;
664b8851fccSafresh1        $from_to        = $opts{from_to}
6659f11ffb7Safresh1                            or _confess("from_to is a mandatory parameter");
666b8851fccSafresh1        $verbose        = $opts{verbose};
667b8851fccSafresh1        $dry_run        = $opts{dry_run};
668b8851fccSafresh1        $uninstall_shadows  = $opts{uninstall_shadows};
669b8851fccSafresh1        $skip           = $opts{skip};
670b8851fccSafresh1        $always_copy    = $opts{always_copy};
671b8851fccSafresh1        $result         = $opts{result};
672b8851fccSafresh1    }
673b8851fccSafresh1
674b8851fccSafresh1    $result ||= {};
675b8851fccSafresh1    $verbose ||= 0;
676b8851fccSafresh1    $dry_run  ||= 0;
677b8851fccSafresh1
678b8851fccSafresh1    $skip= _get_install_skip($skip,$verbose);
679b8851fccSafresh1    $always_copy =  $ENV{EU_INSTALL_ALWAYS_COPY}
680b8851fccSafresh1                 || $ENV{EU_ALWAYS_COPY}
681b8851fccSafresh1                 || 0
682b8851fccSafresh1        unless defined $always_copy;
683b8851fccSafresh1
684b8851fccSafresh1    my(%from_to) = %$from_to;
685b8851fccSafresh1    my(%pack, $dir, %warned);
6869f11ffb7Safresh1    require ExtUtils::Packlist;
687b8851fccSafresh1    my($packlist) = ExtUtils::Packlist->new();
688b8851fccSafresh1
689b8851fccSafresh1    local(*DIR);
690b8851fccSafresh1    for (qw/read write/) {
691b8851fccSafresh1        $pack{$_}=$from_to{$_};
692b8851fccSafresh1        delete $from_to{$_};
693b8851fccSafresh1    }
694b8851fccSafresh1    my $tmpfile = install_rooted_file($pack{"read"});
695b8851fccSafresh1    $packlist->read($tmpfile) if (-f $tmpfile);
696b8851fccSafresh1    my $cwd = cwd();
697b8851fccSafresh1    my @found_files;
698b8851fccSafresh1    my %check_dirs;
6999f11ffb7Safresh1    require File::Find;
7009f11ffb7Safresh1
7019f11ffb7Safresh1    my $blib_lib  = File::Spec->catdir('blib', 'lib');
7029f11ffb7Safresh1    my $blib_arch = File::Spec->catdir('blib', 'arch');
7039f11ffb7Safresh1
7049f11ffb7Safresh1    # File::Find seems to always be Unixy except on MacPerl :(
7059f11ffb7Safresh1    my $current_directory = $^O eq 'MacOS' ? $Curdir : '.';
706b8851fccSafresh1
707b8851fccSafresh1    MOD_INSTALL: foreach my $source (sort keys %from_to) {
708b8851fccSafresh1        #copy the tree to the target directory without altering
709b8851fccSafresh1        #timestamp and permission and remember for the .packlist
710b8851fccSafresh1        #file. The packlist file contains the absolute paths of the
711b8851fccSafresh1        #install locations. AFS users may call this a bug. We'll have
712b8851fccSafresh1        #to reconsider how to add the means to satisfy AFS users also.
713b8851fccSafresh1
714b8851fccSafresh1        #October 1997: we want to install .pm files into archlib if
715b8851fccSafresh1        #there are any files in arch. So we depend on having ./blib/arch
716b8851fccSafresh1        #hardcoded here.
717b8851fccSafresh1
718b8851fccSafresh1        my $targetroot = install_rooted_dir($from_to{$source});
719b8851fccSafresh1
720b8851fccSafresh1        if ($source eq $blib_lib and
721b8851fccSafresh1            exists $from_to{$blib_arch} and
722b8851fccSafresh1            directory_not_empty($blib_arch)
723b8851fccSafresh1        ){
724b8851fccSafresh1            $targetroot = install_rooted_dir($from_to{$blib_arch});
725b8851fccSafresh1            print "Files found in $blib_arch: installing files in $blib_lib into architecture dependent library tree\n";
726b8851fccSafresh1        }
727b8851fccSafresh1
728b8851fccSafresh1        next unless -d $source;
729b8851fccSafresh1        _chdir($source);
730b8851fccSafresh1        # 5.5.3's File::Find missing no_chdir option
731b8851fccSafresh1        # XXX OS-SPECIFIC
7329f11ffb7Safresh1        File::Find::find(sub {
733b8851fccSafresh1            my ($mode,$size,$atime,$mtime) = (stat)[2,7,8,9];
734b8851fccSafresh1
735b8851fccSafresh1            return if !-f _;
736b8851fccSafresh1            my $origfile = $_;
737b8851fccSafresh1
738b8851fccSafresh1            return if $origfile eq ".exists";
739b8851fccSafresh1            my $targetdir  = File::Spec->catdir($targetroot, $File::Find::dir);
740b8851fccSafresh1            my $targetfile = File::Spec->catfile($targetdir, $origfile);
741b8851fccSafresh1            my $sourcedir  = File::Spec->catdir($source, $File::Find::dir);
742b8851fccSafresh1            my $sourcefile = File::Spec->catfile($sourcedir, $origfile);
743b8851fccSafresh1
744b8851fccSafresh1            for my $pat (@$skip) {
745b8851fccSafresh1                if ( $sourcefile=~/$pat/ ) {
746b8851fccSafresh1                    print "Skipping $targetfile (filtered)\n"
747b8851fccSafresh1                        if $verbose>1;
748b8851fccSafresh1                    $result->{install_filtered}{$sourcefile} = $pat;
749b8851fccSafresh1                    return;
750b8851fccSafresh1                }
751b8851fccSafresh1            }
752b8851fccSafresh1            # we have to do this for back compat with old File::Finds
753b8851fccSafresh1            # and because the target is relative
754eac174f2Safresh1            my $save_cwd = File::Spec->catfile($cwd, $sourcedir);
755eac174f2Safresh1            _chdir($cwd);
756eac174f2Safresh1            my $diff = $always_copy || _compare($sourcefile, $targetfile);
757b8851fccSafresh1            $check_dirs{$targetdir}++
758b8851fccSafresh1                unless -w $targetfile;
759b8851fccSafresh1
760b8851fccSafresh1            push @found_files,
761b8851fccSafresh1                [ $diff, $File::Find::dir, $origfile,
762b8851fccSafresh1                  $mode, $size, $atime, $mtime,
763b8851fccSafresh1                  $targetdir, $targetfile, $sourcedir, $sourcefile,
764b8851fccSafresh1
765b8851fccSafresh1                ];
766b8851fccSafresh1            #restore the original directory we were in when File::Find
767b8851fccSafresh1            #called us so that it doesn't get horribly confused.
768b8851fccSafresh1            _chdir($save_cwd);
769b8851fccSafresh1        }, $current_directory );
770b8851fccSafresh1        _chdir($cwd);
771b8851fccSafresh1    }
772b8851fccSafresh1    foreach my $targetdir (sort keys %check_dirs) {
773*fac98b93Safresh1        _mkpath( $targetdir, 0, $Perm_Dir, $verbose, $dry_run );
774b8851fccSafresh1    }
775b8851fccSafresh1    foreach my $found (@found_files) {
776b8851fccSafresh1        my ($diff, $ffd, $origfile, $mode, $size, $atime, $mtime,
777b8851fccSafresh1            $targetdir, $targetfile, $sourcedir, $sourcefile)= @$found;
778b8851fccSafresh1
779b8851fccSafresh1        my $realtarget= $targetfile;
780b8851fccSafresh1        if ($diff) {
781b8851fccSafresh1            eval {
782b8851fccSafresh1                if (-f $targetfile) {
783b8851fccSafresh1                    print "_unlink_or_rename($targetfile)\n" if $verbose>1;
784b8851fccSafresh1                    $targetfile= _unlink_or_rename( $targetfile, 'tryhard', 'install' )
785b8851fccSafresh1                        unless $dry_run;
786b8851fccSafresh1                } elsif ( ! -d $targetdir ) {
787*fac98b93Safresh1                    _mkpath( $targetdir, 0, $Perm_Dir, $verbose, $dry_run );
788b8851fccSafresh1                }
789b8851fccSafresh1                print "Installing $targetfile\n";
790b8851fccSafresh1
791b8851fccSafresh1                _copy( $sourcefile, $targetfile, $verbose, $dry_run, );
792b8851fccSafresh1
793b8851fccSafresh1
794b8851fccSafresh1                #XXX OS-SPECIFIC
795b8851fccSafresh1                print "utime($atime,$mtime,$targetfile)\n" if $verbose>1;
796eac174f2Safresh1                utime($atime,$mtime + _Is_VMS,$targetfile) unless $dry_run>1;
797b8851fccSafresh1
798b8851fccSafresh1
799b8851fccSafresh1                $mode = 0444 | ( $mode & 0111 ? 0111 : 0 );
800b8851fccSafresh1                $mode = $mode | 0222
801b8851fccSafresh1                    if $realtarget ne $targetfile;
802b8851fccSafresh1                _chmod( $mode, $targetfile, $verbose );
803b8851fccSafresh1                $result->{install}{$targetfile} = $sourcefile;
804b8851fccSafresh1                1
805b8851fccSafresh1            } or do {
806b8851fccSafresh1                $result->{install_fail}{$targetfile} = $sourcefile;
807b8851fccSafresh1                die $@;
808b8851fccSafresh1            };
809b8851fccSafresh1        } else {
810b8851fccSafresh1            $result->{install_unchanged}{$targetfile} = $sourcefile;
811b8851fccSafresh1            print "Skipping $targetfile (unchanged)\n" if $verbose;
812b8851fccSafresh1        }
813b8851fccSafresh1
814b8851fccSafresh1        if ( $uninstall_shadows ) {
815b8851fccSafresh1            inc_uninstall($sourcefile,$ffd, $verbose,
816b8851fccSafresh1                          $dry_run,
817b8851fccSafresh1                          $realtarget ne $targetfile ? $realtarget : "",
818b8851fccSafresh1                          $result);
819b8851fccSafresh1        }
820b8851fccSafresh1
821b8851fccSafresh1        # Record the full pathname.
822b8851fccSafresh1        $packlist->{$targetfile}++;
823b8851fccSafresh1    }
824b8851fccSafresh1
825b8851fccSafresh1    if ($pack{'write'}) {
826b8851fccSafresh1        $dir = install_rooted_dir(dirname($pack{'write'}));
827*fac98b93Safresh1        _mkpath( $dir, 0, $Perm_Dir, $verbose, $dry_run );
828b8851fccSafresh1        print "Writing $pack{'write'}\n" if $verbose;
829b8851fccSafresh1        $packlist->write(install_rooted_file($pack{'write'})) unless $dry_run;
830b8851fccSafresh1    }
831b8851fccSafresh1
832b8851fccSafresh1    _do_cleanup($verbose);
833b8851fccSafresh1    return $result;
834b8851fccSafresh1}
835b8851fccSafresh1
836b8851fccSafresh1=begin _private
837b8851fccSafresh1
838eac174f2Safresh1=head2 _do_cleanup
839b8851fccSafresh1
840b8851fccSafresh1Standardize finish event for after another instruction has occurred.
841b8851fccSafresh1Handles converting $MUST_REBOOT to a die for instance.
842b8851fccSafresh1
843b8851fccSafresh1=end _private
844b8851fccSafresh1
845b8851fccSafresh1=cut
846b8851fccSafresh1
847b8851fccSafresh1sub _do_cleanup {
848b8851fccSafresh1    my ($verbose) = @_;
849b8851fccSafresh1    if ($MUST_REBOOT) {
850b8851fccSafresh1        die _estr "Operation not completed! ",
851b8851fccSafresh1            "You must reboot to complete the installation.",
852b8851fccSafresh1            "Sorry.";
853b8851fccSafresh1    } elsif (defined $MUST_REBOOT & $verbose) {
854b8851fccSafresh1        warn _estr "Installation will be completed at the next reboot.\n",
855b8851fccSafresh1             "However it is not necessary to reboot immediately.\n";
856b8851fccSafresh1    }
857b8851fccSafresh1}
858b8851fccSafresh1
859b8851fccSafresh1=begin _undocumented
860b8851fccSafresh1
861eac174f2Safresh1=head2 install_rooted_file( $file )
862b8851fccSafresh1
863b8851fccSafresh1Returns $file, or catfile($INSTALL_ROOT,$file) if $INSTALL_ROOT
864b8851fccSafresh1is defined.
865b8851fccSafresh1
866eac174f2Safresh1=head2 install_rooted_dir( $dir )
867b8851fccSafresh1
868b8851fccSafresh1Returns $dir, or catdir($INSTALL_ROOT,$dir) if $INSTALL_ROOT
869b8851fccSafresh1is defined.
870b8851fccSafresh1
871b8851fccSafresh1=end _undocumented
872b8851fccSafresh1
873b8851fccSafresh1=cut
874b8851fccSafresh1
875b8851fccSafresh1sub install_rooted_file {
876b8851fccSafresh1    if (defined $INSTALL_ROOT) {
877b8851fccSafresh1        File::Spec->catfile($INSTALL_ROOT, $_[0]);
878b8851fccSafresh1    } else {
879b8851fccSafresh1        $_[0];
880b8851fccSafresh1    }
881b8851fccSafresh1}
882b8851fccSafresh1
883b8851fccSafresh1
884b8851fccSafresh1sub install_rooted_dir {
885b8851fccSafresh1    if (defined $INSTALL_ROOT) {
886b8851fccSafresh1        File::Spec->catdir($INSTALL_ROOT, $_[0]);
887b8851fccSafresh1    } else {
888b8851fccSafresh1        $_[0];
889b8851fccSafresh1    }
890b8851fccSafresh1}
891b8851fccSafresh1
892b8851fccSafresh1=begin _undocumented
893b8851fccSafresh1
894eac174f2Safresh1=head2 forceunlink( $file, $tryhard )
895b8851fccSafresh1
896b8851fccSafresh1Tries to delete a file. If $tryhard is true then we will use whatever
897b8851fccSafresh1devious tricks we can to delete the file. Currently this only applies to
898b8851fccSafresh1Win32 in that it will try to use Win32API::File to schedule a delete at
899b8851fccSafresh1reboot. A wrapper for _unlink_or_rename().
900b8851fccSafresh1
901b8851fccSafresh1=end _undocumented
902b8851fccSafresh1
903b8851fccSafresh1=cut
904b8851fccSafresh1
905b8851fccSafresh1sub forceunlink {
906b8851fccSafresh1    my ( $file, $tryhard )= @_; #XXX OS-SPECIFIC
907b8851fccSafresh1    _unlink_or_rename( $file, $tryhard, not("installing") );
908b8851fccSafresh1}
909b8851fccSafresh1
910b8851fccSafresh1=begin _undocumented
911b8851fccSafresh1
912eac174f2Safresh1=head2 directory_not_empty( $dir )
913b8851fccSafresh1
914b8851fccSafresh1Returns 1 if there is an .exists file somewhere in a directory tree.
915b8851fccSafresh1Returns 0 if there is not.
916b8851fccSafresh1
917b8851fccSafresh1=end _undocumented
918b8851fccSafresh1
919b8851fccSafresh1=cut
920b8851fccSafresh1
921b8851fccSafresh1sub directory_not_empty ($) {
922b8851fccSafresh1  my($dir) = @_;
923b8851fccSafresh1  my $files = 0;
9249f11ffb7Safresh1  require File::Find;
9259f11ffb7Safresh1  File::Find::find(sub {
926b8851fccSafresh1           return if $_ eq ".exists";
927b8851fccSafresh1           if (-f) {
928b8851fccSafresh1             $File::Find::prune++;
929b8851fccSafresh1             $files = 1;
930b8851fccSafresh1           }
931b8851fccSafresh1       }, $dir);
932b8851fccSafresh1  return $files;
933b8851fccSafresh1}
934b8851fccSafresh1
935eac174f2Safresh1=head2 install_default
936b8851fccSafresh1
937eac174f2Safresh1I<DISCOURAGED>
938b8851fccSafresh1
939b8851fccSafresh1    install_default();
940b8851fccSafresh1    install_default($fullext);
941b8851fccSafresh1
942b8851fccSafresh1Calls install() with arguments to copy a module from blib/ to the
943b8851fccSafresh1default site installation location.
944b8851fccSafresh1
945b8851fccSafresh1$fullext is the name of the module converted to a directory
946b8851fccSafresh1(ie. Foo::Bar would be Foo/Bar).  If $fullext is not specified, it
947b8851fccSafresh1will attempt to read it from @ARGV.
948b8851fccSafresh1
949b8851fccSafresh1This is primarily useful for install scripts.
950b8851fccSafresh1
951b8851fccSafresh1B<NOTE> This function is not really useful because of the hard-coded
952b8851fccSafresh1install location with no way to control site vs core vs vendor
953b8851fccSafresh1directories and the strange way in which the module name is given.
954b8851fccSafresh1Consider its use discouraged.
955b8851fccSafresh1
956b8851fccSafresh1=cut
957b8851fccSafresh1
958b8851fccSafresh1sub install_default {
9599f11ffb7Safresh1  @_ < 2 or _croak("install_default should be called with 0 or 1 argument");
960b8851fccSafresh1  my $FULLEXT = @_ ? shift : $ARGV[0];
961b8851fccSafresh1  defined $FULLEXT or die "Do not know to where to write install log";
962b8851fccSafresh1  my $INST_LIB = File::Spec->catdir($Curdir,"blib","lib");
963b8851fccSafresh1  my $INST_ARCHLIB = File::Spec->catdir($Curdir,"blib","arch");
964b8851fccSafresh1  my $INST_BIN = File::Spec->catdir($Curdir,'blib','bin');
965b8851fccSafresh1  my $INST_SCRIPT = File::Spec->catdir($Curdir,'blib','script');
966b8851fccSafresh1  my $INST_MAN1DIR = File::Spec->catdir($Curdir,'blib','man1');
967b8851fccSafresh1  my $INST_MAN3DIR = File::Spec->catdir($Curdir,'blib','man3');
968b8851fccSafresh1
969b8851fccSafresh1  my @INST_HTML;
970b8851fccSafresh1  if($Config{installhtmldir}) {
971b8851fccSafresh1      my $INST_HTMLDIR = File::Spec->catdir($Curdir,'blib','html');
972b8851fccSafresh1      @INST_HTML = ($INST_HTMLDIR => $Config{installhtmldir});
973b8851fccSafresh1  }
974b8851fccSafresh1
975b8851fccSafresh1  install({
976b8851fccSafresh1           read => "$Config{sitearchexp}/auto/$FULLEXT/.packlist",
977b8851fccSafresh1           write => "$Config{installsitearch}/auto/$FULLEXT/.packlist",
978b8851fccSafresh1           $INST_LIB => (directory_not_empty($INST_ARCHLIB)) ?
979b8851fccSafresh1                         $Config{installsitearch} :
980b8851fccSafresh1                         $Config{installsitelib},
981b8851fccSafresh1           $INST_ARCHLIB => $Config{installsitearch},
982b8851fccSafresh1           $INST_BIN => $Config{installbin} ,
983b8851fccSafresh1           $INST_SCRIPT => $Config{installscript},
984b8851fccSafresh1           $INST_MAN1DIR => $Config{installman1dir},
985b8851fccSafresh1           $INST_MAN3DIR => $Config{installman3dir},
986b8851fccSafresh1       @INST_HTML,
987b8851fccSafresh1          },1,0,0);
988b8851fccSafresh1}
989b8851fccSafresh1
990b8851fccSafresh1
991eac174f2Safresh1=head2 uninstall
992b8851fccSafresh1
993b8851fccSafresh1    uninstall($packlist_file);
994b8851fccSafresh1    uninstall($packlist_file, $verbose, $dont_execute);
995b8851fccSafresh1
996b8851fccSafresh1Removes the files listed in a $packlist_file.
997b8851fccSafresh1
998b8851fccSafresh1If $verbose is true, will print out each file removed.  Default is
999b8851fccSafresh1false.
1000b8851fccSafresh1
1001b8851fccSafresh1If $dont_execute is true it will only print what it was going to do
1002b8851fccSafresh1without actually doing it.  Default is false.
1003b8851fccSafresh1
1004b8851fccSafresh1=cut
1005b8851fccSafresh1
1006b8851fccSafresh1sub uninstall {
1007b8851fccSafresh1    my($fil,$verbose,$dry_run) = @_;
1008b8851fccSafresh1    $verbose ||= 0;
1009b8851fccSafresh1    $dry_run  ||= 0;
1010b8851fccSafresh1
1011b8851fccSafresh1    die _estr "ERROR: no packlist file found: '$fil'"
1012b8851fccSafresh1        unless -f $fil;
1013b8851fccSafresh1    # my $my_req = $self->catfile(qw(auto ExtUtils Install forceunlink.al));
1014b8851fccSafresh1    # require $my_req; # Hairy, but for the first
10159f11ffb7Safresh1    require ExtUtils::Packlist;
1016b8851fccSafresh1    my ($packlist) = ExtUtils::Packlist->new($fil);
1017b8851fccSafresh1    foreach (sort(keys(%$packlist))) {
1018b8851fccSafresh1        chomp;
1019b8851fccSafresh1        print "unlink $_\n" if $verbose;
1020b8851fccSafresh1        forceunlink($_,'tryhard') unless $dry_run;
1021b8851fccSafresh1    }
1022b8851fccSafresh1    print "unlink $fil\n" if $verbose;
1023b8851fccSafresh1    forceunlink($fil, 'tryhard') unless $dry_run;
1024b8851fccSafresh1    _do_cleanup($verbose);
1025b8851fccSafresh1}
1026b8851fccSafresh1
1027b8851fccSafresh1=begin _undocumented
1028b8851fccSafresh1
1029eac174f2Safresh1=head2 inc_uninstall($filepath,$libdir,$verbose,$dry_run,$ignore,$results)
1030b8851fccSafresh1
1031b8851fccSafresh1Remove shadowed files. If $ignore is true then it is assumed to hold
1032b8851fccSafresh1a filename to ignore. This is used to prevent spurious warnings from
1033b8851fccSafresh1occurring when doing an install at reboot.
1034b8851fccSafresh1
1035b8851fccSafresh1We now only die when failing to remove a file that has precedence over
1036b8851fccSafresh1our own, when our install has precedence we only warn.
1037b8851fccSafresh1
1038b8851fccSafresh1$results is assumed to contain a hashref which will have the keys
1039b8851fccSafresh1'uninstall' and 'uninstall_fail' populated with  keys for the files
1040b8851fccSafresh1removed and values of the source files they would shadow.
1041b8851fccSafresh1
1042b8851fccSafresh1=end _undocumented
1043b8851fccSafresh1
1044b8851fccSafresh1=cut
1045b8851fccSafresh1
1046b8851fccSafresh1sub inc_uninstall {
1047b8851fccSafresh1    my($filepath,$libdir,$verbose,$dry_run,$ignore,$results) = @_;
1048b8851fccSafresh1    my($dir);
1049b8851fccSafresh1    $ignore||="";
1050b8851fccSafresh1    my $file = (File::Spec->splitpath($filepath))[2];
1051b8851fccSafresh1    my %seen_dir = ();
1052b8851fccSafresh1
1053b8851fccSafresh1    my @PERL_ENV_LIB = split $Config{path_sep}, defined $ENV{'PERL5LIB'}
1054b8851fccSafresh1      ? $ENV{'PERL5LIB'} : $ENV{'PERLLIB'} || '';
1055b8851fccSafresh1
1056b8851fccSafresh1    my @dirs=( @PERL_ENV_LIB,
1057b8851fccSafresh1               @INC,
1058b8851fccSafresh1               @Config{qw(archlibexp
1059b8851fccSafresh1                          privlibexp
1060b8851fccSafresh1                          sitearchexp
1061b8851fccSafresh1                          sitelibexp)});
1062b8851fccSafresh1
1063b8851fccSafresh1    #warn join "\n","---",@dirs,"---";
1064b8851fccSafresh1    my $seen_ours;
1065b8851fccSafresh1    foreach $dir ( @dirs ) {
1066eac174f2Safresh1        my $canonpath = _Is_VMS ? $dir : File::Spec->canonpath($dir);
1067b8851fccSafresh1        next if $canonpath eq $Curdir;
1068b8851fccSafresh1        next if $seen_dir{$canonpath}++;
1069b8851fccSafresh1        my $targetfile = File::Spec->catfile($canonpath,$libdir,$file);
1070b8851fccSafresh1        next unless -f $targetfile;
1071b8851fccSafresh1
1072b8851fccSafresh1        # The reason why we compare file's contents is, that we cannot
1073b8851fccSafresh1        # know, which is the file we just installed (AFS). So we leave
1074b8851fccSafresh1        # an identical file in place
1075eac174f2Safresh1        my $diff = _compare($filepath,$targetfile);
1076eac174f2Safresh1
1077b8851fccSafresh1        print "#$file and $targetfile differ\n" if $diff && $verbose > 1;
1078b8851fccSafresh1
1079b8851fccSafresh1        if (!$diff or $targetfile eq $ignore) {
1080b8851fccSafresh1            $seen_ours = 1;
1081b8851fccSafresh1            next;
1082b8851fccSafresh1        }
1083b8851fccSafresh1        if ($dry_run) {
1084b8851fccSafresh1            $results->{uninstall}{$targetfile} = $filepath;
1085b8851fccSafresh1            if ($verbose) {
1086b8851fccSafresh1                $Inc_uninstall_warn_handler ||= ExtUtils::Install::Warn->new();
1087b8851fccSafresh1                $libdir =~ s|^\./||s ; # That's just cosmetics, no need to port. It looks prettier.
1088b8851fccSafresh1                $Inc_uninstall_warn_handler->add(
1089b8851fccSafresh1                                     File::Spec->catfile($libdir, $file),
1090b8851fccSafresh1                                     $targetfile
1091b8851fccSafresh1                                    );
1092b8851fccSafresh1            }
1093b8851fccSafresh1            # if not verbose, we just say nothing
1094b8851fccSafresh1        } else {
1095b8851fccSafresh1            print "Unlinking $targetfile (shadowing?)\n" if $verbose;
1096b8851fccSafresh1            eval {
1097b8851fccSafresh1                die "Fake die for testing"
1098b8851fccSafresh1                    if $ExtUtils::Install::Testing and
1099b8851fccSafresh1                       ucase(File::Spec->canonpath($ExtUtils::Install::Testing)) eq ucase($targetfile);
1100b8851fccSafresh1                forceunlink($targetfile,'tryhard');
1101b8851fccSafresh1                $results->{uninstall}{$targetfile} = $filepath;
1102b8851fccSafresh1                1;
1103b8851fccSafresh1            } or do {
1104b8851fccSafresh1                $results->{fail_uninstall}{$targetfile} = $filepath;
1105b8851fccSafresh1                if ($seen_ours) {
1106b8851fccSafresh1                    warn "Failed to remove probably harmless shadow file '$targetfile'\n";
1107b8851fccSafresh1                } else {
1108b8851fccSafresh1                    die "$@\n";
1109b8851fccSafresh1                }
1110b8851fccSafresh1            };
1111b8851fccSafresh1        }
1112b8851fccSafresh1    }
1113b8851fccSafresh1}
1114b8851fccSafresh1
1115b8851fccSafresh1=begin _undocumented
1116b8851fccSafresh1
1117eac174f2Safresh1=head2 run_filter($cmd,$src,$dest)
1118b8851fccSafresh1
1119b8851fccSafresh1Filter $src using $cmd into $dest.
1120b8851fccSafresh1
1121b8851fccSafresh1=end _undocumented
1122b8851fccSafresh1
1123b8851fccSafresh1=cut
1124b8851fccSafresh1
1125b8851fccSafresh1sub run_filter {
1126b8851fccSafresh1    my ($cmd, $src, $dest) = @_;
1127b8851fccSafresh1    local(*CMD, *SRC);
1128b8851fccSafresh1    open(CMD, "|$cmd >$dest") || die "Cannot fork: $!";
1129b8851fccSafresh1    open(SRC, $src)           || die "Cannot open $src: $!";
1130b8851fccSafresh1    my $buf;
1131b8851fccSafresh1    my $sz = 1024;
1132b8851fccSafresh1    while (my $len = sysread(SRC, $buf, $sz)) {
1133b8851fccSafresh1        syswrite(CMD, $buf, $len);
1134b8851fccSafresh1    }
1135b8851fccSafresh1    close SRC;
1136b8851fccSafresh1    close CMD or die "Filter command '$cmd' failed for $src";
1137b8851fccSafresh1}
1138b8851fccSafresh1
1139eac174f2Safresh1=head2 pm_to_blib
1140b8851fccSafresh1
11419f11ffb7Safresh1    pm_to_blib(\%from_to);
1142b8851fccSafresh1    pm_to_blib(\%from_to, $autosplit_dir);
1143b8851fccSafresh1    pm_to_blib(\%from_to, $autosplit_dir, $filter_cmd);
1144b8851fccSafresh1
1145b8851fccSafresh1Copies each key of %from_to to its corresponding value efficiently.
11469f11ffb7Safresh1If an $autosplit_dir is provided, all .pm files will be autosplit into it.
1147b8851fccSafresh1Any destination directories are created.
1148b8851fccSafresh1
1149b8851fccSafresh1$filter_cmd is an optional shell command to run each .pm file through
1150b8851fccSafresh1prior to splitting and copying.  Input is the contents of the module,
1151b8851fccSafresh1output the new module contents.
1152b8851fccSafresh1
1153b8851fccSafresh1You can have an environment variable PERL_INSTALL_ROOT set which will
1154b8851fccSafresh1be prepended as a directory to each installed file (and directory).
1155b8851fccSafresh1
1156b8851fccSafresh1By default verbose output is generated, setting the PERL_INSTALL_QUIET
1157b8851fccSafresh1environment variable will silence this output.
1158b8851fccSafresh1
1159b8851fccSafresh1=cut
1160b8851fccSafresh1
1161b8851fccSafresh1sub pm_to_blib {
1162b8851fccSafresh1    my($fromto,$autodir,$pm_filter) = @_;
1163b8851fccSafresh1
1164eac174f2Safresh1    my %dirs;
1165*fac98b93Safresh1    _mkpath($autodir,0,$Perm_Dir) if defined $autodir;
1166b8851fccSafresh1    while(my($from, $to) = each %$fromto) {
1167b8851fccSafresh1        if( -f $to && -s $from == -s $to && -M $to < -M $from ) {
1168b8851fccSafresh1            print "Skip $to (unchanged)\n" unless $INSTALL_QUIET;
1169b8851fccSafresh1            next;
1170b8851fccSafresh1        }
1171b8851fccSafresh1
1172b8851fccSafresh1        # When a pm_filter is defined, we need to pre-process the source first
1173b8851fccSafresh1        # to determine whether it has changed or not.  Therefore, only perform
1174b8851fccSafresh1        # the comparison check when there's no filter to be ran.
1175b8851fccSafresh1        #    -- RAM, 03/01/2001
1176b8851fccSafresh1
1177b8851fccSafresh1        my $need_filtering = defined $pm_filter && length $pm_filter &&
1178b8851fccSafresh1                             $from =~ /\.pm$/;
1179b8851fccSafresh1
1180eac174f2Safresh1        if (!$need_filtering && !_compare($from,$to)) {
1181b8851fccSafresh1            print "Skip $to (unchanged)\n" unless $INSTALL_QUIET;
1182b8851fccSafresh1            next;
1183b8851fccSafresh1        }
1184b8851fccSafresh1        if (-f $to){
1185b8851fccSafresh1            # we wont try hard here. its too likely to mess things up.
1186b8851fccSafresh1            forceunlink($to);
1187b8851fccSafresh1        } else {
1188eac174f2Safresh1            my $dirname = dirname($to);
1189eac174f2Safresh1            if (!$dirs{$dirname}++) {
1190*fac98b93Safresh1                _mkpath($dirname,0,$Perm_Dir);
1191eac174f2Safresh1            }
1192b8851fccSafresh1        }
1193b8851fccSafresh1        if ($need_filtering) {
1194b8851fccSafresh1            run_filter($pm_filter, $from, $to);
1195b8851fccSafresh1            print "$pm_filter <$from >$to\n";
1196b8851fccSafresh1        } else {
1197b8851fccSafresh1            _copy( $from, $to );
1198b8851fccSafresh1            print "cp $from $to\n" unless $INSTALL_QUIET;
1199b8851fccSafresh1        }
1200b8851fccSafresh1        my($mode,$atime,$mtime) = (stat $from)[2,8,9];
1201eac174f2Safresh1        utime($atime,$mtime+_Is_VMS,$to);
1202b8851fccSafresh1        _chmod(0444 | ( $mode & 0111 ? 0111 : 0 ),$to);
1203b8851fccSafresh1        next unless $from =~ /\.pm$/;
12049f11ffb7Safresh1        _autosplit($to,$autodir) if defined $autodir;
1205b8851fccSafresh1    }
1206b8851fccSafresh1}
1207b8851fccSafresh1
1208b8851fccSafresh1=begin _private
1209b8851fccSafresh1
1210eac174f2Safresh1=head2 _autosplit
1211b8851fccSafresh1
1212b8851fccSafresh1From 1.0307 back, AutoSplit will sometimes leave an open filehandle to
1213b8851fccSafresh1the file being split.  This causes problems on systems with mandatory
1214b8851fccSafresh1locking (ie. Windows).  So we wrap it and close the filehandle.
1215b8851fccSafresh1
1216b8851fccSafresh1=end _private
1217b8851fccSafresh1
1218b8851fccSafresh1=cut
1219b8851fccSafresh1
1220b8851fccSafresh1sub _autosplit { #XXX OS-SPECIFIC
12219f11ffb7Safresh1    require AutoSplit;
12229f11ffb7Safresh1    my $retval = AutoSplit::autosplit(@_);
1223b8851fccSafresh1    close *AutoSplit::IN if defined *AutoSplit::IN{IO};
1224b8851fccSafresh1
1225b8851fccSafresh1    return $retval;
1226b8851fccSafresh1}
1227b8851fccSafresh1
1228b8851fccSafresh1
1229b8851fccSafresh1package ExtUtils::Install::Warn;
1230b8851fccSafresh1
1231b8851fccSafresh1sub new { bless {}, shift }
1232b8851fccSafresh1
1233b8851fccSafresh1sub add {
1234b8851fccSafresh1    my($self,$file,$targetfile) = @_;
1235b8851fccSafresh1    push @{$self->{$file}}, $targetfile;
1236b8851fccSafresh1}
1237b8851fccSafresh1
1238b8851fccSafresh1sub DESTROY {
1239b8851fccSafresh1    unless(defined $INSTALL_ROOT) {
1240b8851fccSafresh1        my $self = shift;
1241b8851fccSafresh1        my($file,$i,$plural);
1242b8851fccSafresh1        foreach $file (sort keys %$self) {
1243b8851fccSafresh1            $plural = @{$self->{$file}} > 1 ? "s" : "";
1244b8851fccSafresh1            print "## Differing version$plural of $file found. You might like to\n";
1245b8851fccSafresh1            for (0..$#{$self->{$file}}) {
1246b8851fccSafresh1                print "rm ", $self->{$file}[$_], "\n";
1247b8851fccSafresh1                $i++;
1248b8851fccSafresh1            }
1249b8851fccSafresh1        }
1250b8851fccSafresh1        $plural = $i>1 ? "all those files" : "this file";
1251b8851fccSafresh1        my $inst = (_invokant() eq 'ExtUtils::MakeMaker')
1252b8851fccSafresh1                 ? ( $Config::Config{make} || 'make' ).' install'
1253eac174f2Safresh1                     . ( ExtUtils::Install::_Is_VMS ? '/MACRO="UNINST"=1' : ' UNINST=1' )
1254b8851fccSafresh1                 : './Build install uninst=1';
1255b8851fccSafresh1        print "## Running '$inst' will unlink $plural for you.\n";
1256b8851fccSafresh1    }
1257b8851fccSafresh1}
1258b8851fccSafresh1
1259b8851fccSafresh1=begin _private
1260b8851fccSafresh1
1261eac174f2Safresh1=head2 _invokant
1262b8851fccSafresh1
1263b8851fccSafresh1Does a heuristic on the stack to see who called us for more intelligent
1264b8851fccSafresh1error messages. Currently assumes we will be called only by Module::Build
1265b8851fccSafresh1or by ExtUtils::MakeMaker.
1266b8851fccSafresh1
1267b8851fccSafresh1=end _private
1268b8851fccSafresh1
1269b8851fccSafresh1=cut
1270b8851fccSafresh1
1271b8851fccSafresh1sub _invokant {
1272b8851fccSafresh1    my @stack;
1273b8851fccSafresh1    my $frame = 0;
1274b8851fccSafresh1    while (my $file = (caller($frame++))[1]) {
1275b8851fccSafresh1        push @stack, (File::Spec->splitpath($file))[2];
1276b8851fccSafresh1    }
1277b8851fccSafresh1
1278b8851fccSafresh1    my $builder;
1279b8851fccSafresh1    my $top = pop @stack;
1280b8851fccSafresh1    if ($top =~ /^Build/i || exists($INC{'Module/Build.pm'})) {
1281b8851fccSafresh1        $builder = 'Module::Build';
1282b8851fccSafresh1    } else {
1283b8851fccSafresh1        $builder = 'ExtUtils::MakeMaker';
1284b8851fccSafresh1    }
1285b8851fccSafresh1    return $builder;
1286b8851fccSafresh1}
1287b8851fccSafresh1
1288b8851fccSafresh1=head1 ENVIRONMENT
1289b8851fccSafresh1
1290b8851fccSafresh1=over 4
1291b8851fccSafresh1
1292b8851fccSafresh1=item B<PERL_INSTALL_ROOT>
1293b8851fccSafresh1
1294b8851fccSafresh1Will be prepended to each install path.
1295b8851fccSafresh1
1296b8851fccSafresh1=item B<EU_INSTALL_IGNORE_SKIP>
1297b8851fccSafresh1
1298b8851fccSafresh1Will prevent the automatic use of INSTALL.SKIP as the install skip file.
1299b8851fccSafresh1
1300b8851fccSafresh1=item B<EU_INSTALL_SITE_SKIPFILE>
1301b8851fccSafresh1
1302b8851fccSafresh1If there is no INSTALL.SKIP file in the make directory then this value
1303b8851fccSafresh1can be used to provide a default.
1304b8851fccSafresh1
1305b8851fccSafresh1=item B<EU_INSTALL_ALWAYS_COPY>
1306b8851fccSafresh1
1307b8851fccSafresh1If this environment variable is true then normal install processes will
1308b8851fccSafresh1always overwrite older identical files during the install process.
1309b8851fccSafresh1
1310b8851fccSafresh1Note that the alias EU_ALWAYS_COPY will be supported if EU_INSTALL_ALWAYS_COPY
1311b8851fccSafresh1is not defined until at least the 1.50 release. Please ensure you use the
1312b8851fccSafresh1correct EU_INSTALL_ALWAYS_COPY.
1313b8851fccSafresh1
1314b8851fccSafresh1=back
1315b8851fccSafresh1
1316b8851fccSafresh1=head1 AUTHOR
1317b8851fccSafresh1
1318b8851fccSafresh1Original author lost in the mists of time.  Probably the same as Makemaker.
1319b8851fccSafresh1
1320b8851fccSafresh1Production release currently maintained by demerphq C<yves at cpan.org>,
1321b8851fccSafresh1extensive changes by Michael G. Schwern.
1322b8851fccSafresh1
1323b8851fccSafresh1Send bug reports via http://rt.cpan.org/.  Please send your
1324b8851fccSafresh1generated Makefile along with your report.
1325b8851fccSafresh1
1326b8851fccSafresh1=head1 LICENSE
1327b8851fccSafresh1
1328b8851fccSafresh1This program is free software; you can redistribute it and/or
1329b8851fccSafresh1modify it under the same terms as Perl itself.
1330b8851fccSafresh1
1331b8851fccSafresh1See L<http://www.perl.com/perl/misc/Artistic.html>
1332b8851fccSafresh1
1333b8851fccSafresh1
1334b8851fccSafresh1=cut
1335b8851fccSafresh1
1336b8851fccSafresh11;
1337