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