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