summaryrefslogtreecommitdiff
path: root/vms/ext/MM_VMS.pm
diff options
context:
space:
mode:
Diffstat (limited to 'vms/ext/MM_VMS.pm')
-rw-r--r--vms/ext/MM_VMS.pm812
1 files changed, 812 insertions, 0 deletions
diff --git a/vms/ext/MM_VMS.pm b/vms/ext/MM_VMS.pm
index 3ef0233d9a..f861d83021 100644
--- a/vms/ext/MM_VMS.pm
+++ b/vms/ext/MM_VMS.pm
@@ -11,6 +11,818 @@ package ExtUtils::MM_VMS;
use Config;
require Exporter;
+use VMS::Filespec;
+use File::Basename;
+
+Exporter::import('ExtUtils::MakeMaker',
+ qw(%att %skip %Recognized_Att_Keys $Verbose &neatvalue));
+
+
+sub fixpath {
+ my($path) = @_;
+ my($head,$macro,$tail);
+
+ while (($head,$macro,$tail) = ($path =~ m#(.*?)\$\((\S+?)\)/(.*)#)) {
+ ($macro = unixify($att{$macro})) =~ s#/$##;
+ $path = "$head$macro/$tail";
+ }
+ vmsify($path);
+}
+
+
+sub init_others {
+ &MM_Unix::init_others;
+ $att{NOOP} = "\tContinue";
+ $att{MAKEFILE} = '$(MAKEFILE)';
+ $att{RM_F} = '$(PERL) -e "foreach (@ARGV) { -d $_ ? rmdir $_ : unlink $_}"';
+ $att{RM_RF} = '$(PERL) -e "use File::Path; use VMS::Filespec; @dirs = map(unixify($_),@ARGV); rmtree(\@dirs,0,0)"';
+ $att{TOUCH} = '$(PERL) -e "$t=time; utime $t,$t,@ARGV"';
+ $att{CP} = 'Copy/NoConfirm';
+ $att{MV} = 'Rename/NoConfirm';
+}
+
+sub constants {
+ my(@m,$def);
+ push @m, "
+NAME = $att{NAME}
+DISTNAME = $att{DISTNAME}
+VERSION = $att{VERSION}
+
+# In which library should we install this extension?
+# This is typically the same as PERL_LIB.
+# (also see INST_LIBDIR and relationship to ROOTEXT)
+INST_LIB = ",vmspath($att{INST_LIB}),"
+INST_ARCHLIB = ",vmspath($att{INST_ARCHLIB}),"
+INST_EXE = ",vmspath($att{INST_EXE}),"
+
+# Perl library to use when building the extension
+PERL_LIB = ",vmspath($att{PERL_LIB}),"
+PERL_ARCHLIB = ",vmspath($att{PERL_ARCHLIB}),"
+LIBPERL_A = ",vmsify($att{LIBPERL_A}),"
+";
+
+# Define I_PERL_LIBS to include the required -Ipaths
+# To be cute we only include PERL_ARCHLIB if different
+# To be portable we add quotes for VMS
+my(@i_perl_libs) = qw{-I$(PERL_ARCHLIB) -I$(PERL_LIB)};
+shift(@i_perl_libs) if ($att{PERL_ARCHLIB} eq $att{PERL_LIB});
+push @m, "I_PERL_LIBS = \"".join('" "',@i_perl_libs)."\"\n";
+
+if ($att{PERL_SRC}) {
+ push @m, "
+# Where is the perl source code located?
+PERL_SRC = ",vmspath($att{PERL_SRC});
+}
+ push @m,"
+# Perl header files (will eventually be under PERL_LIB)
+PERL_INC = ",vmspath($att{PERL_INC}),"
+# Perl binaries
+PERL = $att{PERL}
+FULLPERL = $att{FULLPERL}
+
+# FULLEXT = Pathname for extension directory (eg DBD/Oracle).
+# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT.
+# ROOTEXT = Directory part of FULLEXT with leading slash (e.g /DBD)
+FULLEXT = ",vmsify($att{FULLEXT}),"
+BASEEXT = $att{BASEEXT}
+ROOTEXT = ",($att{ROOTEXT} eq '') ? '[]' : vmspath($att{ROOTEXT}),"
+
+INC = ";
+
+ if ($att{'INC'}) {
+ push @m,'/Include=(';
+ my(@includes) = split(/\s+/,$att{INC});
+ foreach (@includes) {
+ s/^-I//;
+ push @m,vmspath($_);
+ }
+ push @m, ")\n";
+ }
+
+ if ($att{DEFINE} ne '') {
+ my(@defs) = split(/\s+/,$att{DEFINE});
+ foreach $def (@defs) {
+ $def =~ s/^-D//;
+ $def = "\"$def\"" if $def =~ /=/;
+ }
+ $att{DEFINE} = join ',',@defs;
+ }
+
+ push @m,"
+DEFINE = $att{DEFINE}
+OBJECT = ",vmsify($att{OBJECT}),"
+LDFROM = ",vmsify($att{LDFROM}),"
+LINKTYPE = $att{LINKTYPE}
+
+# Handy lists of source code files:
+XS_FILES = ",join(', ', sort keys %{$att{XS}}),"
+C_FILES = ",join(', ', @{$att{C}}),"
+O_FILES = ",join(', ', @{$att{O_FILES}}),"
+H_FILES = ",join(', ', @{$att{H}}),"
+
+.SUFFIXES : .xs
+
+# This extension may link to it's own library (see SDBM_File)";
+ push @m,"
+MYEXTLIB = ",vmsify($att{MYEXTLIB}),"
+
+# Here is the Config.pm that we are using/depend on
+CONFIGDEP = \$(PERL_ARCHLIB)Config.pm, \$(PERL_INC)config.h
+
+# Where to put things:
+INST_LIBDIR = ",($att{'INST_LIBDIR'} = vmspath(unixpath($att{INST_LIB}) . unixpath($att{ROOTEXT}))),"
+INST_ARCHLIBDIR = ",($att{'INST_ARCHLIBDIR'} = vmspath(unixpath($att{INST_ARCHLIB}) . unixpath($att{ROOTEXT}))),"
+
+INST_AUTODIR = ",($att{'INST_AUTODIR'} = vmspath(unixpath($att{INST_LIB}) . 'auto/' . unixpath($att{FULLEXT}))),'
+INST_ARCHAUTODIR = ',($att{'INST_ARCHAUTODIR'} = vmspath(unixpath($att{INST_ARCHLIB}) . 'auto/' . unixpath($att{FULLEXT}))),'
+
+INST_STATIC = $(INST_ARCHAUTODIR)$(BASEEXT).olb
+INST_DYNAMIC = $(INST_ARCHAUTODIR)$(BASEEXT).$(DLEXT)
+INST_BOOT = $(INST_ARCHAUTODIR)$(BASEEXT).bs
+INST_PM = ',join(', ',map(fixpath($_),sort values %{$att{PM}})),'
+';
+
+ join('',@m);
+}
+
+
+sub const_cccmd {
+ my($cmd) = $Config{'cc'};
+ my($name,$sys,@m);
+
+ ( $name = $att{NAME} . "_cflags" ) =~ s/:/_/g ;
+ print STDOUT "Unix shell script ".$Config{"$att{'BASEEXT'}_cflags"}.
+ " required to modify CC command for $att{'BASEEXT'}\n"
+ if ($Config{$name});
+
+ # Deal with $att{DEFINE} here since some C compilers pay attention
+ # to only one /Define clause on command line, so we have to
+ # conflate the ones from $Config{'cc'} and $att{DEFINE}
+ if ($att{DEFINE} ne '') {
+ if ($cmd =~ m:/define=\(?([^\(\/\)]+)\)?:i) {
+ $cmd = $` . "/Define=(" . $1 . ",$att{DEFINE})" . $';
+ }
+ else { $cmd .= "/Define=($att{DEFINE})" }
+ }
+
+ $sys = ($cmd =~ /^gcc/i) ? 'GNU_CC_Include:[VMS]' : 'Sys$Library';
+ push @m,'
+.FIRST
+ @ If F$TrnLnm("Sys").eqs."" Then Define/NoLog SYS ',$sys,'
+
+';
+ push(@m, "CCCMD = $cmd\n");
+
+ join('',@m);
+}
+
+
+
+sub const_loadlibs{
+ my (@m);
+ push @m, "
+# $att{NAME} might depend on some other libraries.
+#
+# Dependent libraries are linked in either by the Link command
+# at build time or by the DynaLoader at bootstrap time.
+#
+# These comments may need revising:
+#
+# EXTRALIBS = Full list of libraries needed for static linking.
+# Only those libraries that actually exist are included.
+#
+# BSLOADLIBS = List of those libraries that are needed but can be
+# linked in dynamically.
+#
+# LDLOADLIBS = List of those libraries which must be statically
+# linked into the shared library.
+#
+EXTRALIBS = ",map(vmsify($_) . ' ',$att{'EXTRALIBS'}),"
+BSLOADLIBS = ",map(vmsify($_) . ' ',$att{'BSLOADLIBS'}),"
+LDLOADLIBS = ",map(vmsify($_) . ' ',$att{'LDLOADLIBS'}),"\n";
+
+ join('',@m);
+}
+
+# --- Tool Sections ---
+
+sub tool_autosplit{
+ my($self, %attribs) = @_;
+ my($asl) = "";
+ $asl = "\$AutoSplit::Maxlen=$attribs{MAXLEN};" if $attribs{MAXLEN};
+ q{
+# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto
+AUTOSPLITFILE = $(PERL) $(I_PERL_LIBS) -e "use AutoSplit;}.$asl.q{ AutoSplit::autosplit($ARGV[0], $ARGV[1], 0, 1, 1) ;"
+};
+}
+
+sub tool_xsubpp{
+ my($xsdir) = unixpath($att{PERL_LIB}).'ExtUtils';
+ # drop back to old location if xsubpp is not in new location yet
+ $xsdir = unixpath($att{PERL_SRC}).'ext' unless (-f "$xsdir/xsubpp");
+ my(@tmdeps) = '$(XSUBPPDIR)typemap';
+ push(@tmdeps, "typemap") if -f "typemap";
+ my(@tmargs) = map("-typemap $_", @tmdeps);
+ "
+XSUBPPDIR = ".vmspath($xsdir)."
+XSUBPP = \$(PERL) \$(XSUBPPDIR)xsubpp
+XSUBPPDEPS = @tmdeps
+XSUBPPARGS = @tmargs
+";
+}
+
+sub tools_other {
+ "
+# Assumes \$(MMS) invokes MMS or MMK
+USEMAKEFILE = /Descrip=
+USEMACROS = /Macro=(
+MACROEND = )
+MAKEFILE = Descrip.MMS
+SHELL = Posix
+LD = $att{LD}
+TOUCH = $att{TOUCH}
+CP = $att{CP}
+RM_F = $att{RM_F}
+RM_RF = $att{RM_RF}
+MKPATH = Create/Directory
+";
+}
+
+
+# --- Translation Sections ---
+
+sub c_o {
+ '
+.c.obj :
+ $(CCCMD) $(CCCDLFLAGS) /Include=($(PERL_INC)) $(INC) $(MMS$TARGET_NAME).c
+';
+}
+
+sub xs_c {
+ '
+.xs.c :
+ $(XSUBPP) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET)
+';
+}
+
+sub xs_o { # many makes are too dumb to use xs_c then c_o
+ '
+.xs.obj :
+ $(XSUBPP) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET_NAME).c
+ $(CCCMD) $(CCCDLFLAGS) /Include=($(PERL_INC)) $(INC) $(MMS$TARGET_NAME).c
+';
+}
+
+
+# --- Target Sections ---
+
+sub top_targets{
+ my(@m);
+ push @m, '
+all :: config linkext $(INST_PM)
+'.$att{NOOP}.'
+
+config :: '.$att{MAKEFILE}.'
+ @ $(MKPATH) $(INST_LIBDIR), $(INST_ARCHAUTODIR)
+';
+ push @m, '
+$(O_FILES) : $(H_FILES)
+' if @{$att{O_FILES} || []} && @{$att{H} || []};
+ join('',@m);
+}
+
+sub dlsyms {
+ my($self,%attribs) = @_;
+ my($funcs) = $attribs{DL_FUNCS} || $att{DL_FUNCS} || {};
+ my($vars) = $attribs{DL_VARS} || $att{DL_VARS} || [];
+ my(@m);
+
+ push(@m,'
+dynamic :: perlshr.opt $(BASEEXT).opt
+ ',$att{NOOP},'
+
+perlshr.opt : makefile.PL
+ $(PERL) -e "open O,\'>perlshr.opt\'; print O ""PerlShr/Share\n""; close O"
+') unless $skip{'dynamic'};
+
+ push(@m,'
+static :: $(BASEEXT).opt
+ ',$att{NOOP},'
+') unless $skip{'static'};
+
+ push(@m,'
+$(BASEEXT).opt : makefile.PL
+ $(PERL) $(I_PERL_LIBS) -e "use ExtUtils::MakeMaker; mksymlists(DL_FUNCS => ',neatvalue($att{DL_FUNCS}),', DL_VARS => ',neatvalue($att{DL_VARS}),',NAME => ',$att{NAME},')"
+ $(PERL) $(I_PERL_LIBS) -e "open OPT,\'>>$(MMS$TARGET)\'; print OPT ""$(INST_STATIC)/Include=$(BASEEXT)\n$(INST_STATIC)/Library\n"";close OPT"
+');
+
+ join('',@m);
+}
+
+
+# --- Dynamic Loading Sections ---
+
+sub dynamic_lib {
+ my($self, %attribs) = @_;
+ my($otherldflags) = $attribs{OTHERLDFLAGS} || "";
+ my(@m);
+ push @m,"
+
+OTHERLDFLAGS = $otherldflags
+
+";
+ push @m, '
+$(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt perlshr.opt $(BASEEXT).opt
+ @ $(MKPATH) $(INST_ARCHAUTODIR)
+ Link $(LDFLAGS) /Shareable=$(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,perlshr.opt/Option,$(PERL_INC)perlshr_attr.opt/Option
+';
+
+ join('',@m);
+}
+
+sub dynamic_bs {
+ my($self, %attribs) = @_;
+ '
+BOOTSTRAP = '."$att{BASEEXT}.bs".'
+
+# As MakeMaker mkbootstrap might not write a file (if none is required)
+# we use touch to prevent make continually trying to remake it.
+# The DynaLoader only reads a non-empty file.
+$(BOOTSTRAP): '."$att{MAKEFILE} $att{BOOTDEP}".'
+ @ Write Sys$Output "Running mkbootstrap for $(NAME) ($(BSLOADLIBS))"
+ @ $(PERL) $(I_PERL_LIBS) -e "use ExtUtils::MakeMaker; &mkbootstrap(""$(BSLOADLIBS)"");" "INST_LIB=$(INST_LIB)" "INST_ARCHLIB=$(INST_ARCHLIB)" "PERL_SRC=$(PERL_SRC)" "NAME=$(NAME)"
+ @ $(TOUCH) $(BOOTSTRAP)
+
+$(INST_BOOT): $(BOOTSTRAP)
+ @ '.$att{RM_RF}.' $(INST_BOOT)
+ - '.$att{CP}.' $(BOOTSTRAP) $(INST_BOOT)
+';
+}
+# --- Static Loading Sections ---
+
+sub static_lib {
+ '
+$(INST_STATIC) : $(OBJECT), $(MYEXTLIB)
+ @ $(MKPATH) $(INST_ARCHAUTODIR)
+ If F$Search("$(MMS$TARGET)").eqs."" Then Library/Object/Create $(MMS$TARGET)
+ Library/Object/Replace $(MMS$TARGET) $(MMS$SOURCE_LIST)
+';
+}
+
+
+sub installpm_x { # called by installpm perl file
+ my($self, $dist, $inst, $splitlib) = @_;
+ $inst = fixpath($inst);
+ $dist = vmsify($dist);
+ my($instdir) = dirname($inst);
+ my(@m);
+
+ push(@m, "
+$inst : $dist $att{MAKEFILE}
+",' @ ',$att{RM_F},' $(MMS$TARGET);*
+ @ $(MKPATH) ',$instdir,'
+ @ ',$att{CP},' $(MMS$SOURCE) $(MMS$TARGET)
+');
+ if ($splitlib and $inst =~ /\.pm$/) {
+ my($attdir) = $splitlib;
+ $attdir =~ s/\$\((.*)\)/$1/;
+ $attdir = $att{$attdir} if $att{$attdir};
+
+ push(@m, ' $(AUTOSPLITFILE) $(MMS$TARGET) ',
+ vmspath(unixpath($attdir) . 'auto')."\n");
+ push(@m,"\n");
+ }
+
+ join('',@m);
+}
+
+
+# --- Sub-directory Sections ---
+
+sub exescan {
+ vmsify($_);
+}
+
+sub subdir_x {
+ my($self, $subdir) = @_;
+ my(@m);
+ # The intention is that the calling Makefile.PL should define the
+ # $(SUBDIR_MAKEFILE_PL_ARGS) make macro to contain whatever
+ # information needs to be passed down to the other Makefile.PL scripts.
+ # If this does not suit your needs you'll need to write your own
+ # MY::subdir_x() method to override this one.
+ push @m, '
+config :: ',vmspath($subdir) . '$(MAKEFILE)
+ $(MMS) $(USEMAKEFILE) $(MMS$SOURCE) config $(USEMACROS)(INST_LIB=$(INST_LIB),INST_ARCHLIB=$(INST_ARCHLIB), \\
+ LINKTYPE=$(LINKTYPE),INST_EXE=$(INST_EXE),LIBPERL_A=$(LIBPERL_A)$(MACROEND) $(SUBDIR_MAKEFILE_PL_ARGS)
+
+',vmspath($subdir),'$(MAKEFILE) : ',vmspath($subdir),'Makefile.PL, $(CONFIGDEP)
+ @Write Sys$Output "Rebuilding $(MMS$TARGET) ..."
+ $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e "use ExtUtils::MakeMaker; MM->runsubdirpl(qw('.$subdir.'))" \\
+ $(SUBDIR_MAKEFILE_PL_ARGS) INST_LIB=$(INST_LIB) INST_ARCHLIB=$(INST_ARCHLIB) \\
+ INST_EXE=$(INST_EXE) LIBPERL_A=$(LIBPERL_A) LINKTYPE=$(LINKTYPE)
+ @Write Sys$Output "Rebuild of $(MMS$TARGET) complete."
+
+# The default clean, realclean and test targets in this Makefile
+# have automatically been given entries for $subdir.
+
+subdirs ::
+ Set Default ',vmspath($subdir),'
+ $(MMS) all $(USEMACROS)LINKTYPE=$(LINKTYPE)$(MACROEND)
+';
+ join('',@m);
+}
+
+
+# --- Cleanup and Distribution Sections ---
+
+sub clean {
+ my($self, %attribs) = @_;
+ my(@m);
+ push @m, '
+# Delete temporary files but do not touch installed files
+# We don\'t delete the Makefile here so that a
+# later make realclean still has a makefile to work from
+clean ::
+';
+ foreach (@{$att{DIR}}) { # clean subdirectories first
+ my($vmsdir) = vmspath($_);
+ push( @m, ' If F$Search("'.$vmsdir.'$(MAKEFILE)") Then $(MMS) $(USEMAKEFILE)'.$vmsdir.'$(MAKEFILE) clean'."\n");
+ }
+ push @m, "
+ $att{RM_F} *.Map;* *.lis;* *.cpp;* *.Obj;* *.Olb;* \$(BOOTSTRAP);* \$(BASEEXT).bso;*
+";
+
+ my(@otherfiles) = values %{$att{XS}}; # .c files from *.xs files
+ push(@otherfiles, $attribs{FILES}) if $attribs{FILES};
+ push(@otherfiles, "blib.dir");
+ push(@m, " $att{RM_F} ".join(";* ", map(fixpath($_),@otherfiles)),";*\n");
+ # See realclean and ext/utils/make_ext for usage of Makefile.old
+ push(@m, " $att{MV} $att{MAKEFILE} $att{MAKEFILE}_old");
+ push(@m, " $attribs{POSTOP}\n") if $attribs{POSTOP};
+ join('', @m);
+}
+
+
+sub realclean {
+ my($self, %attribs) = @_;
+ my(@m);
+ push(@m,'
+# Delete temporary files (via clean) and also delete installed files
+realclean :: clean
+');
+ foreach(@{$att{DIR}}){
+ my($vmsdir) = vmspath($_);
+ push(@m, ' If F$Search("'."$vmsdir$att{MAKEFILE}".'").nes."" Then $(MMS) $(USEMAKEFILE)'."$vmsdir$att{MAKEFILE}".' realclean'."\n");
+ push(@m, ' If F$Search("'."$vmsdir$att{MAKEFILE}".'_old").nes."" Then $(MMS) $(USEMAKEFILE)'."$vmsdir$att{MAKEFILE}".'_old realclean'."\n");
+ }
+ push @m,'
+ ',$att{RM_RF},' $(INST_AUTODIR) $(INST_ARCHAUTODIR)
+ ',$att{RM_F},' *.Opt;* $(INST_DYNAMIC);* $(INST_STATIC);* $(INST_BOOT);* $(INST_PM);*
+ ',$att{RM_F},' $(OBJECT);* $(MAKEFILE);* $(MAKEFILE)_old;*
+';
+ push(@m, " $att{RM_RF} ".join(";* ", map(fixpath($_),$attribs{'FILES'})),";*\n") if $attribs{'FILES'};
+ push(@m, " $attribs{POSTOP}\n") if $attribs{POSTOP};
+ join('', @m);
+}
+
+
+sub distclean {
+ my($self, %attribs) = @_;
+ my($preop) = $attribs{PREOP} || '@ !'; # e.g., update MANIFEST
+ my($zipname) = $attribs{TARNAME} || '$(DISTNAME)-$(VERSION)';
+ my($zipflags) = $attribs{ZIPFLAGS} || '-Vu';
+ my($postop) = $attribs{POSTOP} || "";
+ my($mkfiles) = join(' ', map("$_\$(MAKEFILE) $_\$(MAKEFILE)_old",map(vmspath($_),@{$att{'DIR'}})));
+
+ "
+distclean : clean
+ $preop
+ $att{RM_F} $mkfiles
+ Zip \"$zipflags\" $zipname \$(BASEEXT).* Makefile.PL
+ $postop
+";
+}
+
+
+# --- Test and Installation Sections ---
+
+sub test {
+ my($self, %attribs) = @_;
+ my($tests) = $attribs{TESTS} || ( -d 't' ? 't/*.t' : '');
+ my(@m);
+ push @m,'
+test : all
+';
+ push(@m,' $(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" $(I_PERL_LIBS) -e "use Test::Harness; runtests @ARGV;" '.$tests."\n")
+ if $tests;
+ push(@m,' $(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" $(I_PERL_LIBS) test.pl',"\n")
+ if -f 'test.pl';
+ foreach(@{$att{DIR}}){
+ my($vmsdir) = vmspath($_);
+ push(@m, ' If F$Search("',$vmsdir,'$(MAKEFILE)").nes."" Then $(PERL) -e "chdir \'',$vmsdir,
+ '\'; print `$(MMS) $(USEMAKEFILE)$(MAKEFILE) $(USEMACRO)LINKTYPE=$(LINKTYPE)$(MACROEND) test`'."\n");
+ }
+ push(@m, "\t\@echo 'No tests defined for \$(NAME) extension.'\n") unless @m > 1;
+
+ join('',@m);
+}
+
+sub install {
+ my($self, %attribs) = @_;
+ my(@m);
+ push @m, q{
+doc_install ::
+ @ $(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" $(I_PERL_LIBS) \\
+ -e "use ExtUtils::MakeMaker; MM->writedoc('Module', '$(NAME)', \\
+ 'LINKTYPE=$(LINKTYPE)', 'VERSION=$(VERSION)', 'EXE_FILES=$(EXE_FILES)')"
+};
+
+ push(@m, "
+install :: pure_install doc_install
+
+pure_install :: all
+");
+ # install subdirectories first
+ foreach(@{$att{DIR}}){
+ my($vmsdir) = vmspath($_);
+ push(@m, ' If F$Search("',$vmsdir,'$(MAKEFILE)").nes."" Then $(PERL) -e "chdir \'',$vmsdir,
+ '\'; print `$(MMS) $(USEMAKEFILE)$(MAKEFILE) install`'."\n");
+ }
+
+ push(@m, "\t! perl5.000 used to autosplit into INST_ARCHLIB, we delete these old files here
+ $att{RM_F} ",fixpath(unixpath($Config{'installarchlib'}).'auto/$(FULLEXT)/*.al'),';* ',
+ fixpath(unixpath($Config{'installarchlib'}).'auto/$(FULLEXT)/*.ix'),";*
+ \$(MMS) \$(USEMACROS)INST_LIB=$Config{'installprivlib'},INST_ARCHLIB=$Config{'installarchlib'},INST_EXE=$Config{'installbin'}\$(MACROEND)
+");
+
+ join("",@m);
+}
+
+sub perldepend {
+ my(@m);
+
+ push @m, '
+$(OBJECT) : $(PERL_INC)EXTERN.h, $(PERL_INC)INTERN.h, $(PERL_INC)XSUB.h, $(PERL_INC)av.h
+$(OBJECT) : $(PERL_INC)cop.h, $(PERL_INC)cv.h, $(PERL_INC)embed.h, $(PERL_INC)form.h
+$(OBJECT) : $(PERL_INC)gv.h, $(PERL_INC)handy.h, $(PERL_INC)hv.h, $(PERL_INC)keywords.h
+$(OBJECT) : $(PERL_INC)mg.h, $(PERL_INC)op.h, $(PERL_INC)opcode.h, $(PERL_INC)patchlevel.h
+$(OBJECT) : $(PERL_INC)perl.h, $(PERL_INC)perly.h, $(PERL_INC)pp.h, $(PERL_INC)proto.h
+$(OBJECT) : $(PERL_INC)regcomp.h, $(PERL_INC)regexp.h, $(PERL_INC)scope.h, $(PERL_INC)sv.h
+$(OBJECT) : $(PERL_INC)vmsish.h, $(PERL_INC)util.h, $(PERL_INC)config.h
+
+';
+ push(@m,'
+
+$(PERL_ARCHLIB)/Config.pm: $(PERL_SRC)/config.sh
+ @ Write Sys$Error "$(PERL_ARCHLIB)/Config.pm may be out of date with $(PERL_SRC)/config.sh"
+ Set Default $(PERL_SRC)
+ $(MMS) $(USEMAKEFILE)[.VMS]$(MAKEFILE) [.lib]config.pm
+');
+
+ push(@m, join(" ", map(vmsify($_),values %{$att{XS}}))." : \$(XSUBPPDEPS)\n")
+ if %{$att{XS}};
+
+ join('',@m);
+}
+
+sub makefile {
+ my(@m,@cmd);
+ push(@m,'
+
+# We take a very conservative approach here, but it\'s worth it.
+# We move $(MAKEFILE) to $(MAKEFILE)_old here to avoid gnu make looping.
+$(MAKEFILE) : Makefile.PL $(CONFIGDEP)
+ @ Write Sys$Output "',$att{MAKEFILE},' out-of-date with respect to $(MMS$SOURCE_LIST)"
+ @ Write Sys$Output "Cleaning current config before rebuilding ',$att{MAKEFILE},'...
+ - ',"$att{MV} $att{MAKEFILE} $att{MAKEFILE}_old",'
+ - $(MMS) $(USEMAKEFILE)',$att{MAKEFILE},'_old clean
+ $(PERL) $(I_PERL_LIBS) Makefile.PL
+ @ Write Sys$Output "Now you must rerun $(MMS)."
+');
+
+ join('',@m);
+}
+
+
+# --- Determine libraries to use and how to use them ---
+
+sub makeaperl {
+ my($self, %attribs) = @_;
+ my($makefilename, $searchdirs, $static, $extra, $perlinc, $target, $tmp, $libperl) =
+ @attribs{qw(MAKE DIRS STAT EXTRA INCL TARGET TMP LIBPERL)};
+ my(@m);
+ my($linkcmd,@staticopts,@staticpkgs,$extralist,$target,$targdir,$libperldir);
+
+ # The front matter of the linkcommand...
+ $linkcmd = join ' ', $Config{'ld'},
+ grep($_, @Config{qw(large split ldflags ccdlflags)});
+ $linkcmd =~ s/\s+/ /g;
+
+ # Which *.olb files could we make use of...
+ local(%olbs);
+ File::Find::find(sub {
+ return unless m/\.olb$/;
+ return if m/^libperl/;
+ $olbs{$ENV{DEFAULT}} = $_;
+ }, grep( -d $_, @{$searchdirs || []}), grep( -f $_, @{$static || []}) );
+
+ $extra = [] unless $extra && ref $extra eq 'ARRAY';
+ # Sort the object libraries in inverse order of
+ # filespec length to try to insure that dependent extensions
+ # will appear before their parents, so the linker will
+ # search the parent library to resolve references.
+ # (e.g. Intuit::DWIM will precede Intuit, so unresolved
+ # references from [.intuit.dwim]dwim.obj can be found
+ # in [.intuit]intuit.olb).
+ for (sort keys %olbs) {
+ next unless $olbs{$_} =~ /\.olb$/;
+ my($dir) = vmspath($_);
+ my($extralibs) = $dir . "extralibs.ld";
+ my($extopt) = $dir . $olbs{$_};
+ $extopt =~ s/\.olb$/.opt/;
+ if (-f $extralibs ) {
+ open LIST,$extralibs or warn $!,next;
+ push @$extra, <LIST>;
+ close LIST;
+ }
+ if (-f $extopt) {
+ open OPT,$extopt or die $!;
+ while (<OPT>) {
+ next unless /(?:UNIVERSAL|VECTOR)=boot_([\w_]+)/;
+ # ExtUtils::Miniperl expects Unix paths
+ (my($pkg) = "$2_$2.a") =~ s#_*#/#g;
+ push @staticpkgs,$pkg;
+ }
+ push @staticopts, $extopt;
+ }
+ }
+
+ $target = "Perl.Exe" unless $target;
+ ($shrtarget,$targdir) = fileparse($target);
+ $shrtarget =~ s/^([^.]*)/$1Shr/;
+ $shrtarget = $targdir . $shrtarget;
+ $target = "Perlshr$Config{'dlext'}" unless $target;
+ $tmp = "[]" unless $tmp;
+ $tmp = unixpath($tmp);
+ if (@$extra) {
+ $extralist = join(' ',@$extra);
+ $extralist =~ s/[,\s\n]+/, /g;
+ }
+ else { $extralist = ''; }
+ if ($libperl) {
+ unless (-f $libperl || -f ($libperl = unixpath($Config{'installarchlib'})."CORE/$libperl")){
+ print STDOUT "Warning: $libperl not found";
+ undef $libperl;
+ }
+ }
+ unless ($libperl) {
+ if (defined $att{PERL_SRC}) {
+ $libperl = "$att{PERL_SRC}/libperl.olb";
+ } elsif ( -f ( $libperl = unixpath($Config{'installarchlib'}).'CORE/libperl.olb' )) {
+ } else {
+ print STDOUT "Warning: $libperl not found";
+ }
+ }
+ $libperldir = vmspath((fileparse($libperl))[1]);
+
+ push @m, '
+# Fill in the target you want to produce if it\'s not perl
+MAP_TARGET = ',vmsify($target),'
+MAP_SHRTARGET = ',vmsify($shrtarget),"
+FULLPERL = $att{'FULLPERL'}
+MAP_LINKCMD = $linkcmd
+MAP_PERLINC = ", $perlinc ? map('"-I'.vmspath($_).'" ',@{$perlinc}) : '$(I_PERL_LIB)','
+# We use the linker options files created with each extension, rather than
+#specifying the object files directly on the command line.
+MAP_STATIC = ',@staticopts ? join(' ', @staticopts) : '','
+MAP_OPTS = ',@staticopts ? ','.join(',', map($_.'/Option', @staticopts)) : '',"
+MAP_EXTRA = $extralist
+MAP_LIBPERL = ",vmsify($libperl),'
+';
+
+
+ push @m,'
+$(MAP_SHRTARGET) : $(MAP_LIBPERL) $(MAP_STATIC) ',"${libperldir}Perlshr_Attr.Opt",'
+ $(MAP_LINKCMD)/Shareable=$(MMS$TARGET) $(MAP_OPTS), $(MAP_EXTRA), $(MAP_LIBPERL) ',"${libperldir}Perlshr_Attr.Opt",'
+$(MAP_TARGET) : $(MAP_SHRTARGET) ',vmsify("${tmp}perlmain.obj"),' ',vmsify("${tmp}PerlShr.Opt"),'
+ $(MAP_LINKCMD) ',vmsify("${tmp}perlmain.obj"),', PerlShr.Opt/Option
+ @ Write Sys$Output "To install the new ""$(MAP_TARGET)"" binary, say"
+ @ Write Sys$Output " $(MMS)$(USEMAKEFILE)$(MAKEFILE) inst_perl $(USEMACROS)MAP_TARGET=$(MAP_TARGET)$(ENDMACRO)"
+ @ Write Sys$Output "To remove the intermediate files, say
+ @ Write Sys$Output " $(MMS)$(USEMAKEFILE)$(MAKEFILE) map_clean"
+';
+ push @m,'
+',vmsify("${tmp}perlmain.c"),' : $(MAKEFILE)
+ @ $(PERL) $(MAP_PERLINC) -e "use ExtUtils::Miniperl; writemain(qw|',@staticpkgs,'|)" >$(MMS$TARGET)
+';
+
+ push @m, q{
+doc_inst_perl :
+ @ $(PERL) -e "use ExtUtils::MakeMaker; MM->writedoc('Perl binary','$(MAP_TARGET)','MAP_STATIC=$(MAP_STATIC)','MAP_EXTRA=$(MAP_EXTRA)','MAP_LIBPERL=$(MAP_LIBPERL)')"
+};
+
+ push @m, "
+inst_perl : pure_inst_perl doc_inst_perl
+
+pure_inst_perl : \$(MAP_TARGET)
+ $att{CP} \$(MAP_SHRTARGET) ",vmspath($Config{'installbin'}),"
+ $att{CP} \$(MAP_TARGET) ",vmspath($Config{'installbin'}),"
+
+map_clean :
+ $att{RM_F} ",vmsify("${tmp}perlmain.obj"),vmsify("${tmp}perlmain.c"),
+ vmsify("${tmp}PerlShr.Opt")," $makefilename
+";
+
+ join '', @m;
+}
+
+sub extliblist {
+ '','','';
+}
+
+sub old_extliblist {
+ '','',''
+}
+
+sub new_extliblist {
+ '','',''
+}
+
+# --- Write a DynaLoader bootstrap file if required
+
+# VMS doesn't require a bootstrap file as a rule
+sub mkbootstrap {
+ 1;
+}
+
+sub mksymlists {
+ my($self,%attribs) = @_;
+
+ MY->init_main() unless $att{BASEEXT};
+
+ my($vars) = $attribs{DL_VARS} || $att{DL_VARS} || [];
+ my($procs) = $attribs{DL_FUNCS} || $att{DL_FUNCS};
+ my($package,$packprefix,$sym);
+ if (!%$procs) {
+ $package = $attribs{NAME} || $att{NAME};
+ $package =~ s/\W/_/g;
+ $procs = { $package => ["boot_$package"] };
+ }
+ my($isvax) = $Config{'arch'} =~ /VAX/i;
+
+ # Options file declaring universal symbols
+ # Used when linking shareable image for dynamic extension,
+ # or when linking PerlShr into which we've added this package
+ # as a static extension
+ # We don't do anything to preserve order, so we won't relax
+ # the GSMATCH criteria for a dynamic extension
+ open OPT, ">$att{BASEEXT}.opt";
+ foreach $package (keys %$procs) {
+ ($packprefix = $package) =~ s/\W/_/g;
+ foreach $sym (@{$$procs{$package}}) {
+ $sym = "XS_${packprefix}_$sym" unless $sym =~ /^boot_/;
+ if ($isvax) { print OPT "UNIVERSAL=$sym\n" }
+ else { print OPT "SYMBOL_VECTOR=($sym=PROCEDURE)\n"; }
+ }
+ }
+ foreach $sym (@$vars) {
+ print OPT "PSECT_ATTR=${sym},PIC,OVR,RD,NOEXE,WRT,NOSHR\n";
+ if ($isvax) { print OPT "UNIVERSAL=$sym\n" }
+ else { print OPT "SYMBOL_VECTOR=($sym=DATA)\n"; }
+ }
+ close OPT;
+}
+
+# --- Output postprocessing section ---
+
+sub nicetext {
+ # Insure that colons marking targets are preceded by space -
+ # most Unix Makes don't need this, but it's necessary under VMS
+ # to distinguish the target delimiter from a colon appearing as
+ # part of a filespec.
+
+ my($self,$text) = @_;
+ $text =~ s/([^\s:])(:+\s)/$1 $2/gs;
+ $text;
+}
+
+1;
+
+__END__
+# MM_VMS.pm
+# MakeMaker default methods for VMS
+# This package is inserted into @ISA of MakeMaker's MM before the
+# built-in MM_Unix methods if MakeMaker.pm is run under VMS.
+#
+# Version: 4.03
+# Author: Charles Bailey bailey@genetics.upenn.edu
+# Revised: 30-Jan-1995
+
+package ExtUtils::MM_VMS;
+
+use Config;
+require Exporter;
use File::VMSspec;
use File::Basename;