This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade to ExtUtils::Manifest 1.55.
[perl5.git] / lib / ExtUtils / Manifest.pm
1 package ExtUtils::Manifest;
2
3 require Exporter;
4 use Config;
5 use File::Basename;
6 use File::Copy 'copy';
7 use File::Find;
8 use File::Spec;
9 use Carp;
10 use strict;
11
12 use vars qw($VERSION @ISA @EXPORT_OK 
13           $Is_MacOS $Is_VMS 
14           $Debug $Verbose $Quiet $MANIFEST $DEFAULT_MSKIP);
15
16 $VERSION = '1.55';
17 @ISA=('Exporter');
18 @EXPORT_OK = qw(mkmanifest
19                 manicheck  filecheck  fullcheck  skipcheck
20                 manifind   maniread   manicopy   maniadd
21                 maniskip
22                );
23
24 $Is_MacOS = $^O eq 'MacOS';
25 $Is_VMS   = $^O eq 'VMS';
26 require VMS::Filespec if $Is_VMS;
27
28 $Debug   = $ENV{PERL_MM_MANIFEST_DEBUG} || 0;
29 $Verbose = defined $ENV{PERL_MM_MANIFEST_VERBOSE} ?
30                    $ENV{PERL_MM_MANIFEST_VERBOSE} : 1;
31 $Quiet = 0;
32 $MANIFEST = 'MANIFEST';
33
34 $DEFAULT_MSKIP = File::Spec->catfile( dirname(__FILE__), "$MANIFEST.SKIP" );
35
36
37 =head1 NAME
38
39 ExtUtils::Manifest - utilities to write and check a MANIFEST file
40
41 =head1 SYNOPSIS
42
43     use ExtUtils::Manifest qw(...funcs to import...);
44
45     mkmanifest();
46
47     my @missing_files    = manicheck;
48     my @skipped          = skipcheck;
49     my @extra_files      = filecheck;
50     my($missing, $extra) = fullcheck;
51
52     my $found    = manifind();
53
54     my $manifest = maniread();
55
56     manicopy($read,$target);
57
58     maniadd({$file => $comment, ...});
59
60
61 =head1 DESCRIPTION
62
63 =head2 Functions
64
65 ExtUtils::Manifest exports no functions by default.  The following are
66 exported on request
67
68 =over 4
69
70 =item mkmanifest
71
72     mkmanifest();
73
74 Writes all files in and below the current directory to your F<MANIFEST>.
75 It works similar to the result of the Unix command
76
77     find . > MANIFEST
78
79 All files that match any regular expression in a file F<MANIFEST.SKIP>
80 (if it exists) are ignored.
81
82 Any existing F<MANIFEST> file will be saved as F<MANIFEST.bak>.
83
84 =cut
85
86 sub _sort {
87     return sort { lc $a cmp lc $b } @_;
88 }
89
90 sub mkmanifest {
91     my $manimiss = 0;
92     my $read = (-r 'MANIFEST' && maniread()) or $manimiss++;
93     $read = {} if $manimiss;
94     local *M;
95     my $bakbase = $MANIFEST;
96     $bakbase =~ s/\./_/g if $Is_VMS; # avoid double dots
97     rename $MANIFEST, "$bakbase.bak" unless $manimiss;
98     open M, "> $MANIFEST" or die "Could not open $MANIFEST: $!";
99     my $skip = maniskip();
100     my $found = manifind();
101     my($key,$val,$file,%all);
102     %all = (%$found, %$read);
103     $all{$MANIFEST} = ($Is_VMS ? "$MANIFEST\t\t" : '') . 'This list of files'
104         if $manimiss; # add new MANIFEST to known file list
105     foreach $file (_sort keys %all) {
106         if ($skip->($file)) {
107             # Policy: only remove files if they're listed in MANIFEST.SKIP.
108             # Don't remove files just because they don't exist.
109             warn "Removed from $MANIFEST: $file\n" if $Verbose and exists $read->{$file};
110             next;
111         }
112         if ($Verbose){
113             warn "Added to $MANIFEST: $file\n" unless exists $read->{$file};
114         }
115         my $text = $all{$file};
116         $file = _unmacify($file);
117         my $tabs = (5 - (length($file)+1)/8);
118         $tabs = 1 if $tabs < 1;
119         $tabs = 0 unless $text;
120         if ($file =~ /\s/) {
121             $file =~ s/([\\'])/\\$1/g;
122             $file = "'$file'";
123         }
124         print M $file, "\t" x $tabs, $text, "\n";
125     }
126     close M;
127 }
128
129 # Geez, shouldn't this use File::Spec or File::Basename or something?  
130 # Why so careful about dependencies?
131 sub clean_up_filename {
132   my $filename = shift;
133   $filename =~ s|^\./||;
134   $filename =~ s/^:([^:]+)$/$1/ if $Is_MacOS;
135   return $filename;
136 }
137
138
139 =item manifind
140
141     my $found = manifind();
142
143 returns a hash reference. The keys of the hash are the files found
144 below the current directory.
145
146 =cut
147
148 sub manifind {
149     my $p = shift || {};
150     my $found = {};
151
152     my $wanted = sub {
153         my $name = clean_up_filename($File::Find::name);
154         warn "Debug: diskfile $name\n" if $Debug;
155         return if -d $_;
156         
157         if( $Is_VMS ) {
158             $name =~ s#(.*)\.$#\L$1#;
159             $name = uc($name) if $name =~ /^MANIFEST(\.SKIP)?$/i;
160         }
161         $found->{$name} = "";
162     };
163
164     # We have to use "$File::Find::dir/$_" in preprocess, because 
165     # $File::Find::name is unavailable.
166     # Also, it's okay to use / here, because MANIFEST files use Unix-style 
167     # paths.
168     find({wanted => $wanted},
169          $Is_MacOS ? ":" : ".");
170
171     return $found;
172 }
173
174
175 =item manicheck
176
177     my @missing_files = manicheck();
178
179 checks if all the files within a C<MANIFEST> in the current directory
180 really do exist. If C<MANIFEST> and the tree below the current
181 directory are in sync it silently returns an empty list.
182 Otherwise it returns a list of files which are listed in the
183 C<MANIFEST> but missing from the directory, and by default also
184 outputs these names to STDERR.
185
186 =cut
187
188 sub manicheck {
189     return _check_files();
190 }
191
192
193 =item filecheck
194
195     my @extra_files = filecheck();
196
197 finds files below the current directory that are not mentioned in the
198 C<MANIFEST> file. An optional file C<MANIFEST.SKIP> will be
199 consulted. Any file matching a regular expression in such a file will
200 not be reported as missing in the C<MANIFEST> file. The list of any
201 extraneous files found is returned, and by default also reported to
202 STDERR.
203
204 =cut
205
206 sub filecheck {
207     return _check_manifest();
208 }
209
210
211 =item fullcheck
212
213     my($missing, $extra) = fullcheck();
214
215 does both a manicheck() and a filecheck(), returning then as two array
216 refs.
217
218 =cut
219
220 sub fullcheck {
221     return [_check_files()], [_check_manifest()];
222 }
223
224
225 =item skipcheck
226
227     my @skipped = skipcheck();
228
229 lists all the files that are skipped due to your C<MANIFEST.SKIP>
230 file.
231
232 =cut
233
234 sub skipcheck {
235     my($p) = @_;
236     my $found = manifind();
237     my $matches = maniskip();
238
239     my @skipped = ();
240     foreach my $file (_sort keys %$found){
241         if (&$matches($file)){
242             warn "Skipping $file\n";
243             push @skipped, $file;
244             next;
245         }
246     }
247
248     return @skipped;
249 }
250
251
252 sub _check_files {
253     my $p = shift;
254     my $dosnames=(defined(&Dos::UseLFN) && Dos::UseLFN()==0);
255     my $read = maniread() || {};
256     my $found = manifind($p);
257
258     my(@missfile) = ();
259     foreach my $file (_sort keys %$read){
260         warn "Debug: manicheck checking from $MANIFEST $file\n" if $Debug;
261         if ($dosnames){
262             $file = lc $file;
263             $file =~ s=(\.(\w|-)+)=substr ($1,0,4)=ge;
264             $file =~ s=((\w|-)+)=substr ($1,0,8)=ge;
265         }
266         unless ( exists $found->{$file} ) {
267             warn "No such file: $file\n" unless $Quiet;
268             push @missfile, $file;
269         }
270     }
271
272     return @missfile;
273 }
274
275
276 sub _check_manifest {
277     my($p) = @_;
278     my $read = maniread() || {};
279     my $found = manifind($p);
280     my $skip  = maniskip();
281
282     my @missentry = ();
283     foreach my $file (_sort keys %$found){
284         next if $skip->($file);
285         warn "Debug: manicheck checking from disk $file\n" if $Debug;
286         unless ( exists $read->{$file} ) {
287             my $canon = $Is_MacOS ? "\t" . _unmacify($file) : '';
288             warn "Not in $MANIFEST: $file$canon\n" unless $Quiet;
289             push @missentry, $file;
290         }
291     }
292
293     return @missentry;
294 }
295
296
297 =item maniread
298
299     my $manifest = maniread();
300     my $manifest = maniread($manifest_file);
301
302 reads a named C<MANIFEST> file (defaults to C<MANIFEST> in the current
303 directory) and returns a HASH reference with files being the keys and
304 comments being the values of the HASH.  Blank lines and lines which
305 start with C<#> in the C<MANIFEST> file are discarded.
306
307 =cut
308
309 sub maniread {
310     my ($mfile) = @_;
311     $mfile ||= $MANIFEST;
312     my $read = {};
313     local *M;
314     unless (open M, "< $mfile"){
315         warn "Problem opening $mfile: $!";
316         return $read;
317     }
318     local $_;
319     while (<M>){
320         chomp;
321         next if /^\s*#/;
322
323         my($file, $comment);
324
325         # filename may contain spaces if enclosed in ''
326         # (in which case, \\ and \' are escapes)
327         if (($file, $comment) = /^'(\\[\\']|.+)+'\s*(.*)/) {
328             $file =~ s/\\([\\'])/$1/g;
329         }
330         else {
331             ($file, $comment) = /^(\S+)\s*(.*)/;
332         }
333         next unless $file;
334
335         if ($Is_MacOS) {
336             $file = _macify($file);
337             $file =~ s/\\([0-3][0-7][0-7])/sprintf("%c", oct($1))/ge;
338         }
339         elsif ($Is_VMS) {
340             require File::Basename;
341             my($base,$dir) = File::Basename::fileparse($file);
342             # Resolve illegal file specifications in the same way as tar
343             $dir =~ tr/./_/;
344             my(@pieces) = split(/\./,$base);
345             if (@pieces > 2) { $base = shift(@pieces) . '.' . join('_',@pieces); }
346             my $okfile = "$dir$base";
347             warn "Debug: Illegal name $file changed to $okfile\n" if $Debug;
348             $file = $okfile;
349             $file = lc($file) unless $file =~ /^MANIFEST(\.SKIP)?$/;
350         }
351
352         $read->{$file} = $comment;
353     }
354     close M;
355     $read;
356 }
357
358 =item maniskip
359
360     my $skipchk = maniskip();
361     my $skipchk = maniskip($manifest_skip_file);
362
363     if ($skipchk->($file)) { .. }
364
365 reads a named C<MANIFEST.SKIP> file (defaults to C<MANIFEST.SKIP> in
366 the current directory) and returns a CODE reference that tests whether
367 a given filename should be skipped.
368
369 =cut
370
371 # returns an anonymous sub that decides if an argument matches
372 sub maniskip {
373     my @skip ;
374     my $mfile = shift || "$MANIFEST.SKIP";
375     _check_mskip_directives($mfile) if -f $mfile;
376     local(*M, $_);
377     open M, "< $mfile" or open M, "< $DEFAULT_MSKIP" or return sub {0};
378     while (<M>){
379         chomp;
380         s/\r//;
381         next if /^#/;
382         next if /^\s*$/;
383         s/^'//;
384         s/'$//;
385         push @skip, _macify($_);
386     }
387     close M;
388     return sub {0} unless (scalar @skip > 0);
389
390     my $opts = $Is_VMS ? '(?i)' : '';
391
392     # Make sure each entry is isolated in its own parentheses, in case
393     # any of them contain alternations
394     my $regex = join '|', map "(?:$_)", @skip;
395
396     return sub { $_[0] =~ qr{$opts$regex} };
397 }
398
399 # checks for the special directives
400 #   #!include_default
401 #   #!include /path/to/some/manifest.skip
402 # in a custom MANIFEST.SKIP for, for including
403 # the content of, respectively, the default MANIFEST.SKIP
404 # and an external manifest.skip file
405 sub _check_mskip_directives {
406     my $mfile = shift;
407     local (*M, $_);
408     my @lines = ();
409     my $flag = 0;
410     unless (open M, "< $mfile") {
411         warn "Problem opening $mfile: $!";
412         return;
413     }
414     while (<M>) {
415         if (/^#!include_default\s*$/) {
416             if (my @default = _include_mskip_file()) {
417                 push @lines, @default;
418                 warn "Debug: Including default MANIFEST.SKIP\n" if $Debug;
419                 $flag++;
420             }
421             next;
422         }
423         if (/^#!include\s+(.*)\s*$/) {
424             my $external_file = $1;
425             if (my @external = _include_mskip_file($external_file)) {
426                 push @lines, @external;
427                 warn "Debug: Including external $external_file\n" if $Debug;
428                 $flag++;
429             }
430             next;
431         }
432         push @lines, $_;
433     }
434     close M;
435     return unless $flag;
436     my $bakbase = $mfile;
437     $bakbase =~ s/\./_/g if $Is_VMS;  # avoid double dots
438     rename $mfile, "$bakbase.bak";
439     warn "Debug: Saving original $mfile as $bakbase.bak\n" if $Debug;
440     unless (open M, "> $mfile") {
441         warn "Problem opening $mfile: $!";
442         return;
443     }
444     print M $_ for (@lines);
445     close M;
446     return;
447 }
448
449 # returns an array containing the lines of an external
450 # manifest.skip file, if given, or $DEFAULT_MSKIP
451 sub _include_mskip_file {
452     my $mskip = shift || $DEFAULT_MSKIP;
453     unless (-f $mskip) {
454         warn qq{Included file "$mskip" not found - skipping};
455         return;
456     }
457     local (*M, $_);
458     unless (open M, "< $mskip") {
459         warn "Problem opening $mskip: $!";
460         return;
461     }
462     my @lines = ();
463     push @lines, "\n#!start included $mskip\n";
464     push @lines, $_ while <M>;
465     close M;
466     push @lines, "#!end included $mskip\n\n";
467     return @lines;
468 }
469
470 =item manicopy
471
472     manicopy(\%src, $dest_dir);
473     manicopy(\%src, $dest_dir, $how);
474
475 Copies the files that are the keys in %src to the $dest_dir.  %src is
476 typically returned by the maniread() function.
477
478     manicopy( maniread(), $dest_dir );
479
480 This function is useful for producing a directory tree identical to the 
481 intended distribution tree. 
482
483 $how can be used to specify a different methods of "copying".  Valid
484 values are C<cp>, which actually copies the files, C<ln> which creates
485 hard links, and C<best> which mostly links the files but copies any
486 symbolic link to make a tree without any symbolic link.  C<cp> is the 
487 default.
488
489 =cut
490
491 sub manicopy {
492     my($read,$target,$how)=@_;
493     croak "manicopy() called without target argument" unless defined $target;
494     $how ||= 'cp';
495     require File::Path;
496     require File::Basename;
497
498     $target = VMS::Filespec::unixify($target) if $Is_VMS;
499     File::Path::mkpath([ $target ],! $Quiet,$Is_VMS ? undef : 0755);
500     foreach my $file (keys %$read){
501         if ($Is_MacOS) {
502             if ($file =~ m!:!) { 
503                 my $dir = _maccat($target, $file);
504                 $dir =~ s/[^:]+$//;
505                 File::Path::mkpath($dir,1,0755);
506             }
507             cp_if_diff($file, _maccat($target, $file), $how);
508         } else {
509             $file = VMS::Filespec::unixify($file) if $Is_VMS;
510             if ($file =~ m!/!) { # Ilya, that hurts, I fear, or maybe not?
511                 my $dir = File::Basename::dirname($file);
512                 $dir = VMS::Filespec::unixify($dir) if $Is_VMS;
513                 File::Path::mkpath(["$target/$dir"],! $Quiet,$Is_VMS ? undef : 0755);
514             }
515             cp_if_diff($file, "$target/$file", $how);
516         }
517     }
518 }
519
520 sub cp_if_diff {
521     my($from, $to, $how)=@_;
522     if (! -f $from) {
523         carp "$from not found";
524         return;
525     }
526     my($diff) = 0;
527     local(*F,*T);
528     open(F,"< $from\0") or die "Can't read $from: $!\n";
529     if (open(T,"< $to\0")) {
530         local $_;
531         while (<F>) { $diff++,last if $_ ne <T>; }
532         $diff++ unless eof(T);
533         close T;
534     }
535     else { $diff++; }
536     close F;
537     if ($diff) {
538         if (-e $to) {
539             unlink($to) or confess "unlink $to: $!";
540         }
541         STRICT_SWITCH: {
542             best($from,$to), last STRICT_SWITCH if $how eq 'best';
543             cp($from,$to), last STRICT_SWITCH if $how eq 'cp';
544             ln($from,$to), last STRICT_SWITCH if $how eq 'ln';
545             croak("ExtUtils::Manifest::cp_if_diff " .
546                   "called with illegal how argument [$how]. " .
547                   "Legal values are 'best', 'cp', and 'ln'.");
548         }
549     }
550 }
551
552 sub cp {
553     my ($srcFile, $dstFile) = @_;
554     my ($access,$mod) = (stat $srcFile)[8,9];
555
556     copy($srcFile,$dstFile);
557     utime $access, $mod + ($Is_VMS ? 1 : 0), $dstFile;
558     _manicopy_chmod($srcFile, $dstFile);
559 }
560
561
562 sub ln {
563     my ($srcFile, $dstFile) = @_;
564     return &cp if $Is_VMS or ($^O eq 'MSWin32' and Win32::IsWin95());
565     link($srcFile, $dstFile);
566
567     unless( _manicopy_chmod($srcFile, $dstFile) ) {
568         unlink $dstFile;
569         return;
570     }
571     1;
572 }
573
574 # 1) Strip off all group and world permissions.
575 # 2) Let everyone read it.
576 # 3) If the owner can execute it, everyone can.
577 sub _manicopy_chmod {
578     my($srcFile, $dstFile) = @_;
579
580     my $perm = 0444 | (stat $srcFile)[2] & 0700;
581     chmod( $perm | ( $perm & 0100 ? 0111 : 0 ), $dstFile );
582 }
583
584 # Files that are often modified in the distdir.  Don't hard link them.
585 my @Exceptions = qw(MANIFEST META.yml SIGNATURE);
586 sub best {
587     my ($srcFile, $dstFile) = @_;
588
589     my $is_exception = grep $srcFile =~ /$_/, @Exceptions;
590     if ($is_exception or !$Config{d_link} or -l $srcFile) {
591         cp($srcFile, $dstFile);
592     } else {
593         ln($srcFile, $dstFile) or cp($srcFile, $dstFile);
594     }
595 }
596
597 sub _macify {
598     my($file) = @_;
599
600     return $file unless $Is_MacOS;
601
602     $file =~ s|^\./||;
603     if ($file =~ m|/|) {
604         $file =~ s|/+|:|g;
605         $file = ":$file";
606     }
607
608     $file;
609 }
610
611 sub _maccat {
612     my($f1, $f2) = @_;
613
614     return "$f1/$f2" unless $Is_MacOS;
615
616     $f1 .= ":$f2";
617     $f1 =~ s/([^:]:):/$1/g;
618     return $f1;
619 }
620
621 sub _unmacify {
622     my($file) = @_;
623
624     return $file unless $Is_MacOS;
625
626     $file =~ s|^:||;
627     $file =~ s|([/ \n])|sprintf("\\%03o", unpack("c", $1))|ge;
628     $file =~ y|:|/|;
629
630     $file;
631 }
632
633
634 =item maniadd
635
636   maniadd({ $file => $comment, ...});
637
638 Adds an entry to an existing F<MANIFEST> unless its already there.
639
640 $file will be normalized (ie. Unixified).  B<UNIMPLEMENTED>
641
642 =cut
643
644 sub maniadd {
645     my($additions) = shift;
646
647     _normalize($additions);
648     _fix_manifest($MANIFEST);
649
650     my $manifest = maniread();
651     my @needed = grep { !exists $manifest->{$_} } keys %$additions;
652     return 1 unless @needed;
653
654     open(MANIFEST, ">>$MANIFEST") or 
655       die "maniadd() could not open $MANIFEST: $!";
656
657     foreach my $file (_sort @needed) {
658         my $comment = $additions->{$file} || '';
659         if ($file =~ /\s/) {
660             $file =~ s/([\\'])/\\$1/g;
661             $file = "'$file'";
662         }
663         printf MANIFEST "%-40s %s\n", $file, $comment;
664     }
665     close MANIFEST or die "Error closing $MANIFEST: $!";
666
667     return 1;
668 }
669
670
671 # Sometimes MANIFESTs are missing a trailing newline.  Fix this.
672 sub _fix_manifest {
673     my $manifest_file = shift;
674
675     open MANIFEST, $MANIFEST or die "Could not open $MANIFEST: $!";
676
677     # Yes, we should be using seek(), but I'd like to avoid loading POSIX
678     # to get SEEK_*
679     my @manifest = <MANIFEST>;
680     close MANIFEST;
681
682     unless( $manifest[-1] =~ /\n\z/ ) {
683         open MANIFEST, ">>$MANIFEST" or die "Could not open $MANIFEST: $!";
684         print MANIFEST "\n";
685         close MANIFEST;
686     }
687 }
688
689
690 # UNIMPLEMENTED
691 sub _normalize {
692     return;
693 }
694
695
696 =back
697
698 =head2 MANIFEST
699
700 A list of files in the distribution, one file per line.  The MANIFEST
701 always uses Unix filepath conventions even if you're not on Unix.  This
702 means F<foo/bar> style not F<foo\bar>.
703
704 Anything between white space and an end of line within a C<MANIFEST>
705 file is considered to be a comment.  Any line beginning with # is also
706 a comment. Beginning with ExtUtils::Manifest 1.52, a filename may
707 contain whitespace characters if it is enclosed in single quotes; single
708 quotes or backslashes in that filename must be backslash-escaped.
709
710     # this a comment
711     some/file
712     some/other/file            comment about some/file
713     'some/third file'          comment
714
715
716 =head2 MANIFEST.SKIP
717
718 The file MANIFEST.SKIP may contain regular expressions of files that
719 should be ignored by mkmanifest() and filecheck(). The regular
720 expressions should appear one on each line. Blank lines and lines
721 which start with C<#> are skipped.  Use C<\#> if you need a regular
722 expression to start with a C<#>.
723
724 For example:
725
726     # Version control files and dirs.
727     \bRCS\b
728     \bCVS\b
729     ,v$
730     \B\.svn\b
731
732     # Makemaker generated files and dirs.
733     ^MANIFEST\.
734     ^Makefile$
735     ^blib/
736     ^MakeMaker-\d
737
738     # Temp, old and emacs backup files.
739     ~$
740     \.old$
741     ^#.*#$
742     ^\.#
743
744 If no MANIFEST.SKIP file is found, a default set of skips will be
745 used, similar to the example above.  If you want nothing skipped,
746 simply make an empty MANIFEST.SKIP file.
747
748 In one's own MANIFEST.SKIP file, certain directives
749 can be used to include the contents of other MANIFEST.SKIP
750 files. At present two such directives are recognized.
751
752 =over 4
753
754 =item #!include_default
755
756 This inserts the contents of the default MANIFEST.SKIP file
757
758 =item #!include /Path/to/another/manifest.skip
759
760 This inserts the contents of the specified external file
761
762 =back
763
764 The included contents will be inserted into the MANIFEST.SKIP
765 file in between I<#!start included /path/to/manifest.skip>
766 and I<#!end included /path/to/manifest.skip> markers.
767 The original MANIFEST.SKIP is saved as MANIFEST.SKIP.bak.
768
769 =head2 EXPORT_OK
770
771 C<&mkmanifest>, C<&manicheck>, C<&filecheck>, C<&fullcheck>,
772 C<&maniread>, and C<&manicopy> are exportable.
773
774 =head2 GLOBAL VARIABLES
775
776 C<$ExtUtils::Manifest::MANIFEST> defaults to C<MANIFEST>. Changing it
777 results in both a different C<MANIFEST> and a different
778 C<MANIFEST.SKIP> file. This is useful if you want to maintain
779 different distributions for different audiences (say a user version
780 and a developer version including RCS).
781
782 C<$ExtUtils::Manifest::Quiet> defaults to 0. If set to a true value,
783 all functions act silently.
784
785 C<$ExtUtils::Manifest::Debug> defaults to 0.  If set to a true value,
786 or if PERL_MM_MANIFEST_DEBUG is true, debugging output will be
787 produced.
788
789 =head1 DIAGNOSTICS
790
791 All diagnostic output is sent to C<STDERR>.
792
793 =over 4
794
795 =item C<Not in MANIFEST:> I<file>
796
797 is reported if a file is found which is not in C<MANIFEST>.
798
799 =item C<Skipping> I<file>
800
801 is reported if a file is skipped due to an entry in C<MANIFEST.SKIP>.
802
803 =item C<No such file:> I<file>
804
805 is reported if a file mentioned in a C<MANIFEST> file does not
806 exist.
807
808 =item C<MANIFEST:> I<$!>
809
810 is reported if C<MANIFEST> could not be opened.
811
812 =item C<Added to MANIFEST:> I<file>
813
814 is reported by mkmanifest() if $Verbose is set and a file is added
815 to MANIFEST. $Verbose is set to 1 by default.
816
817 =back
818
819 =head1 ENVIRONMENT
820
821 =over 4
822
823 =item B<PERL_MM_MANIFEST_DEBUG>
824
825 Turns on debugging
826
827 =back
828
829 =head1 SEE ALSO
830
831 L<ExtUtils::MakeMaker> which has handy targets for most of the functionality.
832
833 =head1 AUTHOR
834
835 Andreas Koenig C<andreas.koenig@anima.de>
836
837 Maintained by Michael G Schwern C<schwern@pobox.com> within the
838 ExtUtils-MakeMaker package and, as a separate CPAN package, by
839 Randy Kobes C<r.kobes@uwinnipeg.ca>.
840
841 =cut
842
843 1;