1 package ExtUtils::Install;
3 $VERSION = substr q$Revision: 1.28 $, 10;
4 # $Date: 1998/01/25 07:08:24 $
8 use Config qw(%Config);
9 use vars qw(@ISA @EXPORT $VERSION);
11 @EXPORT = ('install','uninstall','pm_to_blib', 'install_default');
12 $Is_VMS = $^O eq 'VMS';
14 my $splitchar = $^O eq 'VMS' ? '|' : ($^O eq 'os2' || $^O eq 'dos') ? ';' : ':';
15 my @PERL_ENV_LIB = split $splitchar, defined $ENV{'PERL5LIB'} ? $ENV{'PERL5LIB'} : $ENV{'PERLLIB'} || '';
16 my $Inc_uninstall_warn_handler;
18 #use vars qw( @EXPORT @ISA $Is_VMS );
23 unlink $_[0] or Carp::croak("Cannot forceunlink $_[0]: $!")
27 my($hash,$verbose,$nonono,$inc_uninstall) = @_;
32 use ExtUtils::MakeMaker; # to implement a MY class
33 use ExtUtils::Packlist;
34 use File::Basename qw(dirname);
35 use File::Copy qw(copy);
36 use File::Find qw(find);
37 use File::Path qw(mkpath);
38 use File::Compare qw(compare);
41 my(%pack, $dir, $warn_permissions);
42 my($packlist) = ExtUtils::Packlist->new();
43 # -w doesn't work reliably on FAT dirs
44 $warn_permissions++ if $^O eq 'MSWin32';
46 for (qw/read write/) {
50 my($source_dir_or_file);
51 foreach $source_dir_or_file (sort keys %hash) {
52 #Check if there are files, and if yes, look if the corresponding
53 #target directory is writable for us
54 opendir DIR, $source_dir_or_file or next;
56 next if $_ eq "." || $_ eq ".." || $_ eq ".exists";
57 if (-w $hash{$source_dir_or_file} ||
58 mkpath($hash{$source_dir_or_file})) {
61 warn "Warning: You do not have permissions to " .
62 "install into $hash{$source_dir_or_file}"
63 unless $warn_permissions++;
68 $packlist->read($pack{"read"}) if (-f $pack{"read"});
72 MOD_INSTALL: foreach $source (sort keys %hash) {
73 #copy the tree to the target directory without altering
74 #timestamp and permission and remember for the .packlist
75 #file. The packlist file contains the absolute paths of the
76 #install locations. AFS users may call this a bug. We'll have
77 #to reconsider how to add the means to satisfy AFS users also.
79 #October 1997: we want to install .pm files into archlib if
80 #there are any files in arch. So we depend on having ./blib/arch
82 my $targetroot = $hash{$source};
83 if ($source eq "blib/lib" and
84 exists $hash{"blib/arch"} and
85 directory_not_empty("blib/arch")) {
86 $targetroot = $hash{"blib/arch"};
87 print "Files found in blib/arch: installing files in blib/lib into architecture dependent library tree\n";
89 chdir($source) or next;
91 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
92 $atime,$mtime,$ctime,$blksize,$blocks) = stat;
94 return if $_ eq ".exists";
95 my $targetdir = MY->catdir($targetroot,$File::Find::dir);
96 my $targetfile = MY->catfile($targetdir,$_);
99 if ( -f $targetfile && -s _ == $size) {
100 # We have a good chance, we can skip this one
101 $diff = compare($_,$targetfile);
103 print "$_ differs\n" if $verbose>1;
109 forceunlink($targetfile) unless $nonono;
111 mkpath($targetdir,0,0755) unless $nonono;
112 print "mkpath($targetdir,0,0755)\n" if $verbose>1;
114 copy($_,$targetfile) unless $nonono;
115 print "Installing $targetfile\n";
116 utime($atime,$mtime + $Is_VMS,$targetfile) unless $nonono>1;
117 print "utime($atime,$mtime,$targetfile)\n" if $verbose>1;
118 $mode = 0444 | ( $mode & 0111 ? 0111 : 0 );
119 chmod $mode, $targetfile;
120 print "chmod($mode, $targetfile)\n" if $verbose>1;
122 print "Skipping $targetfile (unchanged)\n" if $verbose;
125 if (! defined $inc_uninstall) { # it's called
126 } elsif ($inc_uninstall == 0){
127 inc_uninstall($_,$File::Find::dir,$verbose,1); # nonono set to 1
129 inc_uninstall($_,$File::Find::dir,$verbose,0); # nonono set to 0
131 $packlist->{$targetfile}++;
134 chdir($cwd) or Carp::croak("Couldn't chdir to $cwd: $!");
136 if ($pack{'write'}) {
137 $dir = dirname($pack{'write'});
139 print "Writing $pack{'write'}\n";
140 $packlist->write($pack{'write'});
144 sub directory_not_empty ($) {
148 return if $_ eq ".exists";
150 $File::Find::prune++;
157 sub install_default {
158 @_ < 2 or die "install_default should be called with 0 or 1 argument";
159 my $FULLEXT = @_ ? shift : $ARGV[0];
160 defined $FULLEXT or die "Do not know to where to write install log";
161 my $INST_LIB = MM->catdir(MM->curdir,"blib","lib");
162 my $INST_ARCHLIB = MM->catdir(MM->curdir,"blib","arch");
163 my $INST_BIN = MM->catdir(MM->curdir,'blib','bin');
164 my $INST_SCRIPT = MM->catdir(MM->curdir,'blib','script');
165 my $INST_MAN1DIR = MM->catdir(MM->curdir,'blib','man1');
166 my $INST_MAN3DIR = MM->catdir(MM->curdir,'blib','man3');
168 read => "$Config{sitearchexp}/auto/$FULLEXT/.packlist",
169 write => "$Config{installsitearch}/auto/$FULLEXT/.packlist",
170 $INST_LIB => (directory_not_empty($INST_ARCHLIB)) ?
171 $Config{installsitearch} :
172 $Config{installsitelib},
173 $INST_ARCHLIB => $Config{installsitearch},
174 $INST_BIN => $Config{installbin} ,
175 $INST_SCRIPT => $Config{installscript},
176 $INST_MAN1DIR => $Config{installman1dir},
177 $INST_MAN3DIR => $Config{installman3dir},
182 use ExtUtils::Packlist;
183 my($fil,$verbose,$nonono) = @_;
184 die "no packlist file found: $fil" unless -f $fil;
185 # my $my_req = $self->catfile(qw(auto ExtUtils Install forceunlink.al));
186 # require $my_req; # Hairy, but for the first
187 my ($packlist) = ExtUtils::Packlist->new($fil);
188 foreach (sort(keys(%$packlist))) {
190 print "unlink $_\n" if $verbose;
191 forceunlink($_) unless $nonono;
193 print "unlink $fil\n" if $verbose;
195 forceunlink($fil) unless $nonono;
199 my($file,$libdir,$verbose,$nonono) = @_;
202 foreach $dir (@INC, @PERL_ENV_LIB, @Config{qw(archlibexp
207 next if $seen_dir{$dir}++;
208 my($targetfile) = MY->catfile($dir,$libdir,$file);
209 next unless -f $targetfile;
211 # The reason why we compare file's contents is, that we cannot
212 # know, which is the file we just installed (AFS). So we leave
213 # an identical file in place
215 if ( -f $targetfile && -s _ == -s $file) {
216 # We have a good chance, we can skip this one
217 $diff = compare($file,$targetfile);
219 print "#$file and $targetfile differ\n" if $verbose>1;
226 $Inc_uninstall_warn_handler ||= new ExtUtils::Install::Warn;
227 $libdir =~ s|^\./|| ; # That's just cosmetics, no need to port. It looks prettier.
228 $Inc_uninstall_warn_handler->add("$libdir/$file",$targetfile);
230 # if not verbose, we just say nothing
232 print "Unlinking $targetfile (shadowing?)\n";
233 forceunlink($targetfile);
239 my($fromto,$autodir) = @_;
241 use File::Basename qw(dirname);
242 use File::Copy qw(copy);
243 use File::Path qw(mkpath);
244 use File::Compare qw(compare);
246 # my $my_req = $self->catfile(qw(auto ExtUtils Install forceunlink.al));
247 # require $my_req; # Hairy, but for the first
249 if (!ref($fromto) && -r $fromto)
251 # Win32 has severe command line length limitations, but
252 # can generate temporary files on-the-fly
253 # so we pass name of file here - eval it to get hash
254 open(FROMTO,"<$fromto") or die "Cannot open $fromto:$!";
255 my $str = '$fromto = {qw{'.join('',<FROMTO>).'}}';
260 mkpath($autodir,0,0755);
261 foreach (keys %$fromto) {
262 next if -f $fromto->{$_} && -M $fromto->{$_} < -M $_;
263 unless (compare($_,$fromto->{$_})){
264 print "Skip $fromto->{$_} (unchanged)\n";
267 if (-f $fromto->{$_}){
268 forceunlink($fromto->{$_});
270 mkpath(dirname($fromto->{$_}),0,0755);
272 copy($_,$fromto->{$_});
273 my($mode,$atime,$mtime) = (stat)[2,8,9];
274 utime($atime,$mtime+$Is_VMS,$fromto->{$_});
275 chmod(0444 | ( $mode & 0111 ? 0111 : 0 ),$fromto->{$_});
276 print "cp $_ $fromto->{$_}\n";
278 autosplit($fromto->{$_},$autodir);
282 package ExtUtils::Install::Warn;
284 sub new { bless {}, shift }
287 my($self,$file,$targetfile) = @_;
288 push @{$self->{$file}}, $targetfile;
293 my($file,$i,$plural);
294 foreach $file (sort keys %$self) {
295 $plural = @{$self->{$file}} > 1 ? "s" : "";
296 print "## Differing version$plural of $file found. You might like to\n";
297 for (0..$#{$self->{$file}}) {
298 print "rm ", $self->{$file}[$_], "\n";
302 $plural = $i>1 ? "all those files" : "this file";
303 print "## Running 'make install UNINST=1' will unlink $plural for you.\n";
312 ExtUtils::Install - install files from here to there
316 B<use ExtUtils::Install;>
318 B<install($hashref,$verbose,$nonono);>
320 B<uninstall($packlistfile,$verbose,$nonono);>
322 B<pm_to_blib($hashref);>
326 Both install() and uninstall() are specific to the way
327 ExtUtils::MakeMaker handles the installation and deinstallation of
328 perl modules. They are not designed as general purpose tools.
330 install() takes three arguments. A reference to a hash, a verbose
331 switch and a don't-really-do-it switch. The hash ref contains a
332 mapping of directories: each key/value pair is a combination of
333 directories to be copied. Key is a directory to copy from, value is a
334 directory to copy to. The whole tree below the "from" directory will
335 be copied preserving timestamps and permissions.
337 There are two keys with a special meaning in the hash: "read" and
338 "write". After the copying is done, install will write the list of
339 target files to the file named by C<$hashref-E<gt>{write}>. If there is
340 another file named by C<$hashref-E<gt>{read}>, the contents of this file will
341 be merged into the written file. The read and the written file may be
342 identical, but on AFS it is quite likely that people are installing to a
343 different directory than the one where the files later appear.
345 install_default() takes one or less arguments. If no arguments are
346 specified, it takes $ARGV[0] as if it was specified as an argument.
347 The argument is the value of MakeMaker's C<FULLEXT> key, like F<Tk/Canvas>.
348 This function calls install() with the same arguments as the defaults
349 the MakeMaker would use.
351 The argument-less form is convenient for install scripts like
353 perl -MExtUtils::Install -e install_default Tk/Canvas
355 Assuming this command is executed in a directory with a populated F<blib>
356 directory, it will proceed as if the F<blib> was build by MakeMaker on
357 this machine. This is useful for binary distributions.
359 uninstall() takes as first argument a file containing filenames to be
360 unlinked. The second argument is a verbose switch, the third is a
361 no-don't-really-do-it-now switch.
363 pm_to_blib() takes a hashref as the first argument and copies all keys
364 of the hash to the corresponding values efficiently. Filenames with
365 the extension pm are autosplit. Second argument is the autosplit