fc05da23688e95513a391f15a7c77286bf2dd6bd
[p5sagit/p5-mst-13.2.git] / lib / ExtUtils / MM_VMS.pm
1 #   MM_VMS.pm
2 #   MakeMaker default methods for VMS
3 #   This package is inserted into @ISA of MakeMaker's MM before the
4 #   built-in ExtUtils::MM_Unix methods if MakeMaker.pm is run under VMS.
5 #
6 #   Author:  Charles Bailey  bailey@newman.upenn.edu
7
8 package ExtUtils::MM_VMS;
9
10 use strict;
11
12 use Carp qw( &carp );
13 use Config;
14 require Exporter;
15 use VMS::Filespec;
16 use File::Basename;
17 use File::Spec;
18 our($Revision, @ISA, $VERSION, $Verbose);
19 # All on one line so MakeMaker can see it.
20 ($VERSION) = ($Revision = '5.56 (27-Apr-1999)') =~ /^([\d.]+)/;
21
22 unshift @MM::ISA, 'ExtUtils::MM_VMS';
23
24 require ExtUtils::MakeMaker;
25 ExtUtils::MakeMaker->import('$Verbose', '&neatvalue');
26
27 =head1 NAME
28
29 ExtUtils::MM_VMS - methods to override UN*X behaviour in ExtUtils::MakeMaker
30
31 =head1 SYNOPSIS
32
33  use ExtUtils::MM_VMS; # Done internally by ExtUtils::MakeMaker if needed
34
35 =head1 DESCRIPTION
36
37 See ExtUtils::MM_Unix for a documentation of the methods provided
38 there. This package overrides the implementation of these methods, not
39 the semantics.
40
41 =head2 Methods always loaded
42
43 =over 4
44
45 =item wraplist
46
47 Converts a list into a string wrapped at approximately 80 columns.
48
49 =cut
50
51 sub wraplist {
52     my($self) = shift;
53     my($line,$hlen) = ('',0);
54     my($word);
55
56     foreach $word (@_) {
57       # Perl bug -- seems to occasionally insert extra elements when
58       # traversing array (scalar(@array) doesn't show them, but
59       # foreach(@array) does) (5.00307)
60       next unless $word =~ /\w/;
61       $line .= ' ' if length($line);
62       if ($hlen > 80) { $line .= "\\\n\t"; $hlen = 0; }
63       $line .= $word;
64       $hlen += length($word) + 2;
65     }
66     $line;
67 }
68
69 =item rootdir (override)
70
71 Returns a string representing of the root directory.
72
73 =cut
74
75 sub rootdir {
76     return File::Spec->rootdir();'
77 }
78
79 package ExtUtils::MM_VMS;
80
81 sub ExtUtils::MM_VMS::ext;
82 sub ExtUtils::MM_VMS::guess_name;
83 sub ExtUtils::MM_VMS::find_perl;
84 sub ExtUtils::MM_VMS::path;
85 sub ExtUtils::MM_VMS::maybe_command;
86 sub ExtUtils::MM_VMS::maybe_command_in_dirs;
87 sub ExtUtils::MM_VMS::perl_script;
88 sub ExtUtils::MM_VMS::file_name_is_absolute;
89 sub ExtUtils::MM_VMS::replace_manpage_separator;
90 sub ExtUtils::MM_VMS::init_others;
91 sub ExtUtils::MM_VMS::constants;
92 sub ExtUtils::MM_VMS::cflags;
93 sub ExtUtils::MM_VMS::const_cccmd;
94 sub ExtUtils::MM_VMS::pm_to_blib;
95 sub ExtUtils::MM_VMS::tool_autosplit;
96 sub ExtUtils::MM_VMS::tool_xsubpp;
97 sub ExtUtils::MM_VMS::xsubpp_version;
98 sub ExtUtils::MM_VMS::tools_other;
99 sub ExtUtils::MM_VMS::dist;
100 sub ExtUtils::MM_VMS::c_o;
101 sub ExtUtils::MM_VMS::xs_c;
102 sub ExtUtils::MM_VMS::xs_o;
103 sub ExtUtils::MM_VMS::top_targets;
104 sub ExtUtils::MM_VMS::dlsyms;
105 sub ExtUtils::MM_VMS::dynamic_lib;
106 sub ExtUtils::MM_VMS::dynamic_bs;
107 sub ExtUtils::MM_VMS::static_lib;
108 sub ExtUtils::MM_VMS::manifypods;
109 sub ExtUtils::MM_VMS::processPL;
110 sub ExtUtils::MM_VMS::installbin;
111 sub ExtUtils::MM_VMS::subdir_x;
112 sub ExtUtils::MM_VMS::clean;
113 sub ExtUtils::MM_VMS::realclean;
114 sub ExtUtils::MM_VMS::dist_basics;
115 sub ExtUtils::MM_VMS::dist_core;
116 sub ExtUtils::MM_VMS::dist_dir;
117 sub ExtUtils::MM_VMS::dist_test;
118 sub ExtUtils::MM_VMS::install;
119 sub ExtUtils::MM_VMS::perldepend;
120 sub ExtUtils::MM_VMS::makefile;
121 sub ExtUtils::MM_VMS::test;
122 sub ExtUtils::MM_VMS::test_via_harness;
123 sub ExtUtils::MM_VMS::test_via_script;
124 sub ExtUtils::MM_VMS::makeaperl;
125 sub ExtUtils::MM_VMS::ext;
126 sub ExtUtils::MM_VMS::nicetext;
127
128 our $AUTOLOAD;
129 sub AUTOLOAD {
130     my $code;
131     if (defined fileno(DATA)) {
132         my $fh = select DATA;
133         my $o = $/;                     # For future reads from the file.
134         $/ = "\n__END__\n";
135         $code = <DATA>;
136         $/ = $o;
137         select $fh;
138         close DATA;
139         eval $code;
140         if ($@) {
141             $@ =~ s/ at .*\n//;
142             Carp::croak $@;
143         }
144     } else {
145         warn "AUTOLOAD called unexpectedly for $AUTOLOAD"; 
146     }
147     defined(&$AUTOLOAD) or die "Myloader inconsistency error";
148     goto &$AUTOLOAD;
149 }
150
151 1;
152
153 #__DATA__
154
155
156 # This isn't really an override.  It's just here because ExtUtils::MM_VMS
157 # appears in @MM::ISA before ExtUtils::Liblist::Kid, so if there isn't an ext()
158 # in MM_VMS, then AUTOLOAD is called, and bad things happen.  So, we just
159 # mimic inheritance here and hand off to ExtUtils::Liblist::Kid.
160 sub ext {
161   require ExtUtils::Liblist;
162   ExtUtils::Liblist::Kid::ext(@_);
163 }
164
165 =back
166
167 =head2 SelfLoaded methods
168
169 Those methods which override default MM_Unix methods are marked
170 "(override)", while methods unique to MM_VMS are marked "(specific)".
171 For overridden methods, documentation is limited to an explanation
172 of why this method overrides the MM_Unix method; see the ExtUtils::MM_Unix
173 documentation for more details.
174
175 =over 4
176
177 =item guess_name (override)
178
179 Try to determine name of extension being built.  We begin with the name
180 of the current directory.  Since VMS filenames are case-insensitive,
181 however, we look for a F<.pm> file whose name matches that of the current
182 directory (presumably the 'main' F<.pm> file for this extension), and try
183 to find a C<package> statement from which to obtain the Mixed::Case
184 package name.
185
186 =cut
187
188 sub guess_name {
189     my($self) = @_;
190     my($defname,$defpm,@pm,%xs,$pm);
191     local *PM;
192
193     $defname = basename(fileify($ENV{'DEFAULT'}));
194     $defname =~ s![\d\-_]*\.dir.*$!!;  # Clip off .dir;1 suffix, and package version
195     $defpm = $defname;
196     # Fallback in case for some reason a user has copied the files for an
197     # extension into a working directory whose name doesn't reflect the
198     # extension's name.  We'll use the name of a unique .pm file, or the
199     # first .pm file with a matching .xs file.
200     if (not -e "${defpm}.pm") {
201       @pm = map { s/.pm$//; $_ } glob('*.pm');
202       if (@pm == 1) { ($defpm = $pm[0]) =~ s/.pm$//; }
203       elsif (@pm) {
204         %xs = map { s/.xs$//; ($_,1) } glob('*.xs');
205         if (%xs) { foreach $pm (@pm) { $defpm = $pm, last if exists $xs{$pm}; } }
206       }
207     }
208     if (open(PM,"${defpm}.pm")){
209         while (<PM>) {
210             if (/^\s*package\s+([^;]+)/i) {
211                 $defname = $1;
212                 last;
213             }
214         }
215         print STDOUT "Warning (non-fatal): Couldn't find package name in ${defpm}.pm;\n\t",
216                      "defaulting package name to $defname\n"
217             if eof(PM);
218         close PM;
219     }
220     else {
221         print STDOUT "Warning (non-fatal): Couldn't find ${defpm}.pm;\n\t",
222                      "defaulting package name to $defname\n";
223     }
224     $defname =~ s#[\d.\-_]+$##;
225     $defname;
226 }
227
228 =item find_perl (override)
229
230 Use VMS file specification syntax and CLI commands to find and
231 invoke Perl images.
232
233 =cut
234
235 sub find_perl {
236     my($self, $ver, $names, $dirs, $trace) = @_;
237     my($name,$dir,$vmsfile,@sdirs,@snames,@cand);
238     my($rslt);
239     my($inabs) = 0;
240     local *TCF;
241     # Check in relative directories first, so we pick up the current
242     # version of Perl if we're running MakeMaker as part of the main build.
243     @sdirs = sort { my($absa) = File::Spec->file_name_is_absolute($a);
244                     my($absb) = File::Spec->file_name_is_absolute($b);
245                     if ($absa && $absb) { return $a cmp $b }
246                     else { return $absa ? 1 : ($absb ? -1 : ($a cmp $b)); }
247                   } @$dirs;
248     # Check miniperl before perl, and check names likely to contain
249     # version numbers before "generic" names, so we pick up an
250     # executable that's less likely to be from an old installation.
251     @snames = sort { my($ba) = $a =~ m!([^:>\]/]+)$!;  # basename
252                      my($bb) = $b =~ m!([^:>\]/]+)$!;
253                      my($ahasdir) = (length($a) - length($ba) > 0);
254                      my($bhasdir) = (length($b) - length($bb) > 0);
255                      if    ($ahasdir and not $bhasdir) { return 1; }
256                      elsif ($bhasdir and not $ahasdir) { return -1; }
257                      else { $bb =~ /\d/ <=> $ba =~ /\d/
258                             or substr($ba,0,1) cmp substr($bb,0,1)
259                             or length($bb) <=> length($ba) } } @$names;
260     # Image names containing Perl version use '_' instead of '.' under VMS
261     foreach $name (@snames) { $name =~ s/\.(\d+)$/_$1/; }
262     if ($trace >= 2){
263         print "Looking for perl $ver by these names:\n";
264         print "\t@snames,\n";
265         print "in these dirs:\n";
266         print "\t@sdirs\n";
267     }
268     foreach $dir (@sdirs){
269         next unless defined $dir; # $self->{PERL_SRC} may be undefined
270         $inabs++ if File::Spec->file_name_is_absolute($dir);
271         if ($inabs == 1) {
272             # We've covered relative dirs; everything else is an absolute
273             # dir (probably an installed location).  First, we'll try potential
274             # command names, to see whether we can avoid a long MCR expression.
275             foreach $name (@snames) { push(@cand,$name) if $name =~ /^[\w\-\$]+$/; }
276             $inabs++; # Should happen above in next $dir, but just in case . . .
277         }
278         foreach $name (@snames){
279             if ($name !~ m![/:>\]]!) { push(@cand,File::Spec->catfile($dir,$name)); }
280             else                     { push(@cand,$self->fixpath($name,0));    }
281         }
282     }
283     foreach $name (@cand) {
284         print "Checking $name\n" if ($trace >= 2);
285         # If it looks like a potential command, try it without the MCR
286         if ($name =~ /^[\w\-\$]+$/) {
287             open(TCF,">temp_mmvms.com") || die('unable to open temp file');
288             print TCF "\$ set message/nofacil/nosever/noident/notext\n";
289             print TCF "\$ $name -e \"require $ver; print \"\"VER_OK\\n\"\"\"\n";
290             close TCF;
291             $rslt = `\@temp_mmvms.com` ;
292             unlink('temp_mmvms.com');
293             if ($rslt =~ /VER_OK/) {
294             print "Using PERL=$name\n" if $trace;
295             return $name;
296         }
297         }
298         next unless $vmsfile = $self->maybe_command($name);
299         $vmsfile =~ s/;[\d\-]*$//;  # Clip off version number; we can use a newer version as well
300         print "Executing $vmsfile\n" if ($trace >= 2);
301         open(TCF,">temp_mmvms.com") || die('unable to open temp file');
302         print TCF "\$ set message/nofacil/nosever/noident/notext\n";
303         print TCF "\$ mcr $vmsfile -e \"require $ver; print \"\"VER_OK\\n\"\"\" \n";
304         close TCF;
305         $rslt = `\@temp_mmvms.com`;
306         unlink('temp_mmvms.com');
307         if ($rslt =~ /VER_OK/) {
308             print "Using PERL=MCR $vmsfile\n" if $trace;
309             return "MCR $vmsfile";
310         }
311     }
312     print STDOUT "Unable to find a perl $ver (by these names: @$names, in these dirs: @$dirs)\n";
313     0; # false and not empty
314 }
315
316 =item path (override)
317
318 Translate logical name DCL$PATH as a searchlist, rather than trying
319 to C<split> string value of C<$ENV{'PATH'}>.
320
321 =cut
322
323 sub path {
324     return File::Spec->path();
325 }
326
327 =item maybe_command (override)
328
329 Follows VMS naming conventions for executable files.
330 If the name passed in doesn't exactly match an executable file,
331 appends F<.Exe> (or equivalent) to check for executable image, and F<.Com>
332 to check for DCL procedure.  If this fails, checks directories in DCL$PATH
333 and finally F<Sys$System:> for an executable file having the name specified,
334 with or without the F<.Exe>-equivalent suffix.
335
336 =cut
337
338 sub maybe_command {
339     my($self,$file) = @_;
340     return $file if -x $file && ! -d _;
341     my(@dirs) = ('');
342     my(@exts) = ('',$Config{'exe_ext'},'.exe','.com');
343     my($dir,$ext);
344     if ($file !~ m![/:>\]]!) {
345         for (my $i = 0; defined $ENV{"DCL\$PATH;$i"}; $i++) {
346             $dir = $ENV{"DCL\$PATH;$i"};
347             $dir .= ':' unless $dir =~ m%[\]:]$%;
348             push(@dirs,$dir);
349         }
350         push(@dirs,'Sys$System:');
351         foreach $dir (@dirs) {
352             my $sysfile = "$dir$file";
353             foreach $ext (@exts) {
354                 return $file if -x "$sysfile$ext" && ! -d _;
355             }
356         }
357     }
358     return 0;
359 }
360
361 =item maybe_command_in_dirs (override)
362
363 Uses DCL argument quoting on test command line.
364
365 =cut
366
367 sub maybe_command_in_dirs {     # $ver is optional argument if looking for perl
368     my($self, $names, $dirs, $trace, $ver) = @_;
369     my($name, $dir);
370     foreach $dir (@$dirs){
371         next unless defined $dir; # $self->{PERL_SRC} may be undefined
372         foreach $name (@$names){
373             my($abs,$tryabs);
374             if (File::Spec->file_name_is_absolute($name)) {
375                 $abs = $name;
376             } else {
377                 $abs = File::Spec->catfile($dir, $name);
378             }
379             print "Checking $abs for $name\n" if ($trace >= 2);
380             next unless $tryabs = $self->maybe_command($abs);
381             print "Substituting $tryabs instead of $abs\n" 
382                 if ($trace >= 2 and $tryabs ne $abs);
383             $abs = $tryabs;
384             if (defined $ver) {
385                 print "Executing $abs\n" if ($trace >= 2);
386                 if (`$abs -e 'require $ver; print "VER_OK\n" ' 2>&1` =~ /VER_OK/) {
387                     print "Using $abs\n" if $trace;
388                     return $abs;
389                 }
390             } else { # Do not look for perl
391                 return $abs;
392             }
393         }
394     }
395 }
396
397 =item perl_script (override)
398
399 If name passed in doesn't specify a readable file, appends F<.com> or
400 F<.pl> and tries again, since it's customary to have file types on all files
401 under VMS.
402
403 =cut
404
405 sub perl_script {
406     my($self,$file) = @_;
407     return $file if -r $file && ! -d _;
408     return "$file.com" if -r "$file.com";
409     return "$file.pl" if -r "$file.pl";
410     return '';
411 }
412
413 =item file_name_is_absolute (override)
414
415 Checks for VMS directory spec as well as Unix separators.
416
417 =cut
418
419 sub file_name_is_absolute {
420     shift;
421     return File::Spec->file_name_is_absolute(@_);
422 }
423
424 =item replace_manpage_separator
425
426 Use as separator a character which is legal in a VMS-syntax file name.
427
428 =cut
429
430 sub replace_manpage_separator {
431     my($self,$man) = @_;
432     $man = unixify($man);
433     $man =~ s#/+#__#g;
434     $man;
435 }
436
437 =item init_others (override)
438
439 Provide VMS-specific forms of various utility commands, then hand
440 off to the default MM_Unix method.
441
442 =cut
443
444 sub init_others {
445     my($self) = @_;
446
447     $self->{NOOP} = 'Continue';
448     $self->{FIRST_MAKEFILE} ||= 'Descrip.MMS';
449     $self->{MAKE_APERL_FILE} ||= 'Makeaperl.MMS';
450     $self->{MAKEFILE} ||= $self->{FIRST_MAKEFILE};
451     $self->{NOECHO} ||= '@ ';
452     $self->{RM_F} = '$(PERL) -e "foreach (@ARGV) { 1 while ( -d $_ ? rmdir $_ : unlink $_)}"';
453     $self->{RM_RF} = '$(PERL) "-I$(PERL_LIB)" -e "use File::Path; @dirs = map(VMS::Filespec::unixify($_),@ARGV); rmtree(\@dirs,0,0)"';
454     $self->{TOUCH} = '$(PERL) -e "$t=time; foreach (@ARGV) { -e $_ ? utime($t,$t,@ARGV) : (open(F,qq(>$_)),close F)}"';
455     $self->{CHMOD} = '$(PERL) -e "chmod @ARGV"';  # expect Unix syntax from MakeMaker
456     $self->{CP} = 'Copy/NoConfirm';
457     $self->{MV} = 'Rename/NoConfirm';
458     $self->{UMASK_NULL} = '! ';  
459     &ExtUtils::MM_Unix::init_others;
460 }
461
462 =item constants (override)
463
464 Fixes up numerous file and directory macros to insure VMS syntax
465 regardless of input syntax.  Also adds a few VMS-specific macros
466 and makes lists of files comma-separated.
467
468 =cut
469
470 sub constants {
471     my($self) = @_;
472     my(@m,$def,$macro);
473
474     # Be kind about case for pollution
475     for (@ARGV) { $_ = uc($_) if /POLLUTE/i; }
476
477     if ($self->{DEFINE} ne '') {
478         my(@terms) = split(/\s+/,$self->{DEFINE});
479         my(@defs,@udefs);
480         foreach $def (@terms) {
481             next unless $def;
482             my $targ = \@defs;
483             if ($def =~ s/^-([DU])//) {       # If it was a Unix-style definition
484                 if ($1 eq 'U') { $targ = \@udefs; }
485                 $def =~ s/='(.*)'$/=$1/;  # then remove shell-protection ''
486                 $def =~ s/^'(.*)'$/$1/;   # from entire term or argument
487             }
488             if ($def =~ /=/) {
489                 $def =~ s/"/""/g;  # Protect existing " from DCL
490                 $def = qq["$def"]; # and quote to prevent parsing of =
491             }
492             push @$targ, $def;
493         }
494         $self->{DEFINE} = '';
495         if (@defs)  { $self->{DEFINE}  = '/Define=(' . join(',',@defs)  . ')'; }
496         if (@udefs) { $self->{DEFINE} .= '/Undef=('  . join(',',@udefs) . ')'; }
497     }
498
499     if ($self->{OBJECT} =~ /\s/) {
500         $self->{OBJECT} =~ s/(\\)?\n+\s+/ /g;
501         $self->{OBJECT} = $self->wraplist(map($self->fixpath($_,0),split(/,?\s+/,$self->{OBJECT})));
502     }
503     $self->{LDFROM} = $self->wraplist(map($self->fixpath($_,0),split(/,?\s+/,$self->{LDFROM})));
504
505
506     # Fix up directory specs
507     $self->{ROOTEXT} = $self->{ROOTEXT} ? $self->fixpath($self->{ROOTEXT},1)
508                                         : '[]';
509     foreach $macro ( qw [
510             INST_BIN INST_SCRIPT INST_LIB INST_ARCHLIB INST_EXE INSTALLPRIVLIB
511             INSTALLARCHLIB INSTALLSCRIPT INSTALLBIN PERL_LIB PERL_ARCHLIB
512             PERL_INC PERL_SRC FULLEXT INST_MAN1DIR INSTALLMAN1DIR
513             INST_MAN3DIR INSTALLMAN3DIR INSTALLSITELIB INSTALLSITEARCH
514             SITELIBEXP SITEARCHEXP ] ) {
515         next unless defined $self->{$macro};
516         $self->{$macro} = $self->fixpath($self->{$macro},1);
517     }
518     $self->{PERL_VMS} = File::Spec->catdir($self->{PERL_SRC},q(VMS))
519         if ($self->{PERL_SRC});
520                         
521
522
523     # Fix up file specs
524     foreach $macro ( qw[LIBPERL_A FIRST_MAKEFILE MAKE_APERL_FILE MYEXTLIB] ) {
525         next unless defined $self->{$macro};
526         $self->{$macro} = $self->fixpath($self->{$macro},0);
527     }
528
529     foreach $macro (qw/
530               AR_STATIC_ARGS NAME DISTNAME NAME_SYM VERSION VERSION_SYM XS_VERSION
531               INST_BIN INST_EXE INST_LIB INST_ARCHLIB INST_SCRIPT PREFIX
532               INSTALLDIRS INSTALLPRIVLIB  INSTALLARCHLIB INSTALLSITELIB
533               INSTALLSITEARCH INSTALLBIN INSTALLSCRIPT PERL_LIB
534               PERL_ARCHLIB SITELIBEXP SITEARCHEXP LIBPERL_A MYEXTLIB
535               FIRST_MAKEFILE MAKE_APERL_FILE PERLMAINCC PERL_SRC PERL_VMS
536               PERL_INC PERL FULLPERL PERLRUN PERLRUNINST TEST_LIBS 
537               PERL_CORE
538               / ) {
539         next unless defined $self->{$macro};
540         push @m, "$macro = $self->{$macro}\n";
541     }
542
543
544     push @m, q[
545 VERSION_MACRO = VERSION
546 DEFINE_VERSION = "$(VERSION_MACRO)=""$(VERSION)"""
547 XS_VERSION_MACRO = XS_VERSION
548 XS_DEFINE_VERSION = "$(XS_VERSION_MACRO)=""$(XS_VERSION)"""
549
550 MAKEMAKER = ],File::Spec->catfile($self->{PERL_LIB},'ExtUtils','MakeMaker.pm'),qq[
551 MM_VERSION = $ExtUtils::MakeMaker::VERSION
552 MM_REVISION = $ExtUtils::MakeMaker::Revision
553 MM_VMS_REVISION = $ExtUtils::MM_VMS::Revision
554
555 # FULLEXT = Pathname for extension directory (eg DBD/Oracle).
556 # BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT.
557 # PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar)
558 # DLBASE  = Basename part of dynamic library. May be just equal BASEEXT.
559 ];
560
561     for my $tmp (qw/
562               FULLEXT VERSION_FROM OBJECT LDFROM
563               / ) {
564         next unless defined $self->{$tmp};
565         push @m, "$tmp = ",$self->fixpath($self->{$tmp},0),"\n";
566     }
567
568     for my $tmp (qw/
569               BASEEXT PARENT_NAME DLBASE INC DEFINE LINKTYPE
570               / ) {
571         next unless defined $self->{$tmp};
572         push @m, "$tmp = $self->{$tmp}\n";
573     }
574
575     for my $tmp (qw/ XS MAN1PODS MAN3PODS PM /) {
576         # Where is the space coming from? --jhi
577         next unless $self ne " " && defined $self->{$tmp};
578         my(%tmp,$key);
579         for $key (keys %{$self->{$tmp}}) {
580             $tmp{$self->fixpath($key,0)} = $self->fixpath($self->{$tmp}{$key},0);
581         }
582         $self->{$tmp} = \%tmp;
583     }
584
585     for my $tmp (qw/ C O_FILES H /) {
586         next unless defined $self->{$tmp};
587         my(@tmp,$val);
588         for $val (@{$self->{$tmp}}) {
589             push(@tmp,$self->fixpath($val,0));
590         }
591         $self->{$tmp} = \@tmp;
592     }
593
594     push @m,'
595
596 # Handy lists of source code files:
597 XS_FILES = ',$self->wraplist(sort keys %{$self->{XS}}),'
598 C_FILES  = ',$self->wraplist(@{$self->{C}}),'
599 O_FILES  = ',$self->wraplist(@{$self->{O_FILES}} ),'
600 H_FILES  = ',$self->wraplist(@{$self->{H}}),'
601 MAN1PODS = ',$self->wraplist(sort keys %{$self->{MAN1PODS}}),'
602 MAN3PODS = ',$self->wraplist(sort keys %{$self->{MAN3PODS}}),'
603
604 ';
605
606     for my $tmp (qw/
607               INST_MAN1DIR INSTALLMAN1DIR MAN1EXT INST_MAN3DIR INSTALLMAN3DIR MAN3EXT
608               /) {
609         next unless defined $self->{$tmp};
610         push @m, "$tmp = $self->{$tmp}\n";
611     }
612
613 push @m,"
614 .SUFFIXES :
615 .SUFFIXES : \$(OBJ_EXT) .c .cpp .cxx .xs
616
617 # Here is the Config.pm that we are using/depend on
618 CONFIGDEP = \$(PERL_ARCHLIB)Config.pm, \$(PERL_INC)config.h \$(VERSION_FROM)
619
620 # Where to put things:
621 INST_LIBDIR      = $self->{INST_LIBDIR}
622 INST_ARCHLIBDIR  = $self->{INST_ARCHLIBDIR}
623
624 INST_AUTODIR     = $self->{INST_AUTODIR}
625 INST_ARCHAUTODIR = $self->{INST_ARCHAUTODIR}
626 ";
627
628     if ($self->has_link_code()) {
629         push @m,'
630 INST_STATIC = $(INST_ARCHAUTODIR)$(BASEEXT)$(LIB_EXT)
631 INST_DYNAMIC = $(INST_ARCHAUTODIR)$(DLBASE).$(DLEXT)
632 INST_BOOT = $(INST_ARCHAUTODIR)$(BASEEXT).bs
633 ';
634     } else {
635         my $shr = $Config{'dbgprefix'} . 'PERLSHR';
636         push @m,'
637 INST_STATIC =
638 INST_DYNAMIC =
639 INST_BOOT =
640 EXPORT_LIST = $(BASEEXT).opt
641 PERL_ARCHIVE = ',($ENV{$shr} ? $ENV{$shr} : "Sys\$Share:$shr.$Config{'dlext'}"),'
642 ';
643     }
644
645     $self->{TO_INST_PM} = [ sort keys %{$self->{PM}} ];
646     $self->{PM_TO_BLIB} = [ %{$self->{PM}} ];
647     push @m,'
648 TO_INST_PM = ',$self->wraplist(@{$self->{TO_INST_PM}}),'
649
650 PM_TO_BLIB = ',$self->wraplist(@{$self->{PM_TO_BLIB}}),'
651 ';
652
653     join('',@m);
654 }
655
656 =item cflags (override)
657
658 Bypass shell script and produce qualifiers for CC directly (but warn
659 user if a shell script for this extension exists).  Fold multiple
660 /Defines into one, since some C compilers pay attention to only one
661 instance of this qualifier on the command line.
662
663 =cut
664
665 sub cflags {
666     my($self,$libperl) = @_;
667     my($quals) = $self->{CCFLAGS} || $Config{'ccflags'};
668     my($definestr,$undefstr,$flagoptstr) = ('','','');
669     my($incstr) = '/Include=($(PERL_INC)';
670     my($name,$sys,@m);
671
672     ( $name = $self->{NAME} . "_cflags" ) =~ s/:/_/g ;
673     print STDOUT "Unix shell script ".$Config{"$self->{'BASEEXT'}_cflags"}.
674          " required to modify CC command for $self->{'BASEEXT'}\n"
675     if ($Config{$name});
676
677     if ($quals =~ / -[DIUOg]/) {
678         while ($quals =~ / -([Og])(\d*)\b/) {
679             my($type,$lvl) = ($1,$2);
680             $quals =~ s/ -$type$lvl\b\s*//;
681             if ($type eq 'g') { $flagoptstr = '/NoOptimize'; }
682             else { $flagoptstr = '/Optimize' . (defined($lvl) ? "=$lvl" : ''); }
683         }
684         while ($quals =~ / -([DIU])(\S+)/) {
685             my($type,$def) = ($1,$2);
686             $quals =~ s/ -$type$def\s*//;
687             $def =~ s/"/""/g;
688             if    ($type eq 'D') { $definestr .= qq["$def",]; }
689             elsif ($type eq 'I') { $incstr .= ',' . $self->fixpath($def,1); }
690             else                 { $undefstr  .= qq["$def",]; }
691         }
692     }
693     if (length $quals and $quals !~ m!/!) {
694         warn "MM_VMS: Ignoring unrecognized CCFLAGS elements \"$quals\"\n";
695         $quals = '';
696     }
697     $definestr .= q["PERL_POLLUTE",] if $self->{POLLUTE};
698     if (length $definestr) { chop($definestr); $quals .= "/Define=($definestr)"; }
699     if (length $undefstr)  { chop($undefstr);  $quals .= "/Undef=($undefstr)";   }
700     # Deal with $self->{DEFINE} here since some C compilers pay attention
701     # to only one /Define clause on command line, so we have to
702     # conflate the ones from $Config{'ccflags'} and $self->{DEFINE}
703     # ($self->{DEFINE} has already been VMSified in constants() above)
704     if ($self->{DEFINE}) { $quals .= $self->{DEFINE}; }
705     for my $type (qw(Def Undef)) {
706         my(@terms);
707         while ($quals =~ m:/${type}i?n?e?=([^/]+):ig) {
708                 my $term = $1;
709                 $term =~ s:^\((.+)\)$:$1:;
710                 push @terms, $term;
711             }
712         if ($type eq 'Def') {
713             push @terms, qw[ $(DEFINE_VERSION) $(XS_DEFINE_VERSION) ];
714         }
715         if (@terms) {
716             $quals =~ s:/${type}i?n?e?=[^/]+::ig;
717             $quals .= "/${type}ine=(" . join(',',@terms) . ')';
718         }
719     }
720
721     $libperl or $libperl = $self->{LIBPERL_A} || "libperl.olb";
722
723     # Likewise with $self->{INC} and /Include
724     if ($self->{'INC'}) {
725         my(@includes) = split(/\s+/,$self->{INC});
726         foreach (@includes) {
727             s/^-I//;
728             $incstr .= ','.$self->fixpath($_,1);
729         }
730     }
731     $quals .= "$incstr)";
732 #    $quals =~ s/,,/,/g; $quals =~ s/\(,/(/g;
733     $self->{CCFLAGS} = $quals;
734
735     $self->{OPTIMIZE} ||= $flagoptstr || $Config{'optimize'};
736     if ($self->{OPTIMIZE} !~ m!/!) {
737         if    ($self->{OPTIMIZE} =~ m!-g!) { $self->{OPTIMIZE} = '/Debug/NoOptimize' }
738         elsif ($self->{OPTIMIZE} =~ /-O(\d*)/) {
739             $self->{OPTIMIZE} = '/Optimize' . (defined($1) ? "=$1" : '');
740         }
741         else {
742             warn "MM_VMS: Can't parse OPTIMIZE \"$self->{OPTIMIZE}\"; using default\n" if length $self->{OPTIMIZE};
743             $self->{OPTIMIZE} = '/Optimize';
744         }
745     }
746
747     return $self->{CFLAGS} = qq{
748 CCFLAGS = $self->{CCFLAGS}
749 OPTIMIZE = $self->{OPTIMIZE}
750 PERLTYPE = $self->{PERLTYPE}
751 SPLIT =
752 LARGE =
753 };
754 }
755
756 =item const_cccmd (override)
757
758 Adds directives to point C preprocessor to the right place when
759 handling #include E<lt>sys/foo.hE<gt> directives.  Also constructs CC
760 command line a bit differently than MM_Unix method.
761
762 =cut
763
764 sub const_cccmd {
765     my($self,$libperl) = @_;
766     my(@m);
767
768     return $self->{CONST_CCCMD} if $self->{CONST_CCCMD};
769     return '' unless $self->needs_linking();
770     if ($Config{'vms_cc_type'} eq 'gcc') {
771         push @m,'
772 .FIRST
773         ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" Then Define/NoLog SYS GNU_CC_Include:[VMS]';
774     }
775     elsif ($Config{'vms_cc_type'} eq 'vaxc') {
776         push @m,'
777 .FIRST
778         ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("VAXC$Include").eqs."" Then Define/NoLog SYS Sys$Library
779         ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("VAXC$Include").nes."" Then Define/NoLog SYS VAXC$Include';
780     }
781     else {
782         push @m,'
783 .FIRST
784         ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("DECC$System_Include").eqs."" Then Define/NoLog SYS ',
785                 ($Config{'arch'} eq 'VMS_AXP' ? 'Sys$Library' : 'DECC$Library_Include'),'
786         ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("DECC$System_Include").nes."" Then Define/NoLog SYS DECC$System_Include';
787     }
788
789     push(@m, "\n\nCCCMD = $Config{'cc'} \$(CCFLAGS)\$(OPTIMIZE)\n");
790
791     $self->{CONST_CCCMD} = join('',@m);
792 }
793
794 =item pm_to_blib (override)
795
796 DCL I<still> accepts a maximum of 255 characters on a command
797 line, so we write the (potentially) long list of file names
798 to a temp file, then persuade Perl to read it instead of the
799 command line to find args.
800
801 =cut
802
803 sub pm_to_blib {
804     my($self) = @_;
805     my($line,$from,$to,@m);
806     my($autodir) = File::Spec->catdir('$(INST_LIB)','auto');
807     my(@files) = @{$self->{PM_TO_BLIB}};
808
809     push @m, q{
810
811 # Dummy target to match Unix target name; we use pm_to_blib.ts as
812 # timestamp file to avoid repeated invocations under VMS
813 pm_to_blib : pm_to_blib.ts
814         $(NOECHO) $(NOOP)
815
816 # As always, keep under DCL's 255-char limit
817 pm_to_blib.ts : $(TO_INST_PM)
818         $(NOECHO) $(PERL) -e "print '},shift(@files),q{ },shift(@files),q{'" >.MM_tmp
819 };
820
821     $line = '';  # avoid uninitialized var warning
822     while ($from = shift(@files),$to = shift(@files)) {
823         $line .= " $from $to";
824         if (length($line) > 128) {
825             push(@m,"\t\$(NOECHO) \$(PERL) -e \"print '$line'\" >>.MM_tmp\n");
826             $line = '';
827         }
828     }
829     push(@m,"\t\$(NOECHO) \$(PERL) -e \"print '$line'\" >>.MM_tmp\n") if $line;
830
831     push(@m,q[  $(PERL) "-I$(PERL_LIB)" "-MExtUtils::Install" -e "pm_to_blib({split(' ',<STDIN>)},'].$autodir.q[','$(PM_FILTER)')" <.MM_tmp]);
832     push(@m,qq[
833         \$(NOECHO) Delete/NoLog/NoConfirm .MM_tmp;
834         \$(NOECHO) \$(TOUCH) pm_to_blib.ts
835 ]);
836
837     join('',@m);
838 }
839
840 =item tool_autosplit (override)
841
842 Use VMS-style quoting on command line.
843
844 =cut
845
846 sub tool_autosplit{
847     my($self, %attribs) = @_;
848     my($asl) = "";
849     $asl = "\$AutoSplit::Maxlen=$attribs{MAXLEN};" if $attribs{MAXLEN};
850     q{
851 # Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto
852 AUTOSPLITFILE = $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e "use AutoSplit;}.$asl.q{ AutoSplit::autosplit($ARGV[0], $ARGV[1], 0, 1, 1) ;"
853 };
854 }
855
856 =item tool_sxubpp (override)
857
858 Use VMS-style quoting on xsubpp command line.
859
860 =cut
861
862 sub tool_xsubpp {
863     my($self) = @_;
864     return '' unless $self->needs_linking;
865     my($xsdir) = File::Spec->catdir($self->{PERL_LIB},'ExtUtils');
866     # drop back to old location if xsubpp is not in new location yet
867     $xsdir = File::Spec->catdir($self->{PERL_SRC},'ext') unless (-f File::Spec->catfile($xsdir,'xsubpp'));
868     my(@tmdeps) = '$(XSUBPPDIR)typemap';
869     if( $self->{TYPEMAPS} ){
870         my $typemap;
871         foreach $typemap (@{$self->{TYPEMAPS}}){
872                 if( ! -f  $typemap ){
873                         warn "Typemap $typemap not found.\n";
874                 }
875                 else{
876                         push(@tmdeps, $self->fixpath($typemap,0));
877                 }
878         }
879     }
880     push(@tmdeps, "typemap") if -f "typemap";
881     my(@tmargs) = map("-typemap $_", @tmdeps);
882     if( exists $self->{XSOPT} ){
883         unshift( @tmargs, $self->{XSOPT} );
884     }
885
886     if ($Config{'ldflags'} && 
887         $Config{'ldflags'} =~ m!/Debug!i &&
888         (!exists($self->{XSOPT}) || $self->{XSOPT} !~ /linenumbers/)) {
889         unshift(@tmargs,'-nolinenumbers');
890     }
891     my $xsubpp_version = $self->xsubpp_version(File::Spec->catfile($xsdir,'xsubpp'));
892
893     # What are the correct thresholds for version 1 && 2 Paul?
894     if ( $xsubpp_version > 1.923 ){
895         $self->{XSPROTOARG} = '' unless defined $self->{XSPROTOARG};
896     } else {
897         if (defined $self->{XSPROTOARG} && $self->{XSPROTOARG} =~ /\-prototypes/) {
898             print STDOUT qq{Warning: This extension wants to pass the switch "-prototypes" to xsubpp.
899         Your version of xsubpp is $xsubpp_version and cannot handle this.
900         Please upgrade to a more recent version of xsubpp.
901 };
902         } else {
903             $self->{XSPROTOARG} = "";
904         }
905     }
906
907     "
908 XSUBPPDIR = $xsdir
909 XSUBPP = \$(PERL) \"-I\$(PERL_ARCHLIB)\" \"-I\$(PERL_LIB)\" \$(XSUBPPDIR)xsubpp
910 XSPROTOARG = $self->{XSPROTOARG}
911 XSUBPPDEPS = @tmdeps
912 XSUBPPARGS = @tmargs
913 ";
914 }
915
916 =item xsubpp_version (override)
917
918 Test xsubpp exit status according to VMS rules ($sts & 1 ==E<gt> good)
919 rather than Unix rules ($sts == 0 ==E<gt> good).
920
921 =cut
922
923 sub xsubpp_version
924 {
925     my($self,$xsubpp) = @_;
926     my ($version) ;
927     return '' unless $self->needs_linking;
928
929     # try to figure out the version number of the xsubpp on the system
930
931     # first try the -v flag, introduced in 1.921 & 2.000a2
932
933     my $command = "$self->{PERL} \"-I$self->{PERL_LIB}\" $xsubpp -v";
934     print "Running: $command\n" if $Verbose;
935     $version = `$command` ;
936     if ($?) {
937         use vmsish 'status';
938         warn "Running '$command' exits with status $?";
939     }
940     chop $version ;
941
942     return $1 if $version =~ /^xsubpp version (.*)/ ;
943
944     # nope, then try something else
945
946     my $counter = '000';
947     my ($file) = 'temp' ;
948     $counter++ while -e "$file$counter"; # don't overwrite anything
949     $file .= $counter;
950
951     local(*F);
952     open(F, ">$file") or die "Cannot open file '$file': $!\n" ;
953     print F <<EOM ;
954 MODULE = fred PACKAGE = fred
955
956 int
957 fred(a)
958         int     a;
959 EOM
960
961     close F ;
962
963     $command = "$self->{PERL} $xsubpp $file";
964     print "Running: $command\n" if $Verbose;
965     my $text = `$command` ;
966     if ($?) {
967         use vmsish 'status';
968         warn "Running '$command' exits with status $?";
969     }
970     unlink $file ;
971
972     # gets 1.2 -> 1.92 and 2.000a1
973     return $1 if $text =~ /automatically by xsubpp version ([\S]+)\s*/  ;
974
975     # it is either 1.0 or 1.1
976     return 1.1 if $text =~ /^Warning: ignored semicolon/ ;
977
978     # none of the above, so 1.0
979     return "1.0" ;
980 }
981
982 =item tools_other (override)
983
984 Adds a few MM[SK] macros, and shortens some the installatin commands,
985 in order to stay under DCL's 255-character limit.  Also changes
986 EQUALIZE_TIMESTAMP to set revision date of target file to one second
987 later than source file, since MMK interprets precisely equal revision
988 dates for a source and target file as a sign that the target needs
989 to be updated.
990
991 =cut
992
993 sub tools_other {
994     my($self) = @_;
995     qq!
996 # Assumes \$(MMS) invokes MMS or MMK
997 # (It is assumed in some cases later that the default makefile name
998 # (Descrip.MMS for MM[SK]) is used.)
999 USEMAKEFILE = /Descrip=
1000 USEMACROS = /Macro=(
1001 MACROEND = )
1002 MAKEFILE = Descrip.MMS
1003 SHELL = Posix
1004 TOUCH = $self->{TOUCH}
1005 CHMOD = $self->{CHMOD}
1006 CP = $self->{CP}
1007 MV = $self->{MV}
1008 RM_F  = $self->{RM_F}
1009 RM_RF = $self->{RM_RF}
1010 SAY = Write Sys\$Output
1011 UMASK_NULL = $self->{UMASK_NULL}
1012 NOOP = $self->{NOOP}
1013 NOECHO = $self->{NOECHO}
1014 MKPATH = Create/Directory
1015 EQUALIZE_TIMESTAMP = \$(PERL) -we "open F,qq{>\$ARGV[1]};close F;utime(0,(stat(\$ARGV[0]))[9]+1,\$ARGV[1])"
1016 !. ($self->{PARENT} ? '' : 
1017 qq!WARN_IF_OLD_PACKLIST = \$(PERL) -e "if (-f \$ARGV[0]){print qq[WARNING: Old package found (\$ARGV[0]); please check for collisions\\n]}"
1018 MOD_INSTALL = \$(PERL) "-I\$(PERL_LIB)" "-MExtUtils::Install" -e "install({split(' ',<STDIN>)},1);"
1019 DOC_INSTALL = \$(PERL) -e "\@ARGV=split(/\\|/,<STDIN>);print '=head2 ',scalar(localtime),': C<',shift,qq[>\\n\\n=over 4\\n\\n];while(\$key=shift && \$val=shift){print qq[=item *\\n\\nC<\$key: \$val>\\n\\n];}print qq[=back\\n\\n]"
1020 UNINSTALL = \$(PERL) "-I\$(PERL_LIB)" "-MExtUtils::Install" -e "uninstall(\$ARGV[0],1,1);"
1021 !);
1022 }
1023
1024 =item dist (override)
1025
1026 Provide VMSish defaults for some values, then hand off to
1027 default MM_Unix method.
1028
1029 =cut
1030
1031 sub dist {
1032     my($self, %attribs) = @_;
1033     $attribs{VERSION}      ||= $self->{VERSION_SYM};
1034     $attribs{NAME}         ||= $self->{DISTNAME};
1035     $attribs{ZIPFLAGS}     ||= '-Vu';
1036     $attribs{COMPRESS}     ||= 'gzip';
1037     $attribs{SUFFIX}       ||= '-gz';
1038     $attribs{SHAR}         ||= 'vms_share';
1039     $attribs{DIST_DEFAULT} ||= 'zipdist';
1040
1041     # Sanitize these for use in $(DISTVNAME) filespec
1042     $attribs{VERSION} =~ s/[^\w\$]/_/g;
1043     $attribs{NAME} =~ s/[^\w\$]/-/g;
1044
1045     return ExtUtils::MM_Unix::dist($self,%attribs);
1046 }
1047
1048 =item c_o (override)
1049
1050 Use VMS syntax on command line.  In particular, $(DEFINE) and
1051 $(PERL_INC) have been pulled into $(CCCMD).  Also use MM[SK] macros.
1052
1053 =cut
1054
1055 sub c_o {
1056     my($self) = @_;
1057     return '' unless $self->needs_linking();
1058     '
1059 .c$(OBJ_EXT) :
1060         $(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).c
1061
1062 .cpp$(OBJ_EXT) :
1063         $(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).cpp
1064
1065 .cxx$(OBJ_EXT) :
1066         $(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).cxx
1067
1068 ';
1069 }
1070
1071 =item xs_c (override)
1072
1073 Use MM[SK] macros.
1074
1075 =cut
1076
1077 sub xs_c {
1078     my($self) = @_;
1079     return '' unless $self->needs_linking();
1080     '
1081 .xs.c :
1082         $(XSUBPP) $(XSPROTOARG) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET)
1083 ';
1084 }
1085
1086 =item xs_o (override)
1087
1088 Use MM[SK] macros, and VMS command line for C compiler.
1089
1090 =cut
1091
1092 sub xs_o {      # many makes are too dumb to use xs_c then c_o
1093     my($self) = @_;
1094     return '' unless $self->needs_linking();
1095     '
1096 .xs$(OBJ_EXT) :
1097         $(XSUBPP) $(XSPROTOARG) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET_NAME).c
1098         $(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).c
1099 ';
1100 }
1101
1102 =item top_targets (override)
1103
1104 Use VMS quoting on command line for Version_check.
1105
1106 =cut
1107
1108 sub top_targets {
1109     my($self) = shift;
1110     my(@m);
1111     push @m, '
1112 all :: pure_all manifypods
1113         $(NOECHO) $(NOOP)
1114
1115 pure_all :: config pm_to_blib subdirs linkext
1116         $(NOECHO) $(NOOP)
1117
1118 subdirs :: $(MYEXTLIB)
1119         $(NOECHO) $(NOOP)
1120
1121 config :: $(MAKEFILE) $(INST_LIBDIR).exists
1122         $(NOECHO) $(NOOP)
1123
1124 config :: $(INST_ARCHAUTODIR).exists
1125         $(NOECHO) $(NOOP)
1126
1127 config :: $(INST_AUTODIR).exists
1128         $(NOECHO) $(NOOP)
1129 ';
1130
1131     push @m, $self->dir_target(qw[$(INST_AUTODIR) $(INST_LIBDIR) $(INST_ARCHAUTODIR)]);
1132     if (%{$self->{MAN1PODS}}) {
1133         push @m, q[
1134 config :: $(INST_MAN1DIR).exists
1135         $(NOECHO) $(NOOP)
1136 ];
1137         push @m, $self->dir_target(qw[$(INST_MAN1DIR)]);
1138     }
1139     if (%{$self->{MAN3PODS}}) {
1140         push @m, q[
1141 config :: $(INST_MAN3DIR).exists
1142         $(NOECHO) $(NOOP)
1143 ];
1144         push @m, $self->dir_target(qw[$(INST_MAN3DIR)]);
1145     }
1146
1147     push @m, '
1148 $(O_FILES) : $(H_FILES)
1149 ' if @{$self->{O_FILES} || []} && @{$self->{H} || []};
1150
1151     push @m, q{
1152 help :
1153         perldoc ExtUtils::MakeMaker
1154 };
1155
1156     push @m, q{
1157 Version_check :
1158         $(NOECHO) $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -
1159         "-MExtUtils::MakeMaker=Version_check" -e "&Version_check('$(MM_VERSION)')"
1160 };
1161
1162     join('',@m);
1163 }
1164
1165 =item dlsyms (override)
1166
1167 Create VMS linker options files specifying universal symbols for this
1168 extension's shareable image, and listing other shareable images or 
1169 libraries to which it should be linked.
1170
1171 =cut
1172
1173 sub dlsyms {
1174     my($self,%attribs) = @_;
1175
1176     return '' unless $self->needs_linking();
1177
1178     my($funcs) = $attribs{DL_FUNCS} || $self->{DL_FUNCS} || {};
1179     my($vars)  = $attribs{DL_VARS}  || $self->{DL_VARS}  || [];
1180     my($funclist)  = $attribs{FUNCLIST}  || $self->{FUNCLIST}  || [];
1181     my(@m);
1182
1183     unless ($self->{SKIPHASH}{'dynamic'}) {
1184         push(@m,'
1185 dynamic :: $(INST_ARCHAUTODIR)$(BASEEXT).opt
1186         $(NOECHO) $(NOOP)
1187 ');
1188     }
1189
1190     push(@m,'
1191 static :: $(INST_ARCHAUTODIR)$(BASEEXT).opt
1192         $(NOECHO) $(NOOP)
1193 ') unless $self->{SKIPHASH}{'static'};
1194
1195     push @m,'
1196 $(INST_ARCHAUTODIR)$(BASEEXT).opt : $(BASEEXT).opt
1197         $(CP) $(MMS$SOURCE) $(MMS$TARGET)
1198
1199 $(BASEEXT).opt : Makefile.PL
1200         $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e "use ExtUtils::Mksymlists;" -
1201         ',qq[-e "Mksymlists('NAME' => '$self->{NAME}', 'DL_FUNCS' => ],
1202         neatvalue($funcs),q[, 'DL_VARS' => ],neatvalue($vars),
1203         q[, 'FUNCLIST' => ],neatvalue($funclist),qq[)"\n];
1204
1205     push @m, '  $(PERL) -e "print ""$(INST_STATIC)/Include=';
1206     if ($self->{OBJECT} =~ /\bBASEEXT\b/ or
1207         $self->{OBJECT} =~ /\b$self->{BASEEXT}\b/i) { 
1208         push @m, ($Config{d_vms_case_sensitive_symbols}
1209                    ? uc($self->{BASEEXT}) :'$(BASEEXT)');
1210     }
1211     else {  # We don't have a "main" object file, so pull 'em all in
1212        # Upcase module names if linker is being case-sensitive
1213        my($upcase) = $Config{d_vms_case_sensitive_symbols};
1214         my(@omods) = map { s/\.[^.]*$//;         # Trim off file type
1215                            s[\$\(\w+_EXT\)][];   # even as a macro
1216                            s/.*[:>\/\]]//;       # Trim off dir spec
1217                            $upcase ? uc($_) : $_;
1218                          } split ' ', $self->eliminate_macros($self->{OBJECT});
1219         my($tmp,@lines,$elt) = '';
1220         $tmp = shift @omods;
1221         foreach $elt (@omods) {
1222             $tmp .= ",$elt";
1223                 if (length($tmp) > 80) { push @lines, $tmp;  $tmp = ''; }
1224         }
1225         push @lines, $tmp;
1226         push @m, '(', join( qq[, -\\n\\t"";" >>\$(MMS\$TARGET)\n\t\$(PERL) -e "print ""], @lines),')';
1227     }
1228         push @m, '\n$(INST_STATIC)/Library\n"";" >>$(MMS$TARGET)',"\n";
1229
1230     if (length $self->{LDLOADLIBS}) {
1231         my($lib); my($line) = '';
1232         foreach $lib (split ' ', $self->{LDLOADLIBS}) {
1233             $lib =~ s%\$%\\\$%g;  # Escape '$' in VMS filespecs
1234             if (length($line) + length($lib) > 160) {
1235                 push @m, "\t\$(PERL) -e \"print qq{$line}\" >>\$(MMS\$TARGET)\n";
1236                 $line = $lib . '\n';
1237             }
1238             else { $line .= $lib . '\n'; }
1239         }
1240         push @m, "\t\$(PERL) -e \"print qq{$line}\" >>\$(MMS\$TARGET)\n" if $line;
1241     }
1242
1243     join('',@m);
1244
1245 }
1246
1247 =item dynamic_lib (override)
1248
1249 Use VMS Link command.
1250
1251 =cut
1252
1253 sub dynamic_lib {
1254     my($self, %attribs) = @_;
1255     return '' unless $self->needs_linking(); #might be because of a subdir
1256
1257     return '' unless $self->has_link_code();
1258
1259     my($otherldflags) = $attribs{OTHERLDFLAGS} || "";
1260     my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || "";
1261     my $shr = $Config{'dbgprefix'} . 'PerlShr';
1262     my(@m);
1263     push @m,"
1264
1265 OTHERLDFLAGS = $otherldflags
1266 INST_DYNAMIC_DEP = $inst_dynamic_dep
1267
1268 ";
1269     push @m, '
1270 $(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt $(INST_ARCHAUTODIR).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP)
1271         $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR)
1272         If F$TrnLNm("',$shr,'").eqs."" Then Define/NoLog/User ',"$shr Sys\$Share:$shr.$Config{'dlext'}",'
1273         Link $(LDFLAGS) /Shareable=$(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,$(PERL_INC)perlshr_attr.opt/Option
1274 ';
1275
1276     push @m, $self->dir_target('$(INST_ARCHAUTODIR)');
1277     join('',@m);
1278 }
1279
1280 =item dynamic_bs (override)
1281
1282 Use VMS-style quoting on Mkbootstrap command line.
1283
1284 =cut
1285
1286 sub dynamic_bs {
1287     my($self, %attribs) = @_;
1288     return '
1289 BOOTSTRAP =
1290 ' unless $self->has_link_code();
1291     '
1292 BOOTSTRAP = '."$self->{BASEEXT}.bs".'
1293
1294 # As MakeMaker mkbootstrap might not write a file (if none is required)
1295 # we use touch to prevent make continually trying to remake it.
1296 # The DynaLoader only reads a non-empty file.
1297 $(BOOTSTRAP) : $(MAKEFILE) '."$self->{BOOTDEP}".' $(INST_ARCHAUTODIR).exists
1298         $(NOECHO) $(SAY) "Running mkbootstrap for $(NAME) ($(BSLOADLIBS))"
1299         $(NOECHO) $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -
1300         -e "use ExtUtils::Mkbootstrap; Mkbootstrap(\'$(BASEEXT)\',\'$(BSLOADLIBS)\');"
1301         $(NOECHO) $(TOUCH) $(MMS$TARGET)
1302
1303 $(INST_BOOT) : $(BOOTSTRAP) $(INST_ARCHAUTODIR).exists
1304         $(NOECHO) $(RM_RF) $(INST_BOOT)
1305         - $(CP) $(BOOTSTRAP) $(INST_BOOT)
1306 ';
1307 }
1308
1309 =item static_lib (override)
1310
1311 Use VMS commands to manipulate object library.
1312
1313 =cut
1314
1315 sub static_lib {
1316     my($self) = @_;
1317     return '' unless $self->needs_linking();
1318
1319     return '
1320 $(INST_STATIC) :
1321         $(NOECHO) $(NOOP)
1322 ' unless ($self->{OBJECT} or @{$self->{C} || []} or $self->{MYEXTLIB});
1323
1324     my(@m,$lib);
1325     push @m,'
1326 # Rely on suffix rule for update action
1327 $(OBJECT) : $(INST_ARCHAUTODIR).exists
1328
1329 $(INST_STATIC) : $(OBJECT) $(MYEXTLIB)
1330 ';
1331     # If this extension has its own library (eg SDBM_File)
1332     # then copy that to $(INST_STATIC) and add $(OBJECT) into it.
1333     push(@m, "\t",'$(CP) $(MYEXTLIB) $(MMS$TARGET)',"\n") if $self->{MYEXTLIB};
1334
1335     push(@m,"\t",'If F$Search("$(MMS$TARGET)").eqs."" Then Library/Object/Create $(MMS$TARGET)',"\n");
1336
1337     # if there was a library to copy, then we can't use MMS$SOURCE_LIST,
1338     # 'cause it's a library and you can't stick them in other libraries.
1339     # In that case, we use $OBJECT instead and hope for the best
1340     if ($self->{MYEXTLIB}) {
1341       push(@m,"\t",'Library/Object/Replace $(MMS$TARGET) $(OBJECT)',"\n"); 
1342     } else {
1343       push(@m,"\t",'Library/Object/Replace $(MMS$TARGET) $(MMS$SOURCE_LIST)',"\n");
1344     }
1345     
1346     push @m, "\t\$(NOECHO) \$(PERL) -e 1 >\$(INST_ARCHAUTODIR)extralibs.ld\n";
1347     foreach $lib (split ' ', $self->{EXTRALIBS}) {
1348       push(@m,"\t",'$(NOECHO) $(PERL) -e "print qq{',$lib,'\n}" >>$(INST_ARCHAUTODIR)extralibs.ld',"\n");
1349     }
1350     push @m, $self->dir_target('$(INST_ARCHAUTODIR)');
1351     join('',@m);
1352 }
1353
1354
1355 =item manifypods (override)
1356
1357 Use VMS-style quoting on command line, and VMS logical name
1358 to specify fallback location at build time if we can't find pod2man.
1359
1360 =cut
1361
1362
1363 sub manifypods {
1364     my($self, %attribs) = @_;
1365     return "\nmanifypods :\n\t\$(NOECHO) \$(NOOP)\n" unless %{$self->{MAN3PODS}} or %{$self->{MAN1PODS}};
1366     my($dist);
1367     my($pod2man_exe);
1368     if (defined $self->{PERL_SRC}) {
1369         $pod2man_exe = File::Spec->catfile($self->{PERL_SRC},'pod','pod2man');
1370     } else {
1371         $pod2man_exe = File::Spec->catfile($Config{scriptdirexp},'pod2man');
1372     }
1373     if (not ($pod2man_exe = $self->perl_script($pod2man_exe))) {
1374         # No pod2man but some MAN3PODS to be installed
1375         print <<END;
1376
1377 Warning: I could not locate your pod2man program.  As a last choice,
1378          I will look for the file to which the logical name POD2MAN
1379          points when MMK is invoked.
1380
1381 END
1382         $pod2man_exe = "pod2man";
1383     }
1384     my(@m);
1385     push @m,
1386 qq[POD2MAN_EXE = $pod2man_exe\n],
1387 q[POD2MAN = $(PERL) -we "%m=@ARGV;for (keys %m){" -
1388 -e "system(qq/MCR $^X ""-I$(PERL_ARCHLIB)"" ""-I$(PERL_LIB)"" $(POD2MAN_EXE) $_ >$m{$_}/);}"
1389 ];
1390     push @m, "\nmanifypods : \$(MAN1PODS) \$(MAN3PODS)\n";
1391     if (%{$self->{MAN1PODS}} || %{$self->{MAN3PODS}}) {
1392         my($pod);
1393         foreach $pod (sort keys %{$self->{MAN1PODS}}) {
1394             push @m, qq[\t\@- If F\$Search("\$(POD2MAN_EXE)").nes."" Then \$(POD2MAN) ];
1395             push @m, "$pod $self->{MAN1PODS}{$pod}\n";
1396         }
1397         foreach $pod (sort keys %{$self->{MAN3PODS}}) {
1398             push @m, qq[\t\@- If F\$Search("\$(POD2MAN_EXE)").nes."" Then \$(POD2MAN) ];
1399             push @m, "$pod $self->{MAN3PODS}{$pod}\n";
1400         }
1401     }
1402     join('', @m);
1403 }
1404
1405 =item processPL (override)
1406
1407 Use VMS-style quoting on command line.
1408
1409 =cut
1410
1411 sub processPL {
1412     my($self) = @_;
1413     return "" unless $self->{PL_FILES};
1414     my(@m, $plfile);
1415     foreach $plfile (sort keys %{$self->{PL_FILES}}) {
1416         my $list = ref($self->{PL_FILES}->{$plfile})
1417                 ? $self->{PL_FILES}->{$plfile}
1418                 : [$self->{PL_FILES}->{$plfile}];
1419         foreach my $target (@$list) {
1420             my $vmsplfile = vmsify($plfile);
1421             my $vmsfile = vmsify($target);
1422             push @m, "
1423 all :: $vmsfile
1424         \$(NOECHO) \$(NOOP)
1425
1426 $vmsfile :: $vmsplfile
1427 ",'     $(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" '," $vmsplfile $vmsfile
1428 ";
1429         }
1430     }
1431     join "", @m;
1432 }
1433
1434 =item installbin (override)
1435
1436 Stay under DCL's 255 character command line limit once again by
1437 splitting potentially long list of files across multiple lines
1438 in C<realclean> target.
1439
1440 =cut
1441
1442 sub installbin {
1443     my($self) = @_;
1444     return '' unless $self->{EXE_FILES} && ref $self->{EXE_FILES} eq "ARRAY";
1445     return '' unless @{$self->{EXE_FILES}};
1446     my(@m, $from, $to, %fromto, @to, $line);
1447     my(@exefiles) = map { vmsify($_) } @{$self->{EXE_FILES}};
1448     for $from (@exefiles) {
1449         my($path) = '$(INST_SCRIPT)' . basename($from);
1450         local($_) = $path;  # backward compatibility
1451         $to = $self->libscan($path);
1452         print "libscan($from) => '$to'\n" if ($Verbose >=2);
1453         $fromto{$from} = vmsify($to);
1454     }
1455     @to = values %fromto;
1456     push @m, "
1457 EXE_FILES = @exefiles
1458
1459 all :: @to
1460         \$(NOECHO) \$(NOOP)
1461
1462 realclean ::
1463 ";
1464     $line = '';  #avoid unitialized var warning
1465     foreach $to (@to) {
1466         if (length($line) + length($to) > 80) {
1467             push @m, "\t\$(RM_F) $line\n";
1468             $line = $to;
1469         }
1470         else { $line .= " $to"; }
1471     }
1472     push @m, "\t\$(RM_F) $line\n\n" if $line;
1473
1474     while (($from,$to) = each %fromto) {
1475         last unless defined $from;
1476         my $todir;
1477         if ($to =~ m#[/>:\]]#) { $todir = dirname($to); }
1478         else                   { ($todir = $to) =~ s/[^\)]+$//; }
1479         $todir = $self->fixpath($todir,1);
1480         push @m, "
1481 $to : $from \$(MAKEFILE) ${todir}.exists
1482         \$(CP) $from $to
1483
1484 ", $self->dir_target($todir);
1485     }
1486     join "", @m;
1487 }
1488
1489 =item subdir_x (override)
1490
1491 Use VMS commands to change default directory.
1492
1493 =cut
1494
1495 sub subdir_x {
1496     my($self, $subdir) = @_;
1497     my(@m,$key);
1498     $subdir = $self->fixpath($subdir,1);
1499     push @m, '
1500
1501 subdirs ::
1502         olddef = F$Environment("Default")
1503         Set Default ',$subdir,'
1504         - $(MMS)$(MMSQUALIFIERS) all $(USEMACROS)$(PASTHRU)$(MACROEND)
1505         Set Default \'olddef\'
1506 ';
1507     join('',@m);
1508 }
1509
1510 =item clean (override)
1511
1512 Split potentially long list of files across multiple commands (in
1513 order to stay under the magic command line limit).  Also use MM[SK]
1514 commands for handling subdirectories.
1515
1516 =cut
1517
1518 sub clean {
1519     my($self, %attribs) = @_;
1520     my(@m,$dir);
1521     push @m, '
1522 # Delete temporary files but do not touch installed files. We don\'t delete
1523 # the Descrip.MMS here so that a later make realclean still has it to use.
1524 clean ::
1525 ';
1526     foreach $dir (@{$self->{DIR}}) { # clean subdirectories first
1527         my($vmsdir) = $self->fixpath($dir,1);
1528         push( @m, '     If F$Search("'.$vmsdir.'$(MAKEFILE)").nes."" Then \\',"\n\t",
1529               '$(PERL) -e "chdir ',"'$vmsdir'",'; print `$(MMS)$(MMSQUALIFIERS) clean`;"',"\n");
1530     }
1531     push @m, '  $(RM_F) *.Map *.Dmp *.Lis *.cpp *.$(DLEXT) *$(OBJ_EXT) *$(LIB_EXT) *.Opt $(BOOTSTRAP) $(BASEEXT).bso .MM_Tmp
1532 ';
1533
1534     my(@otherfiles) = values %{$self->{XS}}; # .c files from *.xs files
1535     # Unlink realclean, $attribs{FILES} is a string here; it may contain
1536     # a list or a macro that expands to a list.
1537     if ($attribs{FILES}) {
1538         my($word,$key,@filist);
1539         if (ref $attribs{FILES} eq 'ARRAY') { @filist = @{$attribs{FILES}}; }
1540         else { @filist = split /\s+/, $attribs{FILES}; }
1541         foreach $word (@filist) {
1542             if (($key) = $word =~ m#^\$\((.*)\)$# and ref $self->{$key} eq 'ARRAY') {
1543                 push(@otherfiles, @{$self->{$key}});
1544             }
1545             else { push(@otherfiles, $word); }
1546         }
1547     }
1548     push(@otherfiles, qw[ blib $(MAKE_APERL_FILE) extralibs.ld perlmain.c pm_to_blib.ts ]);
1549     push(@otherfiles,File::Spec->catfile('$(INST_ARCHAUTODIR)','extralibs.all'));
1550     my($file,$line);
1551     $line = '';  #avoid unitialized var warning
1552     # Occasionally files are repeated several times from different sources
1553     { my(%of) = map { ($_,1) } @otherfiles; @otherfiles = keys %of; }
1554     
1555     foreach $file (@otherfiles) {
1556         $file = $self->fixpath($file);
1557         if (length($line) + length($file) > 80) {
1558             push @m, "\t\$(RM_RF) $line\n";
1559             $line = "$file";
1560         }
1561         else { $line .= " $file"; }
1562     }
1563     push @m, "\t\$(RM_RF) $line\n" if $line;
1564     push(@m, "  $attribs{POSTOP}\n") if $attribs{POSTOP};
1565     join('', @m);
1566 }
1567
1568 =item realclean (override)
1569
1570 Guess what we're working around?  Also, use MM[SK] for subdirectories.
1571
1572 =cut
1573
1574 sub realclean {
1575     my($self, %attribs) = @_;
1576     my(@m);
1577     push(@m,'
1578 # Delete temporary files (via clean) and also delete installed files
1579 realclean :: clean
1580 ');
1581     foreach(@{$self->{DIR}}){
1582         my($vmsdir) = $self->fixpath($_,1);
1583         push(@m, '      If F$Search("'."$vmsdir".'$(MAKEFILE)").nes."" Then \\',"\n\t",
1584               '$(PERL) -e "chdir ',"'$vmsdir'",'; print `$(MMS)$(MMSQUALIFIERS) realclean`;"',"\n");
1585     }
1586     push @m,'   $(RM_RF) $(INST_AUTODIR) $(INST_ARCHAUTODIR)
1587 ';
1588     # We can't expand several of the MMS macros here, since they don't have
1589     # corresponding %$self keys (i.e. they're defined in Descrip.MMS as a
1590     # combination of macros).  In order to stay below DCL's 255 char limit,
1591     # we put only 2 on a line.
1592     my($file,$line,$fcnt);
1593     my(@files) = qw{ $(MAKEFILE) $(MAKEFILE)_old };
1594     if ($self->has_link_code) {
1595         push(@files,qw{ $(INST_DYNAMIC) $(INST_STATIC) $(INST_BOOT) $(OBJECT) });
1596     }
1597     push(@files, values %{$self->{PM}});
1598     $line = '';  #avoid unitialized var warning
1599     # Occasionally files are repeated several times from different sources
1600     { my(%f) = map { ($_,1) } @files; @files = keys %f; }
1601     foreach $file (@files) {
1602         $file = $self->fixpath($file);
1603         if (length($line) + length($file) > 80 || ++$fcnt >= 2) {
1604             push @m, "\t\$(RM_F) $line\n";
1605             $line = "$file";
1606             $fcnt = 0;
1607         }
1608         else { $line .= " $file"; }
1609     }
1610     push @m, "\t\$(RM_F) $line\n" if $line;
1611     if ($attribs{FILES}) {
1612         my($word,$key,@filist,@allfiles);
1613         if (ref $attribs{FILES} eq 'ARRAY') { @filist = @{$attribs{FILES}}; }
1614         else { @filist = split /\s+/, $attribs{FILES}; }
1615         foreach $word (@filist) {
1616             if (($key) = $word =~ m#^\$\((.*)\)$# and ref $self->{$key} eq 'ARRAY') {
1617                 push(@allfiles, @{$self->{$key}});
1618             }
1619             else { push(@allfiles, $word); }
1620         }
1621         $line = '';
1622         # Occasionally files are repeated several times from different sources
1623         { my(%af) = map { ($_,1) } @allfiles; @allfiles = keys %af; }
1624         foreach $file (@allfiles) {
1625             $file = $self->fixpath($file);
1626             if (length($line) + length($file) > 80) {
1627                 push @m, "\t\$(RM_RF) $line\n";
1628                 $line = "$file";
1629             }
1630             else { $line .= " $file"; }
1631         }
1632         push @m, "\t\$(RM_RF) $line\n" if $line;
1633     }
1634     push(@m, "  $attribs{POSTOP}\n")                     if $attribs{POSTOP};
1635     join('', @m);
1636 }
1637
1638 =item dist_basics (override)
1639
1640 Use VMS-style quoting on command line.
1641
1642 =cut
1643
1644 sub dist_basics {
1645     my($self) = @_;
1646 '
1647 distclean :: realclean distcheck
1648         $(NOECHO) $(NOOP)
1649
1650 distcheck :
1651         $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e "use ExtUtils::Manifest \'&fullcheck\'; fullcheck()"
1652
1653 skipcheck :
1654         $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e "use ExtUtils::Manifest \'&skipcheck\'; skipcheck()"
1655
1656 manifest :
1657         $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e "use ExtUtils::Manifest \'&mkmanifest\'; mkmanifest()"
1658 ';
1659 }
1660
1661 =item dist_core (override)
1662
1663 Syntax for invoking F<VMS_Share> differs from that for Unix F<shar>,
1664 so C<shdist> target actions are VMS-specific.
1665
1666 =cut
1667
1668 sub dist_core {
1669     my($self) = @_;
1670 q[
1671 dist : $(DIST_DEFAULT)
1672         $(NOECHO) $(PERL) -le "print 'Warning: $m older than $vf' if -e ($vf = '$(VERSION_FROM)') && -M $vf < -M ($m = '$(MAKEFILE)')"
1673
1674 zipdist : $(DISTVNAME).zip
1675         $(NOECHO) $(NOOP)
1676
1677 tardist : $(DISTVNAME).tar$(SUFFIX)
1678         $(NOECHO) $(NOOP)
1679
1680 $(DISTVNAME).zip : distdir
1681         $(PREOP)
1682         $(ZIP) "$(ZIPFLAGS)" $(MMS$TARGET) [.$(DISTVNAME)...]*.*;
1683         $(RM_RF) $(DISTVNAME)
1684         $(POSTOP)
1685
1686 $(DISTVNAME).tar$(SUFFIX) : distdir
1687         $(PREOP)
1688         $(TO_UNIX)
1689         $(TAR) "$(TARFLAGS)" $(DISTVNAME).tar [.$(DISTVNAME)...]
1690         $(RM_RF) $(DISTVNAME)
1691         $(COMPRESS) $(DISTVNAME).tar
1692         $(POSTOP)
1693
1694 shdist : distdir
1695         $(PREOP)
1696         $(SHAR) [.$(DISTVNAME...]*.*; $(DISTVNAME).share
1697         $(RM_RF) $(DISTVNAME)
1698         $(POSTOP)
1699 ];
1700 }
1701
1702 =item dist_dir (override)
1703
1704 Use VMS-style quoting on command line.
1705
1706 =cut
1707
1708 sub dist_dir {
1709     my($self) = @_;
1710 q{
1711 distdir :
1712         $(RM_RF) $(DISTVNAME)
1713         $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e "use ExtUtils::Manifest '/mani/';" \\
1714         -e "manicopy(maniread(),'$(DISTVNAME)','$(DIST_CP)');"
1715 };
1716 }
1717
1718 =item dist_test (override)
1719
1720 Use VMS commands to change default directory, and use VMS-style
1721 quoting on command line.
1722
1723 =cut
1724
1725 sub dist_test {
1726     my($self) = @_;
1727 q{
1728 disttest : distdir
1729         startdir = F$Environment("Default")
1730         Set Default [.$(DISTVNAME)]
1731         $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" Makefile.PL
1732         $(MMS)$(MMSQUALIFIERS)
1733         $(MMS)$(MMSQUALIFIERS) test
1734         Set Default 'startdir'
1735 };
1736 }
1737
1738 # --- Test and Installation Sections ---
1739
1740 =item install (override)
1741
1742 Work around DCL's 255 character limit several times,and use
1743 VMS-style command line quoting in a few cases.
1744
1745 =cut
1746
1747 sub install {
1748     my($self, %attribs) = @_;
1749     my(@m,@docfiles);
1750
1751     if ($self->{EXE_FILES}) {
1752         my($line,$file) = ('','');
1753         foreach $file (@{$self->{EXE_FILES}}) {
1754             $line .= "$file ";
1755             if (length($line) > 128) {
1756                 push(@docfiles,qq[\t\$(PERL) -e "print '$line'" >>.MM_tmp\n]);
1757                 $line = '';
1758             }
1759         }
1760         push(@docfiles,qq[\t\$(PERL) -e "print '$line'" >>.MM_tmp\n]) if $line;
1761     }
1762
1763     push @m, q[
1764 install :: all pure_install doc_install
1765         $(NOECHO) $(NOOP)
1766
1767 install_perl :: all pure_perl_install doc_perl_install
1768         $(NOECHO) $(NOOP)
1769
1770 install_site :: all pure_site_install doc_site_install
1771         $(NOECHO) $(NOOP)
1772
1773 install_ :: install_site
1774         $(NOECHO) $(SAY) "INSTALLDIRS not defined, defaulting to INSTALLDIRS=site"
1775
1776 pure_install :: pure_$(INSTALLDIRS)_install
1777         $(NOECHO) $(NOOP)
1778
1779 doc_install :: doc_$(INSTALLDIRS)_install
1780         $(NOECHO) $(SAY) "Appending installation info to $(INSTALLARCHLIB)perllocal.pod"
1781
1782 pure__install : pure_site_install
1783         $(NOECHO) $(SAY) "INSTALLDIRS not defined, defaulting to INSTALLDIRS=site"
1784
1785 doc__install : doc_site_install
1786         $(NOECHO) $(SAY) "INSTALLDIRS not defined, defaulting to INSTALLDIRS=site"
1787
1788 # This hack brought to you by DCL's 255-character command line limit
1789 pure_perl_install ::
1790         $(NOECHO) $(PERL) -e "print 'read ].File::Spec->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').q[ '" >.MM_tmp
1791         $(NOECHO) $(PERL) -e "print 'write ].File::Spec->catfile('$(INSTALLARCHLIB)','auto','$(FULLEXT)','.packlist').q[ '" >>.MM_tmp
1792         $(NOECHO) $(PERL) -e "print '$(INST_LIB) $(INSTALLPRIVLIB) '" >>.MM_tmp
1793         $(NOECHO) $(PERL) -e "print '$(INST_ARCHLIB) $(INSTALLARCHLIB) '" >>.MM_tmp
1794         $(NOECHO) $(PERL) -e "print '$(INST_BIN) $(INSTALLBIN) '" >>.MM_tmp
1795         $(NOECHO) $(PERL) -e "print '$(INST_SCRIPT) $(INSTALLSCRIPT) '" >>.MM_tmp
1796         $(NOECHO) $(PERL) -e "print '$(INST_MAN1DIR) $(INSTALLMAN1DIR) '" >>.MM_tmp
1797         $(NOECHO) $(PERL) -e "print '$(INST_MAN3DIR) $(INSTALLMAN3DIR) '" >>.MM_tmp
1798         $(MOD_INSTALL) <.MM_tmp
1799         $(NOECHO) Delete/NoLog/NoConfirm .MM_tmp;
1800         $(NOECHO) $(WARN_IF_OLD_PACKLIST) ].File::Spec->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist').q[
1801
1802 # Likewise
1803 pure_site_install ::
1804         $(NOECHO) $(PERL) -e "print 'read ].File::Spec->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist').q[ '" >.MM_tmp
1805         $(NOECHO) $(PERL) -e "print 'write ].File::Spec->catfile('$(INSTALLSITEARCH)','auto','$(FULLEXT)','.packlist').q[ '" >>.MM_tmp
1806         $(NOECHO) $(PERL) -e "print '$(INST_LIB) $(INSTALLSITELIB) '" >>.MM_tmp
1807         $(NOECHO) $(PERL) -e "print '$(INST_ARCHLIB) $(INSTALLSITEARCH) '" >>.MM_tmp
1808         $(NOECHO) $(PERL) -e "print '$(INST_BIN) $(INSTALLBIN) '" >>.MM_tmp
1809         $(NOECHO) $(PERL) -e "print '$(INST_SCRIPT) $(INSTALLSCRIPT) '" >>.MM_tmp
1810         $(NOECHO) $(PERL) -e "print '$(INST_MAN1DIR) $(INSTALLMAN1DIR) '" >>.MM_tmp
1811         $(NOECHO) $(PERL) -e "print '$(INST_MAN3DIR) $(INSTALLMAN3DIR) '" >>.MM_tmp
1812         $(MOD_INSTALL) <.MM_tmp
1813         $(NOECHO) Delete/NoLog/NoConfirm .MM_tmp;
1814         $(NOECHO) $(WARN_IF_OLD_PACKLIST) ].File::Spec->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').q[
1815
1816 # Ditto
1817 doc_perl_install ::
1818         $(NOECHO) $(PERL) -e "print 'Module $(NAME)|installed into|$(INSTALLPRIVLIB)|'" >.MM_tmp
1819         $(NOECHO) $(PERL) -e "print 'LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES)|'" >>.MM_tmp
1820 ],@docfiles,
1821 q%      $(NOECHO) $(PERL) -e "print q[@ARGV=split(/\\|/,<STDIN>);]" >.MM2_tmp
1822         $(NOECHO) $(PERL) -e "print q[print '=head2 ',scalar(localtime),': C<',shift,qq[>\\n\\n=over 4\\n\\n];]" >>.MM2_tmp
1823         $(NOECHO) $(PERL) -e "print q[while(($key=shift) && ($val=shift)) ]" >>.MM2_tmp
1824         $(NOECHO) $(PERL) -e "print q[{print qq[=item *\\n\\nC<$key: $val>\\n\\n];}print qq[=back\\n\\n];]" >>.MM2_tmp
1825         $(NOECHO) $(PERL) .MM2_tmp <.MM_tmp >>%.File::Spec->catfile('$(INSTALLARCHLIB)','perllocal.pod').q[
1826         $(NOECHO) Delete/NoLog/NoConfirm .MM_tmp;,.MM2_tmp;
1827
1828 # And again
1829 doc_site_install ::
1830         $(NOECHO) $(PERL) -e "print 'Module $(NAME)|installed into|$(INSTALLSITELIB)|'" >.MM_tmp
1831         $(NOECHO) $(PERL) -e "print 'LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES)|'" >>.MM_tmp
1832 ],@docfiles,
1833 q%      $(NOECHO) $(PERL) -e "print q[@ARGV=split(/\\|/,<STDIN>);]" >.MM2_tmp
1834         $(NOECHO) $(PERL) -e "print q[print '=head2 ',scalar(localtime),': C<',shift,qq[>\\n\\n=over 4\\n\\n];]" >>.MM2_tmp
1835         $(NOECHO) $(PERL) -e "print q[while(($key=shift) && ($val=shift)) ]" >>.MM2_tmp
1836         $(NOECHO) $(PERL) -e "print q[{print qq[=item *\\n\\nC<$key: $val>\\n\\n];}print qq[=back\\n\\n];]" >>.MM2_tmp
1837         $(NOECHO) $(PERL) .MM2_tmp <.MM_tmp >>%.File::Spec->catfile('$(INSTALLARCHLIB)','perllocal.pod').q[
1838         $(NOECHO) Delete/NoLog/NoConfirm .MM_tmp;,.MM2_tmp;
1839
1840 ];
1841
1842     push @m, q[
1843 uninstall :: uninstall_from_$(INSTALLDIRS)dirs
1844         $(NOECHO) $(NOOP)
1845
1846 uninstall_from_perldirs ::
1847         $(NOECHO) $(UNINSTALL) ].File::Spec->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').q[
1848         $(NOECHO) $(SAY) "Uninstall is now deprecated and makes no actual changes."
1849         $(NOECHO) $(SAY) "Please check the list above carefully for errors, and manually remove"
1850         $(NOECHO) $(SAY) "the appropriate files.  Sorry for the inconvenience."
1851
1852 uninstall_from_sitedirs ::
1853         $(NOECHO) $(UNINSTALL) ],File::Spec->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist'),"\n",q[
1854         $(NOECHO) $(SAY) "Uninstall is now deprecated and makes no actual changes."
1855         $(NOECHO) $(SAY) "Please check the list above carefully for errors, and manually remove"
1856         $(NOECHO) $(SAY) "the appropriate files.  Sorry for the inconvenience."
1857 ];
1858
1859     join('',@m);
1860 }
1861
1862 =item perldepend (override)
1863
1864 Use VMS-style syntax for files; it's cheaper to just do it directly here
1865 than to have the MM_Unix method call C<catfile> repeatedly.  Also, if
1866 we have to rebuild Config.pm, use MM[SK] to do it.
1867
1868 =cut
1869
1870 sub perldepend {
1871     my($self) = @_;
1872     my(@m);
1873
1874     push @m, '
1875 $(OBJECT) : $(PERL_INC)EXTERN.h, $(PERL_INC)INTERN.h, $(PERL_INC)XSUB.h
1876 $(OBJECT) : $(PERL_INC)av.h, $(PERL_INC)cc_runtime.h, $(PERL_INC)config.h
1877 $(OBJECT) : $(PERL_INC)cop.h, $(PERL_INC)cv.h, $(PERL_INC)embed.h
1878 $(OBJECT) : $(PERL_INC)embedvar.h, $(PERL_INC)fakethr.h, $(PERL_INC)form.h
1879 $(OBJECT) : $(PERL_INC)gv.h, $(PERL_INC)handy.h, $(PERL_INC)hv.h
1880 $(OBJECT) : $(PERL_INC)intrpvar.h, $(PERL_INC)iperlsys.h, $(PERL_INC)keywords.h
1881 $(OBJECT) : $(PERL_INC)mg.h, $(PERL_INC)nostdio.h, $(PERL_INC)op.h
1882 $(OBJECT) : $(PERL_INC)opcode.h, $(PERL_INC)opnames.h, $(PERL_INC)patchlevel.h
1883 $(OBJECT) : $(PERL_INC)perl.h, $(PERL_INC)perlapi.h, $(PERL_INC)perlio.h
1884 $(OBJECT) : $(PERL_INC)perlsdio.h, $(PERL_INC)perlsfio.h, $(PERL_INC)perlvars.h
1885 $(OBJECT) : $(PERL_INC)perly.h, $(PERL_INC)pp.h, $(PERL_INC)pp_proto.h
1886 $(OBJECT) : $(PERL_INC)proto.h, $(PERL_INC)regcomp.h, $(PERL_INC)regexp.h
1887 $(OBJECT) : $(PERL_INC)regnodes.h, $(PERL_INC)scope.h, $(PERL_INC)sv.h
1888 $(OBJECT) : $(PERL_INC)thrdvar.h, $(PERL_INC)thread.h, $(PERL_INC)utf8.h
1889 $(OBJECT) : $(PERL_INC)util.h, $(PERL_INC)vmsish.h, $(PERL_INC)warnings.h
1890
1891 ' if $self->{OBJECT}; 
1892
1893     if ($self->{PERL_SRC}) {
1894         my(@macros);
1895         my($mmsquals) = '$(USEMAKEFILE)[.vms]$(MAKEFILE)';
1896         push(@macros,'__AXP__=1') if $Config{'arch'} eq 'VMS_AXP';
1897         push(@macros,'DECC=1')    if $Config{'vms_cc_type'} eq 'decc';
1898         push(@macros,'GNUC=1')    if $Config{'vms_cc_type'} eq 'gcc';
1899         push(@macros,'SOCKET=1')  if $Config{'d_has_sockets'};
1900         push(@macros,qq["CC=$Config{'cc'}"])  if $Config{'cc'} =~ m!/!;
1901         $mmsquals .= '$(USEMACROS)' . join(',',@macros) . '$(MACROEND)' if @macros;
1902         push(@m,q[
1903 # Check for unpropagated config.sh changes. Should never happen.
1904 # We do NOT just update config.h because that is not sufficient.
1905 # An out of date config.h is not fatal but complains loudly!
1906 $(PERL_INC)config.h : $(PERL_SRC)config.sh
1907         $(NOOP)
1908
1909 $(PERL_ARCHLIB)Config.pm : $(PERL_SRC)config.sh
1910         $(NOECHO) Write Sys$Error "$(PERL_ARCHLIB)Config.pm may be out of date with config.h or genconfig.pl"
1911         olddef = F$Environment("Default")
1912         Set Default $(PERL_SRC)
1913         $(MMS)],$mmsquals,);
1914         if ($self->{PERL_ARCHLIB} =~ m|\[-| && $self->{PERL_SRC} =~ m|(\[-+)|) {
1915             my($prefix,$target) = ($1,$self->fixpath('$(PERL_ARCHLIB)Config.pm',0));
1916             $target =~ s/\Q$prefix/[/;
1917             push(@m," $target");
1918         }
1919         else { push(@m,' $(MMS$TARGET)'); }
1920         push(@m,q[
1921         Set Default 'olddef'
1922 ]);
1923     }
1924
1925     push(@m, join(" ", map($self->fixpath($_,0),values %{$self->{XS}}))." : \$(XSUBPPDEPS)\n")
1926       if %{$self->{XS}};
1927
1928     join('',@m);
1929 }
1930
1931 =item makefile (override)
1932
1933 Use VMS commands and quoting.
1934
1935 =cut
1936
1937 sub makefile {
1938     my($self) = @_;
1939     my(@m,@cmd);
1940     # We do not know what target was originally specified so we
1941     # must force a manual rerun to be sure. But as it should only
1942     # happen very rarely it is not a significant problem.
1943     push @m, q[
1944 $(OBJECT) : $(FIRST_MAKEFILE)
1945 ] if $self->{OBJECT};
1946
1947     push @m,q[
1948 # We take a very conservative approach here, but it\'s worth it.
1949 # We move $(MAKEFILE) to $(MAKEFILE)_old here to avoid gnu make looping.
1950 $(MAKEFILE) : Makefile.PL $(CONFIGDEP)
1951         $(NOECHO) $(SAY) "$(MAKEFILE) out-of-date with respect to $(MMS$SOURCE_LIST)"
1952         $(NOECHO) $(SAY) "Cleaning current config before rebuilding $(MAKEFILE) ..."
1953         - $(MV) $(MAKEFILE) $(MAKEFILE)_old
1954         - $(MMS)$(MMSQUALIFIERS) $(USEMAKEFILE)$(MAKEFILE)_old clean
1955         $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" Makefile.PL ],join(' ',map(qq["$_"],@ARGV)),q[
1956         $(NOECHO) $(SAY) "$(MAKEFILE) has been rebuilt."
1957         $(NOECHO) $(SAY) "Please run $(MMS) to build the extension."
1958 ];
1959
1960     join('',@m);
1961 }
1962
1963 =item test (override)
1964
1965 Use VMS commands for handling subdirectories.
1966
1967 =cut
1968
1969 sub test {
1970     my($self, %attribs) = @_;
1971     my($tests) = $attribs{TESTS} || ( -d 't' ? 't/*.t' : '');
1972     my(@m);
1973     push @m,"
1974 TEST_VERBOSE = 0
1975 TEST_TYPE = test_\$(LINKTYPE)
1976 TEST_FILE = test.pl
1977 TESTDB_SW = -d
1978
1979 test :: \$(TEST_TYPE)
1980         \$(NOECHO) \$(NOOP)
1981
1982 testdb :: testdb_\$(LINKTYPE)
1983         \$(NOECHO) \$(NOOP)
1984
1985 ";
1986     foreach(@{$self->{DIR}}){
1987       my($vmsdir) = $self->fixpath($_,1);
1988       push(@m, '        If F$Search("',$vmsdir,'$(MAKEFILE)").nes."" Then $(PERL) -e "chdir ',"'$vmsdir'",
1989            '; print `$(MMS)$(MMSQUALIFIERS) $(PASTHRU2) test`'."\n");
1990     }
1991     push(@m, "\t\$(NOECHO) \$(SAY) \"No tests defined for \$(NAME) extension.\"\n")
1992         unless $tests or -f "test.pl" or @{$self->{DIR}};
1993     push(@m, "\n");
1994
1995     push(@m, "test_dynamic :: pure_all\n");
1996     push(@m, $self->test_via_harness('$(FULLPERL)', $tests)) if $tests;
1997     push(@m, $self->test_via_script('$(FULLPERL)', 'test.pl')) if -f "test.pl";
1998     push(@m, "\t\$(NOECHO) \$(NOOP)\n") if (!$tests && ! -f "test.pl");
1999     push(@m, "\n");
2000
2001     push(@m, "testdb_dynamic :: pure_all\n");
2002     push(@m, $self->test_via_script('$(FULLPERL) "$(TESTDB_SW)"', '$(TEST_FILE)'));
2003     push(@m, "\n");
2004
2005     # Occasionally we may face this degenerate target:
2006     push @m, "test_ : test_dynamic\n\n";
2007  
2008     if ($self->needs_linking()) {
2009         push(@m, "test_static :: pure_all \$(MAP_TARGET)\n");
2010         push(@m, $self->test_via_harness('$(MAP_TARGET)', $tests)) if $tests;
2011         push(@m, $self->test_via_script('$(MAP_TARGET)', 'test.pl')) if -f 'test.pl';
2012         push(@m, "\n");
2013         push(@m, "testdb_static :: pure_all \$(MAP_TARGET)\n");
2014         push(@m, $self->test_via_script('$(MAP_TARGET) $(TESTDB_SW)', '$(TEST_FILE)'));
2015         push(@m, "\n");
2016     }
2017     else {
2018         push @m, "test_static :: test_dynamic\n\t\$(NOECHO) \$(NOOP)\n\n";
2019         push @m, "testdb_static :: testdb_dynamic\n\t\$(NOECHO) \$(NOOP)\n";
2020     }
2021
2022     join('',@m);
2023 }
2024
2025 =item test_via_harness (override)
2026
2027 Use VMS-style quoting on command line.
2028
2029 =cut
2030
2031 sub test_via_harness {
2032     my($self,$perl,$tests) = @_;
2033     "   $perl".' "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" "-I$(PERL_LIB)" "-I$(PERL_ARCHLIB)" \\'."\n\t".
2034     '-e "use Test::Harness qw(&runtests $verbose); $verbose=$(TEST_VERBOSE); runtests @ARGV;" \\'."\n\t$tests\n";
2035 }
2036
2037 =item test_via_script (override)
2038
2039 Use VMS-style quoting on command line.
2040
2041 =cut
2042
2043 sub test_via_script {
2044     my($self,$perl,$script) = @_;
2045     "   $perl".' "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" '.$script.'
2046 ';
2047 }
2048
2049 =item makeaperl (override)
2050
2051 Undertake to build a new set of Perl images using VMS commands.  Since
2052 VMS does dynamic loading, it's not necessary to statically link each
2053 extension into the Perl image, so this isn't the normal build path.
2054 Consequently, it hasn't really been tested, and may well be incomplete.
2055
2056 =cut
2057
2058 our %olbs;
2059
2060 sub makeaperl {
2061     my($self, %attribs) = @_;
2062     my($makefilename, $searchdirs, $static, $extra, $perlinc, $target, $tmp, $libperl) = 
2063       @attribs{qw(MAKE DIRS STAT EXTRA INCL TARGET TMP LIBPERL)};
2064     my(@m);
2065     push @m, "
2066 # --- MakeMaker makeaperl section ---
2067 MAP_TARGET    = $target
2068 ";
2069     return join '', @m if $self->{PARENT};
2070
2071     my($dir) = join ":", @{$self->{DIR}};
2072
2073     unless ($self->{MAKEAPERL}) {
2074         push @m, q{
2075 $(MAKE_APERL_FILE) : $(FIRST_MAKEFILE)
2076         $(NOECHO) $(SAY) "Writing ""$(MMS$TARGET)"" for this $(MAP_TARGET)"
2077         $(NOECHO) $(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" \
2078                 Makefile.PL DIR=}, $dir, q{ \
2079                 MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \
2080                 MAKEAPERL=1 NORECURS=1 };
2081
2082         push @m, map(q[ \\\n\t\t"$_"], @ARGV),q{
2083
2084 $(MAP_TARGET) :: $(MAKE_APERL_FILE)
2085         $(MMS)$(MMSQUALIFIERS)$(USEMAKEFILE)$(MAKE_APERL_FILE) static $(MMS$TARGET)
2086 };
2087         push @m, "\n";
2088
2089         return join '', @m;
2090     }
2091
2092
2093     my($linkcmd,@optlibs,@staticpkgs,$extralist,$targdir,$libperldir,%libseen);
2094     local($_);
2095
2096     # The front matter of the linkcommand...
2097     $linkcmd = join ' ', $Config{'ld'},
2098             grep($_, @Config{qw(large split ldflags ccdlflags)});
2099     $linkcmd =~ s/\s+/ /g;
2100
2101     # Which *.olb files could we make use of...
2102     local(%olbs);       # XXX can this be lexical?
2103     $olbs{$self->{INST_ARCHAUTODIR}} = "$self->{BASEEXT}\$(LIB_EXT)";
2104     require File::Find;
2105     File::Find::find(sub {
2106         return unless m/\Q$self->{LIB_EXT}\E$/;
2107         return if m/^libperl/;
2108
2109         if( exists $self->{INCLUDE_EXT} ){
2110                 my $found = 0;
2111                 my $incl;
2112                 my $xx;
2113
2114                 ($xx = $File::Find::name) =~ s,.*?/auto/,,;
2115                 $xx =~ s,/?$_,,;
2116                 $xx =~ s,/,::,g;
2117
2118                 # Throw away anything not explicitly marked for inclusion.
2119                 # DynaLoader is implied.
2120                 foreach $incl ((@{$self->{INCLUDE_EXT}},'DynaLoader')){
2121                         if( $xx eq $incl ){
2122                                 $found++;
2123                                 last;
2124                         }
2125                 }
2126                 return unless $found;
2127         }
2128         elsif( exists $self->{EXCLUDE_EXT} ){
2129                 my $excl;
2130                 my $xx;
2131
2132                 ($xx = $File::Find::name) =~ s,.*?/auto/,,;
2133                 $xx =~ s,/?$_,,;
2134                 $xx =~ s,/,::,g;
2135
2136                 # Throw away anything explicitly marked for exclusion
2137                 foreach $excl (@{$self->{EXCLUDE_EXT}}){
2138                         return if( $xx eq $excl );
2139                 }
2140         }
2141
2142         $olbs{$ENV{DEFAULT}} = $_;
2143     }, grep( -d $_, @{$searchdirs || []}));
2144
2145     # We trust that what has been handed in as argument will be buildable
2146     $static = [] unless $static;
2147     @olbs{@{$static}} = (1) x @{$static};
2148  
2149     $extra = [] unless $extra && ref $extra eq 'ARRAY';
2150     # Sort the object libraries in inverse order of
2151     # filespec length to try to insure that dependent extensions
2152     # will appear before their parents, so the linker will
2153     # search the parent library to resolve references.
2154     # (e.g. Intuit::DWIM will precede Intuit, so unresolved
2155     # references from [.intuit.dwim]dwim.obj can be found
2156     # in [.intuit]intuit.olb).
2157     for (sort { length($a) <=> length($b) } keys %olbs) {
2158         next unless $olbs{$_} =~ /\Q$self->{LIB_EXT}\E$/;
2159         my($dir) = $self->fixpath($_,1);
2160         my($extralibs) = $dir . "extralibs.ld";
2161         my($extopt) = $dir . $olbs{$_};
2162         $extopt =~ s/$self->{LIB_EXT}$/.opt/;
2163         push @optlibs, "$dir$olbs{$_}";
2164         # Get external libraries this extension will need
2165         if (-f $extralibs ) {
2166             my %seenthis;
2167             open LIST,$extralibs or warn $!,next;
2168             while (<LIST>) {
2169                 chomp;
2170                 # Include a library in the link only once, unless it's mentioned
2171                 # multiple times within a single extension's options file, in which
2172                 # case we assume the builder needed to search it again later in the
2173                 # link.
2174                 my $skip = exists($libseen{$_}) && !exists($seenthis{$_});
2175                 $libseen{$_}++;  $seenthis{$_}++;
2176                 next if $skip;
2177                 push @$extra,$_;
2178             }
2179             close LIST;
2180         }
2181         # Get full name of extension for ExtUtils::Miniperl
2182         if (-f $extopt) {
2183             open OPT,$extopt or die $!;
2184             while (<OPT>) {
2185                 next unless /(?:UNIVERSAL|VECTOR)=boot_([\w_]+)/;
2186                 my $pkg = $1;
2187                 $pkg =~ s#__*#::#g;
2188                 push @staticpkgs,$pkg;
2189             }
2190         }
2191     }
2192     # Place all of the external libraries after all of the Perl extension
2193     # libraries in the final link, in order to maximize the opportunity
2194     # for XS code from multiple extensions to resolve symbols against the
2195     # same external library while only including that library once.
2196     push @optlibs, @$extra;
2197
2198     $target = "Perl$Config{'exe_ext'}" unless $target;
2199     my $shrtarget;
2200     ($shrtarget,$targdir) = fileparse($target);
2201     $shrtarget =~ s/^([^.]*)/$1Shr/;
2202     $shrtarget = $targdir . $shrtarget;
2203     $target = "Perlshr.$Config{'dlext'}" unless $target;
2204     $tmp = "[]" unless $tmp;
2205     $tmp = $self->fixpath($tmp,1);
2206     if (@optlibs) { $extralist = join(' ',@optlibs); }
2207     else          { $extralist = ''; }
2208     # Let ExtUtils::Liblist find the necessary libs for us (but skip PerlShr)
2209     # that's what we're building here).
2210     push @optlibs, grep { !/PerlShr/i } split ' ', +($self->ext())[2];
2211     if ($libperl) {
2212         unless (-f $libperl || -f ($libperl = File::Spec->catfile($Config{'installarchlib'},'CORE',$libperl))) {
2213             print STDOUT "Warning: $libperl not found\n";
2214             undef $libperl;
2215         }
2216     }
2217     unless ($libperl) {
2218         if (defined $self->{PERL_SRC}) {
2219             $libperl = File::Spec->catfile($self->{PERL_SRC},"libperl$self->{LIB_EXT}");
2220         } elsif (-f ($libperl = File::Spec->catfile($Config{'installarchlib'},'CORE',"libperl$self->{LIB_EXT}")) ) {
2221         } else {
2222             print STDOUT "Warning: $libperl not found
2223     If you're going to build a static perl binary, make sure perl is installed
2224     otherwise ignore this warning\n";
2225         }
2226     }
2227     $libperldir = $self->fixpath((fileparse($libperl))[1],1);
2228
2229     push @m, '
2230 # Fill in the target you want to produce if it\'s not perl
2231 MAP_TARGET    = ',$self->fixpath($target,0),'
2232 MAP_SHRTARGET = ',$self->fixpath($shrtarget,0),"
2233 MAP_LINKCMD   = $linkcmd
2234 MAP_PERLINC   = ", $perlinc ? map('"$_" ',@{$perlinc}) : '',"
2235 MAP_EXTRA     = $extralist
2236 MAP_LIBPERL = ",$self->fixpath($libperl,0),'
2237 ';
2238
2239
2240     push @m,"\n${tmp}Makeaperl.Opt : \$(MAP_EXTRA)\n";
2241     foreach (@optlibs) {
2242         push @m,'       $(NOECHO) $(PERL) -e "print q{',$_,'}" >>$(MMS$TARGET)',"\n";
2243     }
2244     push @m,"\n${tmp}PerlShr.Opt :\n\t";
2245     push @m,'$(NOECHO) $(PERL) -e "print q{$(MAP_SHRTARGET)}" >$(MMS$TARGET)',"\n";
2246
2247 push @m,'
2248 $(MAP_SHRTARGET) : $(MAP_LIBPERL) Makeaperl.Opt ',"${libperldir}Perlshr_Attr.Opt",'
2249         $(MAP_LINKCMD)/Shareable=$(MMS$TARGET) $(MAP_LIBPERL), Makeaperl.Opt/Option ',"${libperldir}Perlshr_Attr.Opt/Option",'
2250 $(MAP_TARGET) : $(MAP_SHRTARGET) ',"${tmp}perlmain\$(OBJ_EXT) ${tmp}PerlShr.Opt",'
2251         $(MAP_LINKCMD) ',"${tmp}perlmain\$(OBJ_EXT)",', PerlShr.Opt/Option
2252         $(NOECHO) $(SAY) "To install the new ""$(MAP_TARGET)"" binary, say"
2253         $(NOECHO) $(SAY) "    $(MMS)$(MMSQUALIFIERS)$(USEMAKEFILE)$(MAKEFILE) inst_perl $(USEMACROS)MAP_TARGET=$(MAP_TARGET)$(ENDMACRO)"
2254         $(NOECHO) $(SAY) "To remove the intermediate files, say
2255         $(NOECHO) $(SAY) "    $(MMS)$(MMSQUALIFIERS)$(USEMAKEFILE)$(MAKEFILE) map_clean"
2256 ';
2257     push @m,"\n${tmp}perlmain.c : \$(MAKEFILE)\n\t\$(NOECHO) \$(PERL) -e 1 >${tmp}Writemain.tmp\n";
2258     push @m, "# More from the 255-char line length limit\n";
2259     foreach (@staticpkgs) {
2260         push @m,'       $(NOECHO) $(PERL) -e "print q{',$_,qq[}" >>${tmp}Writemain.tmp\n];
2261     }
2262         push @m,'
2263         $(NOECHO) $(PERL) $(MAP_PERLINC) -ane "use ExtUtils::Miniperl; writemain(@F)" ',$tmp,'Writemain.tmp >$(MMS$TARGET)
2264         $(NOECHO) $(RM_F) ',"${tmp}Writemain.tmp\n";
2265
2266     push @m, q[
2267 # Still more from the 255-char line length limit
2268 doc_inst_perl :
2269         $(NOECHO) $(PERL) -e "print 'Perl binary $(MAP_TARGET)|'" >.MM_tmp
2270         $(NOECHO) $(PERL) -e "print 'MAP_STATIC|$(MAP_STATIC)|'" >>.MM_tmp
2271         $(NOECHO) $(PERL) -pl040 -e " " ].File::Spec->catfile('$(INST_ARCHAUTODIR)','extralibs.all'),q[ >>.MM_tmp
2272         $(NOECHO) $(PERL) -e "print 'MAP_LIBPERL|$(MAP_LIBPERL)|'" >>.MM_tmp
2273         $(DOC_INSTALL) <.MM_tmp >>].File::Spec->catfile('$(INSTALLARCHLIB)','perllocal.pod').q[
2274         $(NOECHO) Delete/NoLog/NoConfirm .MM_tmp;
2275 ];
2276
2277     push @m, "
2278 inst_perl : pure_inst_perl doc_inst_perl
2279         \$(NOECHO) \$(NOOP)
2280
2281 pure_inst_perl : \$(MAP_TARGET)
2282         $self->{CP} \$(MAP_SHRTARGET) ",$self->fixpath($Config{'installbin'},1),"
2283         $self->{CP} \$(MAP_TARGET) ",$self->fixpath($Config{'installbin'},1),"
2284
2285 clean :: map_clean
2286         \$(NOECHO) \$(NOOP)
2287
2288 map_clean :
2289         \$(RM_F) ${tmp}perlmain\$(OBJ_EXT) ${tmp}perlmain.c \$(MAKEFILE)
2290         \$(RM_F) ${tmp}Makeaperl.Opt ${tmp}PerlShr.Opt \$(MAP_TARGET)
2291 ";
2292
2293     join '', @m;
2294 }
2295   
2296 # --- Output postprocessing section ---
2297
2298 =item nicetext (override)
2299
2300 Insure that colons marking targets are preceded by space, in order
2301 to distinguish the target delimiter from a colon appearing as
2302 part of a filespec.
2303
2304 =cut
2305
2306 sub nicetext {
2307
2308     my($self,$text) = @_;
2309     $text =~ s/([^\s:])(:+\s)/$1 $2/gs;
2310     $text;
2311 }
2312
2313 1;
2314
2315 =back
2316
2317 =cut
2318
2319 __END__
2320