ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/staticperl/perl/lib/ExtUtils/Install.pm
Revision: 1.1
Committed: Thu Jun 30 14:27:10 2005 UTC (21 years, 3 months ago) by root
Branch: MAIN
CVS Tags: PERL-5-8-7, HEAD
Branch point for: PERL
Log Message:
*** empty log message ***

File Contents

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