📄 install.pm
字号:
package ExtUtils::Install;use 5.00503;use strict;use vars qw(@ISA @EXPORT $VERSION $MUST_REBOOT %Config);$VERSION = '1.44';$VERSION = eval $VERSION;use AutoSplit;use Carp ();use Config qw(%Config);use Cwd qw(cwd);use Exporter;use ExtUtils::Packlist;use File::Basename qw(dirname);use File::Compare qw(compare);use File::Copy;use File::Find qw(find);use File::Path;use File::Spec;@ISA = ('Exporter');@EXPORT = ('install','uninstall','pm_to_blib', 'install_default');=head1 NAMEExtUtils::Install - install files from here to there=head1 SYNOPSIS use ExtUtils::Install; install({ 'blib/lib' => 'some/install/dir' } ); uninstall($packlist); pm_to_blib({ 'lib/Foo/Bar.pm' => 'blib/lib/Foo/Bar.pm' });=head1 DESCRIPTIONHandles the installing and uninstalling of perl modules, scripts, manpages, etc...Both install() and uninstall() are specific to the wayExtUtils::MakeMaker handles the installation and deinstallation ofperl modules. They are not designed as general purpose tools.On some operating systems such as Win32 installation may not be possibleuntil after a reboot has occured. This can have varying consequences:removing an old DLL does not impact programs using the new one, but ifa new DLL cannot be installed properly until reboot then anythingdepending on it must wait. The package variable $ExtUtils::Install::MUST_REBOOTis used to store this status.If this variable is true then such an operation has occured andanything depending on this module cannot proceed until a reboothas occured.If this value is defined but false then such an operation hasocurred, but should not impact later operations.=begin _private=item _chmod($$;$)Wrapper to chmod() for debugging and error trapping.=item _warnonce(@)Warns about something only once.=item _choke(@)Dies with a special message.=end _private=cutmy $Is_VMS = $^O eq 'VMS';my $Is_MacPerl = $^O eq 'MacOS';my $Is_Win32 = $^O eq 'MSWin32';my $Is_cygwin = $^O eq 'cygwin';my $CanMoveAtBoot = ($Is_Win32 || $Is_cygwin);# *note* CanMoveAtBoot is only incidentally the same condition as below# this needs not hold true in the future.my $Has_Win32API_File = ($Is_Win32 || $Is_cygwin) ? (eval {require Win32API::File; 1} || 0) : 0;my $Inc_uninstall_warn_handler;# install relative to heremy $INSTALL_ROOT = $ENV{PERL_INSTALL_ROOT};my $Curdir = File::Spec->curdir;my $Updir = File::Spec->updir;sub _estr(@) { return join "\n",'!' x 72,@_,'!' x 72,'';}{my %warned;sub _warnonce(@) { my $first=shift; my $msg=_estr "WARNING: $first",@_; warn $msg unless $warned{$msg}++;}}sub _choke(@) { my $first=shift; my $msg=_estr "ERROR: $first",@_; Carp::croak($msg);}sub _chmod($$;$) { my ( $mode, $item, $verbose )=@_; $verbose ||= 0; if (chmod $mode, $item) { print "chmod($mode, $item)\n" if $verbose > 1; } else { my $err="$!"; _warnonce "WARNING: Failed chmod($mode, $item): $err\n" if -e $item; }}=begin _private=item _move_file_at_boot( $file, $target, $moan )OS-Specific, Win32/CygwinSchedules a file to be moved/renamed/deleted at next boot.$file should be a filespec of an existing file$target should be a ref to an array if the file is to be deletedotherwise it should be a filespec for a rename. If the file is existingit will be replaced.Sets $MUST_REBOOT to 0 to indicate a deletion operation has occuredand sets it to 1 to indicate that a move operation has been requested.returns 1 on success, on failure if $moan is false errors are fatal.If $moan is true then returns 0 on error and warns instead of dies.=end _private=cutsub _move_file_at_boot { #XXX OS-SPECIFIC my ( $file, $target, $moan )= @_; Carp::confess("Panic: Can't _move_file_at_boot on this platform!") unless $CanMoveAtBoot; my $descr= ref $target ? "'$file' for deletion" : "'$file' for installation as '$target'"; if ( ! $Has_Win32API_File ) { my @msg=( "Cannot schedule $descr at reboot.", "Try installing Win32API::File to allow operations on locked files", "to be scheduled during reboot. Or try to perform the operation by", "hand yourself. (You may need to close other perl processes first)" ); if ( $moan ) { _warnonce(@msg) } else { _choke(@msg) } return 0; } my $opts= Win32API::File::MOVEFILE_DELAY_UNTIL_REBOOT(); $opts= $opts | Win32API::File::MOVEFILE_REPLACE_EXISTING() unless ref $target; _chmod( 0666, $file ); _chmod( 0666, $target ) unless ref $target; if (Win32API::File::MoveFileEx( $file, $target, $opts )) { $MUST_REBOOT ||= ref $target ? 0 : 1; return 1; } else { my @msg=( "MoveFileEx $descr at reboot failed: $^E", "You may try to perform the operation by hand yourself. ", "(You may need to close other perl processes first).", ); if ( $moan ) { _warnonce(@msg) } else { _choke(@msg) } } return 0;}=begin _private=item _unlink_or_rename( $file, $tryhard, $installing )OS-Specific, Win32/CygwinTries to get a file out of the way by unlinking it or renaming it. Onsome OS'es (Win32 based) DLL files can end up locked such that they canbe renamed but not deleted. Likewise sometimes a file can be locked suchthat it cant even be renamed or changed except at reboot. To handlethese cases this routine finds a tempfile name that it can either renamethe file out of the way or use as a proxy for the install so that therename can happen later (at reboot). $file : the file to remove. $tryhard : should advanced tricks be used for deletion $installing : we are not merely deleting but we want to overwriteWhen $tryhard is not true if the unlink fails its fatal. When $tryhardis true then the file is attempted to be renamed. The renamed file isthen scheduled for deletion. If the rename fails then $installinggoverns what happens. If it is false the failure is fatal. If it is truethen an attempt is made to schedule installation at boot using atemporary file to hold the new file. If this fails then a fatal error isthrown, if it succeeds it returns the temporary file name (which will bea derivative of the original in the same directory) so that the caller canuse it to install under. In all other cases of success returns $file.On failure throws a fatal error.=end _private=cutsub _unlink_or_rename { #XXX OS-SPECIFIC my ( $file, $tryhard, $installing )= @_; _chmod( 0666, $file ); unlink $file and return $file; my $error="$!"; _choke("Cannot unlink '$file': $!") unless $CanMoveAtBoot && $tryhard; my $tmp= "AAA"; ++$tmp while -e "$file.$tmp"; $tmp= "$file.$tmp"; warn "WARNING: Unable to unlink '$file': $error\n", "Going to try to rename it to '$tmp'.\n"; if ( rename $file, $tmp ) { warn "Rename succesful. Scheduling '$tmp'\nfor deletion at reboot.\n"; # when $installing we can set $moan to true. # IOW, if we cant delete the renamed file at reboot its # not the end of the world. The other cases are more serious # and need to be fatal. _move_file_at_boot( $tmp, [], $installing ); return $file; } elsif ( $installing ) { _warnonce("Rename failed: $!. Scheduling '$tmp'\nfor". " installation as '$file' at reboot.\n"); _move_file_at_boot( $tmp, $file ); return $tmp; } else { _choke("Rename failed:$!", "Cannot procede."); }}=head2 Functions=over 4=item B<install> install(\%from_to); install(\%from_to, $verbose, $dont_execute, $uninstall_shadows, $skip);Copies each directory tree of %from_to to its corresponding valuepreserving timestamps and permissions.There are two keys with a special meaning in the hash: "read" and"write". These contain packlist files. After the copying is done,install() will write the list of target files to $from_to{write}. If$from_to{read} is given the contents of this file will be merged intothe written file. The read and the written file may be identical, buton AFS it is quite likely that people are installing to a differentdirectory than the one where the files later appear.If $verbose is true, will print out each file removed. Default isfalse. This is "make install VERBINST=1". $verbose values goingup to 5 show increasingly more diagnostics output.If $dont_execute is true it will only print what it was going to dowithout actually doing it. Default is false.If $uninstall_shadows is true any differing versions throughout @INCwill be uninstalled. This is "make install UNINST=1"As of 1.37_02 install() supports the use of a list of patterns to filterout files that shouldn't be installed. If $skip is omitted or undefinedthen install will try to read the list from INSTALL.SKIP in the CWD.This file is a list of regular expressions and is just like theMANIFEST.SKIP file used by L<ExtUtils::Manifest>.A default site INSTALL.SKIP may be provided by setting then environmentvariable EU_INSTALL_SITE_SKIPFILE, this will only be used when thereisn't a distribution specific INSTALL.SKIP. If the environment variableEU_INSTALL_IGNORE_SKIP is true then no install file filtering will beperformed.If $skip is undefined then the skip file will be autodetected and used if itis found. If $skip is a reference to an array then it is assumedthe array contains the list of patterns, if $skip is a true non reference it isassumed to be the filename holding the list of patterns, any other value of$skip is taken to mean that no install filtering should occur.=cut=begin _private=item _get_install_skipHandles loading the INSTALL.SKIP file. Returns an array of patterns to use.=cutsub _get_install_skip { my ( $skip, $verbose )= @_; if ($ENV{EU_INSTALL_IGNORE_SKIP}) { print "EU_INSTALL_IGNORE_SKIP is set, ignore skipfile settings\n" if $verbose>2; return []; } if ( ! defined $skip ) { print "Looking for install skip list\n" if $verbose>2; for my $file ( 'INSTALL.SKIP', $ENV{EU_INSTALL_SITE_SKIPFILE} ) { next unless $file; print "\tChecking for $file\n" if $verbose>2; if (-e $file) { $skip= $file; last; } } } if ($skip && !ref $skip) { print "Reading skip patterns from '$skip'.\n" if $verbose; if (open my $fh,$skip ) { my @patterns; while (<$fh>) { chomp; next if /^\s*(?:#|$)/; print "\tSkip pattern: $_\n" if $verbose>3; push @patterns, $_; } $skip= \@patterns; } else { warn "Can't read skip file:'$skip':$!\n"; $skip=[]; } } elsif ( UNIVERSAL::isa($skip,'ARRAY') ) { print "Using array for skip list\n" if $verbose>2; } elsif ($verbose) { print "No skip list found.\n" if $verbose>1; $skip= []; } warn "Got @{[0+@$skip]} skip patterns.\n" if $verbose>3; return $skip
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -