diff options
Diffstat (limited to 'vms/ext/MM_VMS.pm')
-rw-r--r-- | vms/ext/MM_VMS.pm | 812 |
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; |