1*0Sstevel@tonic-gatepackage ExtUtils::Install; 2*0Sstevel@tonic-gate 3*0Sstevel@tonic-gateuse 5.00503; 4*0Sstevel@tonic-gateuse vars qw(@ISA @EXPORT $VERSION); 5*0Sstevel@tonic-gate$VERSION = 1.32; 6*0Sstevel@tonic-gate 7*0Sstevel@tonic-gateuse Exporter; 8*0Sstevel@tonic-gateuse Carp (); 9*0Sstevel@tonic-gateuse Config qw(%Config); 10*0Sstevel@tonic-gate@ISA = ('Exporter'); 11*0Sstevel@tonic-gate@EXPORT = ('install','uninstall','pm_to_blib', 'install_default'); 12*0Sstevel@tonic-gate$Is_VMS = $^O eq 'VMS'; 13*0Sstevel@tonic-gate$Is_MacPerl = $^O eq 'MacOS'; 14*0Sstevel@tonic-gate 15*0Sstevel@tonic-gatemy $Inc_uninstall_warn_handler; 16*0Sstevel@tonic-gate 17*0Sstevel@tonic-gate# install relative to here 18*0Sstevel@tonic-gate 19*0Sstevel@tonic-gatemy $INSTALL_ROOT = $ENV{PERL_INSTALL_ROOT}; 20*0Sstevel@tonic-gate 21*0Sstevel@tonic-gateuse File::Spec; 22*0Sstevel@tonic-gatemy $Curdir = File::Spec->curdir; 23*0Sstevel@tonic-gatemy $Updir = File::Spec->updir; 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate 26*0Sstevel@tonic-gate=head1 NAME 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gateExtUtils::Install - install files from here to there 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate=head1 SYNOPSIS 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate use ExtUtils::Install; 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate install({ 'blib/lib' => 'some/install/dir' } ); 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate uninstall($packlist); 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate pm_to_blib({ 'lib/Foo/Bar.pm' => 'blib/lib/Foo/Bar.pm' }); 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate=head1 DESCRIPTION 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gateHandles the installing and uninstalling of perl modules, scripts, man 44*0Sstevel@tonic-gatepages, etc... 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gateBoth install() and uninstall() are specific to the way 47*0Sstevel@tonic-gateExtUtils::MakeMaker handles the installation and deinstallation of 48*0Sstevel@tonic-gateperl modules. They are not designed as general purpose tools. 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate=head2 Functions 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate=over 4 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate=item B<install> 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate install(\%from_to); 57*0Sstevel@tonic-gate install(\%from_to, $verbose, $dont_execute, $uninstall_shadows); 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gateCopies each directory tree of %from_to to its corresponding value 60*0Sstevel@tonic-gatepreserving timestamps and permissions. 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gateThere are two keys with a special meaning in the hash: "read" and 63*0Sstevel@tonic-gate"write". These contain packlist files. After the copying is done, 64*0Sstevel@tonic-gateinstall() will write the list of target files to $from_to{write}. If 65*0Sstevel@tonic-gate$from_to{read} is given the contents of this file will be merged into 66*0Sstevel@tonic-gatethe written file. The read and the written file may be identical, but 67*0Sstevel@tonic-gateon AFS it is quite likely that people are installing to a different 68*0Sstevel@tonic-gatedirectory than the one where the files later appear. 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gateIf $verbose is true, will print out each file removed. Default is 71*0Sstevel@tonic-gatefalse. This is "make install VERBINST=1" 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gateIf $dont_execute is true it will only print what it was going to do 74*0Sstevel@tonic-gatewithout actually doing it. Default is false. 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gateIf $uninstall_shadows is true any differing versions throughout @INC 77*0Sstevel@tonic-gatewill be uninstalled. This is "make install UNINST=1" 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate=cut 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gatesub install { 82*0Sstevel@tonic-gate my($from_to,$verbose,$nonono,$inc_uninstall) = @_; 83*0Sstevel@tonic-gate $verbose ||= 0; 84*0Sstevel@tonic-gate $nonono ||= 0; 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate use Cwd qw(cwd); 87*0Sstevel@tonic-gate use ExtUtils::Packlist; 88*0Sstevel@tonic-gate use File::Basename qw(dirname); 89*0Sstevel@tonic-gate use File::Copy qw(copy); 90*0Sstevel@tonic-gate use File::Find qw(find); 91*0Sstevel@tonic-gate use File::Path qw(mkpath); 92*0Sstevel@tonic-gate use File::Compare qw(compare); 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate my(%from_to) = %$from_to; 95*0Sstevel@tonic-gate my(%pack, $dir, $warn_permissions); 96*0Sstevel@tonic-gate my($packlist) = ExtUtils::Packlist->new(); 97*0Sstevel@tonic-gate # -w doesn't work reliably on FAT dirs 98*0Sstevel@tonic-gate $warn_permissions++ if $^O eq 'MSWin32'; 99*0Sstevel@tonic-gate local(*DIR); 100*0Sstevel@tonic-gate for (qw/read write/) { 101*0Sstevel@tonic-gate $pack{$_}=$from_to{$_}; 102*0Sstevel@tonic-gate delete $from_to{$_}; 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate my($source_dir_or_file); 105*0Sstevel@tonic-gate foreach $source_dir_or_file (sort keys %from_to) { 106*0Sstevel@tonic-gate #Check if there are files, and if yes, look if the corresponding 107*0Sstevel@tonic-gate #target directory is writable for us 108*0Sstevel@tonic-gate opendir DIR, $source_dir_or_file or next; 109*0Sstevel@tonic-gate for (readdir DIR) { 110*0Sstevel@tonic-gate next if $_ eq $Curdir || $_ eq $Updir || $_ eq ".exists"; 111*0Sstevel@tonic-gate my $targetdir = install_rooted_dir($from_to{$source_dir_or_file}); 112*0Sstevel@tonic-gate mkpath($targetdir) unless $nonono; 113*0Sstevel@tonic-gate if (!$nonono && !-w $targetdir) { 114*0Sstevel@tonic-gate warn "Warning: You do not have permissions to " . 115*0Sstevel@tonic-gate "install into $from_to{$source_dir_or_file}" 116*0Sstevel@tonic-gate unless $warn_permissions++; 117*0Sstevel@tonic-gate } 118*0Sstevel@tonic-gate } 119*0Sstevel@tonic-gate closedir DIR; 120*0Sstevel@tonic-gate } 121*0Sstevel@tonic-gate my $tmpfile = install_rooted_file($pack{"read"}); 122*0Sstevel@tonic-gate $packlist->read($tmpfile) if (-f $tmpfile); 123*0Sstevel@tonic-gate my $cwd = cwd(); 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate MOD_INSTALL: foreach my $source (sort keys %from_to) { 126*0Sstevel@tonic-gate #copy the tree to the target directory without altering 127*0Sstevel@tonic-gate #timestamp and permission and remember for the .packlist 128*0Sstevel@tonic-gate #file. The packlist file contains the absolute paths of the 129*0Sstevel@tonic-gate #install locations. AFS users may call this a bug. We'll have 130*0Sstevel@tonic-gate #to reconsider how to add the means to satisfy AFS users also. 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate #October 1997: we want to install .pm files into archlib if 133*0Sstevel@tonic-gate #there are any files in arch. So we depend on having ./blib/arch 134*0Sstevel@tonic-gate #hardcoded here. 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate my $targetroot = install_rooted_dir($from_to{$source}); 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate my $blib_lib = File::Spec->catdir('blib', 'lib'); 139*0Sstevel@tonic-gate my $blib_arch = File::Spec->catdir('blib', 'arch'); 140*0Sstevel@tonic-gate if ($source eq $blib_lib and 141*0Sstevel@tonic-gate exists $from_to{$blib_arch} and 142*0Sstevel@tonic-gate directory_not_empty($blib_arch)) { 143*0Sstevel@tonic-gate $targetroot = install_rooted_dir($from_to{$blib_arch}); 144*0Sstevel@tonic-gate print "Files found in $blib_arch: installing files in $blib_lib into architecture dependent library tree\n"; 145*0Sstevel@tonic-gate } 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate chdir $source or next; 148*0Sstevel@tonic-gate find(sub { 149*0Sstevel@tonic-gate my ($mode,$size,$atime,$mtime) = (stat)[2,7,8,9]; 150*0Sstevel@tonic-gate return unless -f _; 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate my $origfile = $_; 153*0Sstevel@tonic-gate return if $origfile eq ".exists"; 154*0Sstevel@tonic-gate my $targetdir = File::Spec->catdir($targetroot, $File::Find::dir); 155*0Sstevel@tonic-gate my $targetfile = File::Spec->catfile($targetdir, $origfile); 156*0Sstevel@tonic-gate my $sourcedir = File::Spec->catdir($source, $File::Find::dir); 157*0Sstevel@tonic-gate my $sourcefile = File::Spec->catfile($sourcedir, $origfile); 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate my $save_cwd = cwd; 160*0Sstevel@tonic-gate chdir $cwd; # in case the target is relative 161*0Sstevel@tonic-gate # 5.5.3's File::Find missing no_chdir option. 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate my $diff = 0; 164*0Sstevel@tonic-gate if ( -f $targetfile && -s _ == $size) { 165*0Sstevel@tonic-gate # We have a good chance, we can skip this one 166*0Sstevel@tonic-gate $diff = compare($sourcefile, $targetfile); 167*0Sstevel@tonic-gate } else { 168*0Sstevel@tonic-gate print "$sourcefile differs\n" if $verbose>1; 169*0Sstevel@tonic-gate $diff++; 170*0Sstevel@tonic-gate } 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate if ($diff){ 173*0Sstevel@tonic-gate if (-f $targetfile){ 174*0Sstevel@tonic-gate forceunlink($targetfile) unless $nonono; 175*0Sstevel@tonic-gate } else { 176*0Sstevel@tonic-gate mkpath($targetdir,0,0755) unless $nonono; 177*0Sstevel@tonic-gate print "mkpath($targetdir,0,0755)\n" if $verbose>1; 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate copy($sourcefile, $targetfile) unless $nonono; 180*0Sstevel@tonic-gate print "Installing $targetfile\n"; 181*0Sstevel@tonic-gate utime($atime,$mtime + $Is_VMS,$targetfile) unless $nonono>1; 182*0Sstevel@tonic-gate print "utime($atime,$mtime,$targetfile)\n" if $verbose>1; 183*0Sstevel@tonic-gate $mode = 0444 | ( $mode & 0111 ? 0111 : 0 ); 184*0Sstevel@tonic-gate chmod $mode, $targetfile; 185*0Sstevel@tonic-gate print "chmod($mode, $targetfile)\n" if $verbose>1; 186*0Sstevel@tonic-gate } else { 187*0Sstevel@tonic-gate print "Skipping $targetfile (unchanged)\n" if $verbose; 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate if (defined $inc_uninstall) { 191*0Sstevel@tonic-gate inc_uninstall($sourcefile,$File::Find::dir,$verbose, 192*0Sstevel@tonic-gate $inc_uninstall ? 0 : 1); 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate # Record the full pathname. 196*0Sstevel@tonic-gate $packlist->{$targetfile}++; 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate # File::Find can get confused if you chdir in here. 199*0Sstevel@tonic-gate chdir $save_cwd; 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate # File::Find seems to always be Unixy except on MacPerl :( 202*0Sstevel@tonic-gate }, $Is_MacPerl ? $Curdir : '.' ); 203*0Sstevel@tonic-gate chdir($cwd) or Carp::croak("Couldn't chdir to $cwd: $!"); 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate if ($pack{'write'}) { 206*0Sstevel@tonic-gate $dir = install_rooted_dir(dirname($pack{'write'})); 207*0Sstevel@tonic-gate mkpath($dir,0,0755) unless $nonono; 208*0Sstevel@tonic-gate print "Writing $pack{'write'}\n"; 209*0Sstevel@tonic-gate $packlist->write(install_rooted_file($pack{'write'})) unless $nonono; 210*0Sstevel@tonic-gate } 211*0Sstevel@tonic-gate} 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gatesub install_rooted_file { 214*0Sstevel@tonic-gate if (defined $INSTALL_ROOT) { 215*0Sstevel@tonic-gate File::Spec->catfile($INSTALL_ROOT, $_[0]); 216*0Sstevel@tonic-gate } else { 217*0Sstevel@tonic-gate $_[0]; 218*0Sstevel@tonic-gate } 219*0Sstevel@tonic-gate} 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gatesub install_rooted_dir { 223*0Sstevel@tonic-gate if (defined $INSTALL_ROOT) { 224*0Sstevel@tonic-gate File::Spec->catdir($INSTALL_ROOT, $_[0]); 225*0Sstevel@tonic-gate } else { 226*0Sstevel@tonic-gate $_[0]; 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate} 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gatesub forceunlink { 232*0Sstevel@tonic-gate chmod 0666, $_[0]; 233*0Sstevel@tonic-gate unlink $_[0] or Carp::croak("Cannot forceunlink $_[0]: $!") 234*0Sstevel@tonic-gate} 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gatesub directory_not_empty ($) { 238*0Sstevel@tonic-gate my($dir) = @_; 239*0Sstevel@tonic-gate my $files = 0; 240*0Sstevel@tonic-gate find(sub { 241*0Sstevel@tonic-gate return if $_ eq ".exists"; 242*0Sstevel@tonic-gate if (-f) { 243*0Sstevel@tonic-gate $File::Find::prune++; 244*0Sstevel@tonic-gate $files = 1; 245*0Sstevel@tonic-gate } 246*0Sstevel@tonic-gate }, $dir); 247*0Sstevel@tonic-gate return $files; 248*0Sstevel@tonic-gate} 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate=item B<install_default> I<DISCOURAGED> 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate install_default(); 254*0Sstevel@tonic-gate install_default($fullext); 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gateCalls install() with arguments to copy a module from blib/ to the 257*0Sstevel@tonic-gatedefault site installation location. 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate$fullext is the name of the module converted to a directory 260*0Sstevel@tonic-gate(ie. Foo::Bar would be Foo/Bar). If $fullext is not specified, it 261*0Sstevel@tonic-gatewill attempt to read it from @ARGV. 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gateThis is primarily useful for install scripts. 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gateB<NOTE> This function is not really useful because of the hard-coded 266*0Sstevel@tonic-gateinstall location with no way to control site vs core vs vendor 267*0Sstevel@tonic-gatedirectories and the strange way in which the module name is given. 268*0Sstevel@tonic-gateConsider its use discouraged. 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate=cut 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gatesub install_default { 273*0Sstevel@tonic-gate @_ < 2 or die "install_default should be called with 0 or 1 argument"; 274*0Sstevel@tonic-gate my $FULLEXT = @_ ? shift : $ARGV[0]; 275*0Sstevel@tonic-gate defined $FULLEXT or die "Do not know to where to write install log"; 276*0Sstevel@tonic-gate my $INST_LIB = File::Spec->catdir(File::Spec->curdir,"blib","lib"); 277*0Sstevel@tonic-gate my $INST_ARCHLIB = File::Spec->catdir(File::Spec->curdir,"blib","arch"); 278*0Sstevel@tonic-gate my $INST_BIN = File::Spec->catdir(File::Spec->curdir,'blib','bin'); 279*0Sstevel@tonic-gate my $INST_SCRIPT = File::Spec->catdir(File::Spec->curdir,'blib','script'); 280*0Sstevel@tonic-gate my $INST_MAN1DIR = File::Spec->catdir(File::Spec->curdir,'blib','man1'); 281*0Sstevel@tonic-gate my $INST_MAN3DIR = File::Spec->catdir(File::Spec->curdir,'blib','man3'); 282*0Sstevel@tonic-gate install({ 283*0Sstevel@tonic-gate read => "$Config{sitearchexp}/auto/$FULLEXT/.packlist", 284*0Sstevel@tonic-gate write => "$Config{installsitearch}/auto/$FULLEXT/.packlist", 285*0Sstevel@tonic-gate $INST_LIB => (directory_not_empty($INST_ARCHLIB)) ? 286*0Sstevel@tonic-gate $Config{installsitearch} : 287*0Sstevel@tonic-gate $Config{installsitelib}, 288*0Sstevel@tonic-gate $INST_ARCHLIB => $Config{installsitearch}, 289*0Sstevel@tonic-gate $INST_BIN => $Config{installbin} , 290*0Sstevel@tonic-gate $INST_SCRIPT => $Config{installscript}, 291*0Sstevel@tonic-gate $INST_MAN1DIR => $Config{installman1dir}, 292*0Sstevel@tonic-gate $INST_MAN3DIR => $Config{installman3dir}, 293*0Sstevel@tonic-gate },1,0,0); 294*0Sstevel@tonic-gate} 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate=item B<uninstall> 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate uninstall($packlist_file); 300*0Sstevel@tonic-gate uninstall($packlist_file, $verbose, $dont_execute); 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gateRemoves the files listed in a $packlist_file. 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gateIf $verbose is true, will print out each file removed. Default is 305*0Sstevel@tonic-gatefalse. 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gateIf $dont_execute is true it will only print what it was going to do 308*0Sstevel@tonic-gatewithout actually doing it. Default is false. 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate=cut 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gatesub uninstall { 313*0Sstevel@tonic-gate use ExtUtils::Packlist; 314*0Sstevel@tonic-gate my($fil,$verbose,$nonono) = @_; 315*0Sstevel@tonic-gate $verbose ||= 0; 316*0Sstevel@tonic-gate $nonono ||= 0; 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate die "no packlist file found: $fil" unless -f $fil; 319*0Sstevel@tonic-gate # my $my_req = $self->catfile(qw(auto ExtUtils Install forceunlink.al)); 320*0Sstevel@tonic-gate # require $my_req; # Hairy, but for the first 321*0Sstevel@tonic-gate my ($packlist) = ExtUtils::Packlist->new($fil); 322*0Sstevel@tonic-gate foreach (sort(keys(%$packlist))) { 323*0Sstevel@tonic-gate chomp; 324*0Sstevel@tonic-gate print "unlink $_\n" if $verbose; 325*0Sstevel@tonic-gate forceunlink($_) unless $nonono; 326*0Sstevel@tonic-gate } 327*0Sstevel@tonic-gate print "unlink $fil\n" if $verbose; 328*0Sstevel@tonic-gate forceunlink($fil) unless $nonono; 329*0Sstevel@tonic-gate} 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gatesub inc_uninstall { 332*0Sstevel@tonic-gate my($filepath,$libdir,$verbose,$nonono) = @_; 333*0Sstevel@tonic-gate my($dir); 334*0Sstevel@tonic-gate my $file = (File::Spec->splitpath($filepath))[2]; 335*0Sstevel@tonic-gate my %seen_dir = (); 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate my @PERL_ENV_LIB = split $Config{path_sep}, defined $ENV{'PERL5LIB'} 338*0Sstevel@tonic-gate ? $ENV{'PERL5LIB'} : $ENV{'PERLLIB'} || ''; 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate foreach $dir (@INC, @PERL_ENV_LIB, @Config{qw(archlibexp 341*0Sstevel@tonic-gate privlibexp 342*0Sstevel@tonic-gate sitearchexp 343*0Sstevel@tonic-gate sitelibexp)}) { 344*0Sstevel@tonic-gate next if $dir eq $Curdir; 345*0Sstevel@tonic-gate next if $seen_dir{$dir}++; 346*0Sstevel@tonic-gate my($targetfile) = File::Spec->catfile($dir,$libdir,$file); 347*0Sstevel@tonic-gate next unless -f $targetfile; 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate # The reason why we compare file's contents is, that we cannot 350*0Sstevel@tonic-gate # know, which is the file we just installed (AFS). So we leave 351*0Sstevel@tonic-gate # an identical file in place 352*0Sstevel@tonic-gate my $diff = 0; 353*0Sstevel@tonic-gate if ( -f $targetfile && -s _ == -s $filepath) { 354*0Sstevel@tonic-gate # We have a good chance, we can skip this one 355*0Sstevel@tonic-gate $diff = compare($filepath,$targetfile); 356*0Sstevel@tonic-gate } else { 357*0Sstevel@tonic-gate print "#$file and $targetfile differ\n" if $verbose>1; 358*0Sstevel@tonic-gate $diff++; 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate next unless $diff; 362*0Sstevel@tonic-gate if ($nonono) { 363*0Sstevel@tonic-gate if ($verbose) { 364*0Sstevel@tonic-gate $Inc_uninstall_warn_handler ||= new ExtUtils::Install::Warn; 365*0Sstevel@tonic-gate $libdir =~ s|^\./||s ; # That's just cosmetics, no need to port. It looks prettier. 366*0Sstevel@tonic-gate $Inc_uninstall_warn_handler->add( 367*0Sstevel@tonic-gate File::Spec->catfile($libdir, $file), 368*0Sstevel@tonic-gate $targetfile 369*0Sstevel@tonic-gate ); 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate # if not verbose, we just say nothing 372*0Sstevel@tonic-gate } else { 373*0Sstevel@tonic-gate print "Unlinking $targetfile (shadowing?)\n"; 374*0Sstevel@tonic-gate forceunlink($targetfile); 375*0Sstevel@tonic-gate } 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate} 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gatesub run_filter { 380*0Sstevel@tonic-gate my ($cmd, $src, $dest) = @_; 381*0Sstevel@tonic-gate local(*CMD, *SRC); 382*0Sstevel@tonic-gate open(CMD, "|$cmd >$dest") || die "Cannot fork: $!"; 383*0Sstevel@tonic-gate open(SRC, $src) || die "Cannot open $src: $!"; 384*0Sstevel@tonic-gate my $buf; 385*0Sstevel@tonic-gate my $sz = 1024; 386*0Sstevel@tonic-gate while (my $len = sysread(SRC, $buf, $sz)) { 387*0Sstevel@tonic-gate syswrite(CMD, $buf, $len); 388*0Sstevel@tonic-gate } 389*0Sstevel@tonic-gate close SRC; 390*0Sstevel@tonic-gate close CMD or die "Filter command '$cmd' failed for $src"; 391*0Sstevel@tonic-gate} 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate=item B<pm_to_blib> 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate pm_to_blib(\%from_to, $autosplit_dir); 397*0Sstevel@tonic-gate pm_to_blib(\%from_to, $autosplit_dir, $filter_cmd); 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gateCopies each key of %from_to to its corresponding value efficiently. 400*0Sstevel@tonic-gateFilenames with the extension .pm are autosplit into the $autosplit_dir. 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate$filter_cmd is an optional shell command to run each .pm file through 403*0Sstevel@tonic-gateprior to splitting and copying. Input is the contents of the module, 404*0Sstevel@tonic-gateoutput the new module contents. 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gateYou can have an environment variable PERL_INSTALL_ROOT set which will 407*0Sstevel@tonic-gatebe prepended as a directory to each installed file (and directory). 408*0Sstevel@tonic-gate 409*0Sstevel@tonic-gate=cut 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gatesub pm_to_blib { 412*0Sstevel@tonic-gate my($fromto,$autodir,$pm_filter) = @_; 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate use File::Basename qw(dirname); 415*0Sstevel@tonic-gate use File::Copy qw(copy); 416*0Sstevel@tonic-gate use File::Path qw(mkpath); 417*0Sstevel@tonic-gate use File::Compare qw(compare); 418*0Sstevel@tonic-gate use AutoSplit; 419*0Sstevel@tonic-gate # my $my_req = $self->catfile(qw(auto ExtUtils Install forceunlink.al)); 420*0Sstevel@tonic-gate # require $my_req; # Hairy, but for the first 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate if (!ref($fromto) && -r $fromto) 423*0Sstevel@tonic-gate { 424*0Sstevel@tonic-gate # Win32 has severe command line length limitations, but 425*0Sstevel@tonic-gate # can generate temporary files on-the-fly 426*0Sstevel@tonic-gate # so we pass name of file here - eval it to get hash 427*0Sstevel@tonic-gate open(FROMTO,"<$fromto") or die "Cannot open $fromto:$!"; 428*0Sstevel@tonic-gate my $str = '$fromto = {qw{'.join('',<FROMTO>).'}}'; 429*0Sstevel@tonic-gate eval $str; 430*0Sstevel@tonic-gate close(FROMTO); 431*0Sstevel@tonic-gate } 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gate mkpath($autodir,0,0755); 434*0Sstevel@tonic-gate while(my($from, $to) = each %$fromto) { 435*0Sstevel@tonic-gate if( -f $to && -s $from == -s $to && -M $to < -M $from ) { 436*0Sstevel@tonic-gate print "Skip $to (unchanged)\n"; 437*0Sstevel@tonic-gate next; 438*0Sstevel@tonic-gate } 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate # When a pm_filter is defined, we need to pre-process the source first 441*0Sstevel@tonic-gate # to determine whether it has changed or not. Therefore, only perform 442*0Sstevel@tonic-gate # the comparison check when there's no filter to be ran. 443*0Sstevel@tonic-gate # -- RAM, 03/01/2001 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate my $need_filtering = defined $pm_filter && length $pm_filter && 446*0Sstevel@tonic-gate $from =~ /\.pm$/; 447*0Sstevel@tonic-gate 448*0Sstevel@tonic-gate if (!$need_filtering && 0 == compare($from,$to)) { 449*0Sstevel@tonic-gate print "Skip $to (unchanged)\n"; 450*0Sstevel@tonic-gate next; 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate if (-f $to){ 453*0Sstevel@tonic-gate forceunlink($to); 454*0Sstevel@tonic-gate } else { 455*0Sstevel@tonic-gate mkpath(dirname($to),0,0755); 456*0Sstevel@tonic-gate } 457*0Sstevel@tonic-gate if ($need_filtering) { 458*0Sstevel@tonic-gate run_filter($pm_filter, $from, $to); 459*0Sstevel@tonic-gate print "$pm_filter <$from >$to\n"; 460*0Sstevel@tonic-gate } else { 461*0Sstevel@tonic-gate copy($from,$to); 462*0Sstevel@tonic-gate print "cp $from $to\n"; 463*0Sstevel@tonic-gate } 464*0Sstevel@tonic-gate my($mode,$atime,$mtime) = (stat $from)[2,8,9]; 465*0Sstevel@tonic-gate utime($atime,$mtime+$Is_VMS,$to); 466*0Sstevel@tonic-gate chmod(0444 | ( $mode & 0111 ? 0111 : 0 ),$to); 467*0Sstevel@tonic-gate next unless $from =~ /\.pm$/; 468*0Sstevel@tonic-gate _autosplit($to,$autodir); 469*0Sstevel@tonic-gate } 470*0Sstevel@tonic-gate} 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate 473*0Sstevel@tonic-gate=begin _private 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate=item _autosplit 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gateFrom 1.0307 back, AutoSplit will sometimes leave an open filehandle to 478*0Sstevel@tonic-gatethe file being split. This causes problems on systems with mandatory 479*0Sstevel@tonic-gatelocking (ie. Windows). So we wrap it and close the filehandle. 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate=end _private 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate=cut 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gatesub _autosplit { 486*0Sstevel@tonic-gate my $retval = autosplit(@_); 487*0Sstevel@tonic-gate close *AutoSplit::IN if defined *AutoSplit::IN{IO}; 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate return $retval; 490*0Sstevel@tonic-gate} 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gatepackage ExtUtils::Install::Warn; 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gatesub new { bless {}, shift } 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gatesub add { 498*0Sstevel@tonic-gate my($self,$file,$targetfile) = @_; 499*0Sstevel@tonic-gate push @{$self->{$file}}, $targetfile; 500*0Sstevel@tonic-gate} 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gatesub DESTROY { 503*0Sstevel@tonic-gate unless(defined $INSTALL_ROOT) { 504*0Sstevel@tonic-gate my $self = shift; 505*0Sstevel@tonic-gate my($file,$i,$plural); 506*0Sstevel@tonic-gate foreach $file (sort keys %$self) { 507*0Sstevel@tonic-gate $plural = @{$self->{$file}} > 1 ? "s" : ""; 508*0Sstevel@tonic-gate print "## Differing version$plural of $file found. You might like to\n"; 509*0Sstevel@tonic-gate for (0..$#{$self->{$file}}) { 510*0Sstevel@tonic-gate print "rm ", $self->{$file}[$_], "\n"; 511*0Sstevel@tonic-gate $i++; 512*0Sstevel@tonic-gate } 513*0Sstevel@tonic-gate } 514*0Sstevel@tonic-gate $plural = $i>1 ? "all those files" : "this file"; 515*0Sstevel@tonic-gate print "## Running 'make install UNINST=1' will unlink $plural for you.\n"; 516*0Sstevel@tonic-gate } 517*0Sstevel@tonic-gate} 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate=back 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate=head1 ENVIRONMENT 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate=over 4 525*0Sstevel@tonic-gate 526*0Sstevel@tonic-gate=item B<PERL_INSTALL_ROOT> 527*0Sstevel@tonic-gate 528*0Sstevel@tonic-gateWill be prepended to each install path. 529*0Sstevel@tonic-gate 530*0Sstevel@tonic-gate=back 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gate=head1 AUTHOR 533*0Sstevel@tonic-gate 534*0Sstevel@tonic-gateOriginal author lost in the mists of time. Probably the same as Makemaker. 535*0Sstevel@tonic-gate 536*0Sstevel@tonic-gateCurrently maintained by Michael G Schwern <F<schwern@pobox.com>> 537*0Sstevel@tonic-gate 538*0Sstevel@tonic-gateSend patches and ideas to <F<makemaker@perl.org>>. 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gateSend bug reports via http://rt.cpan.org/. Please send your 541*0Sstevel@tonic-gategenerated Makefile along with your report. 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gateFor more up-to-date information, see http://www.makemaker.org. 544*0Sstevel@tonic-gate 545*0Sstevel@tonic-gate 546*0Sstevel@tonic-gate=head1 LICENSE 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gateThis program is free software; you can redistribute it and/or 549*0Sstevel@tonic-gatemodify it under the same terms as Perl itself. 550*0Sstevel@tonic-gate 551*0Sstevel@tonic-gateSee F<http://www.perl.com/perl/misc/Artistic.html> 552*0Sstevel@tonic-gate 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate=cut 555*0Sstevel@tonic-gate 556*0Sstevel@tonic-gate1; 557