diff options
Diffstat (limited to 'Master/tlpkg/tlperl/lib/ExtUtils/MM_Unix.pm')
-rw-r--r-- | Master/tlpkg/tlperl/lib/ExtUtils/MM_Unix.pm | 881 |
1 files changed, 543 insertions, 338 deletions
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_Unix.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_Unix.pm index 009b18ee085..66a24d7838b 100644 --- a/Master/tlpkg/tlperl/lib/ExtUtils/MM_Unix.pm +++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_Unix.pm @@ -7,15 +7,14 @@ use strict; use Carp; use ExtUtils::MakeMaker::Config; use File::Basename qw(basename dirname); -use DirHandle; our %Config_Override; -use ExtUtils::MakeMaker qw($Verbose neatvalue); +use ExtUtils::MakeMaker qw($Verbose neatvalue _sprintf562); # If we make $VERSION an our variable parse_version() breaks use vars qw($VERSION); -$VERSION = '7.10_02'; +$VERSION = '7.24'; $VERSION = eval $VERSION; ## no critic [BuiltinFunctions::ProhibitStringyEval] require ExtUtils::MM_Any; @@ -98,7 +97,6 @@ something that used to be in here, look in MM_Any. # So we don't have to keep calling the methods over and over again, # we have these globals to cache the values. Faster and shrtr. my $Curdir = __PACKAGE__->curdir; -my $Rootdir = __PACKAGE__->rootdir; my $Updir = __PACKAGE__->updir; @@ -143,31 +141,36 @@ sub c_o { }; } - push @m, qq{ -.c.s: - $command -S $flags \$*.c + my $m_o = $self->{XSMULTI} ? $self->xs_obj_opt('$*.s') : ''; + push @m, sprintf <<'EOF', $command, $flags, $m_o; -.c\$(OBJ_EXT): - $command $flags \$*.c +.c.s : + %s -S %s $*.c %s +EOF -.cpp\$(OBJ_EXT): - $command $flags \$*.cpp + my @exts = qw(c cpp cxx cc); + push @exts, 'C' if !$Is{OS2} and !$Is{Win32} and !$Is{Dos}; #Case-specific + $m_o = $self->{XSMULTI} ? $self->xs_obj_opt('$*$(OBJ_EXT)') : ''; + for my $ext (@exts) { + push @m, "\n.$ext\$(OBJ_EXT) :\n\t$command $flags \$*.$ext" . ( $m_o ? " $m_o" : '' ) . "\n"; + } + return join "", @m; +} -.cxx\$(OBJ_EXT): - $command $flags \$*.cxx -.cc\$(OBJ_EXT): - $command $flags \$*.cc -}; +=item xs_obj_opt - push @m, qq{ -.C\$(OBJ_EXT): - $command $flags \$*.C -} if !$Is{OS2} and !$Is{Win32} and !$Is{Dos}; #Case-specific +Takes the object file as an argument, and returns the portion of compile +command-line that will output to the specified object file. - return join "", @m; +=cut + +sub xs_obj_opt { + my ($self, $output_file) = @_; + "-o $output_file"; } + =item cflags (o) Does very much the same as the cflags script in the perl @@ -284,9 +287,6 @@ sub cflags { $pollute = '$(PERL_MALLOC_DEF)'; } - $self->{CCFLAGS} = quote_paren($self->{CCFLAGS}); - $self->{OPTIMIZE} = quote_paren($self->{OPTIMIZE}); - return $self->{CFLAGS} = qq{ CCFLAGS = $self->{CCFLAGS} OPTIMIZE = $self->{OPTIMIZE} @@ -337,7 +337,6 @@ END foreach my $key (@{$self->{CONFIG}}){ # SITE*EXP macros are defined in &constants; avoid duplicates here next if $once_only{$key}; - $self->{uc $key} = quote_paren($self->{uc $key}); push @m, uc($key) , ' = ' , $self->{uc $key}, "\n"; $once_only{$key} = 1; } @@ -455,9 +454,9 @@ MM_REVISION = $self->{MM_REVISION} push @m, " # Handy lists of source code files: XS_FILES = ".$self->wraplist(sort keys %{$self->{XS}})." -C_FILES = ".$self->wraplist(@{$self->{C}})." -O_FILES = ".$self->wraplist(@{$self->{O_FILES}})." -H_FILES = ".$self->wraplist(@{$self->{H}})." +C_FILES = ".$self->wraplist(sort @{$self->{C}})." +O_FILES = ".$self->wraplist(sort @{$self->{O_FILES}})." +H_FILES = ".$self->wraplist(sort @{$self->{H}})." MAN1PODS = ".$self->wraplist(sort keys %{$self->{MAN1PODS}})." MAN3PODS = ".$self->wraplist(sort keys %{$self->{MAN3PODS}})." "; @@ -466,7 +465,7 @@ MAN3PODS = ".$self->wraplist(sort keys %{$self->{MAN3PODS}})." push @m, q{ # Where is the Config information that we are using/depend on CONFIGDEP = $(PERL_ARCHLIBDEP)$(DFSEP)Config.pm $(PERL_INCDEP)$(DFSEP)config.h -} if -e File::Spec->catfile( $self->{PERL_INC}, 'config.h' ); +} if -e $self->catfile( $self->{PERL_INC}, 'config.h' ); push @m, qq{ @@ -492,10 +491,7 @@ PERL_ARCHIVE_AFTER = $self->{PERL_ARCHIVE_AFTER} push @m, " -TO_INST_PM = ".$self->wraplist(sort keys %{$self->{PM}})." - -PM_TO_BLIB = ".$self->wraplist(map { ($_ => $self->{PM}->{$_}) } sort keys %{$self->{PM}})." -"; +TO_INST_PM = ".$self->wraplist(map $self->quote_dep($_), sort keys %{$self->{PM}})."\n"; join('',@m); } @@ -510,8 +506,9 @@ Same as macro for the depend attribute. sub depend { my($self,%attribs) = @_; my(@m,$key,$val); - while (($key,$val) = each %attribs){ - last unless defined $key; + for my $key (sort keys %attribs){ + my $val = $attribs{$key}; + next unless defined $key and defined $val; push @m, "$key : $val\n"; } join "", @m; @@ -883,25 +880,43 @@ Defines targets for bootstrap files. sub dynamic_bs { my($self, %attribs) = @_; - return ' -BOOTSTRAP = -' unless $self->has_link_code(); - - my $target = $Is{VMS} ? '$(MMS$TARGET)' : '$@'; - - return sprintf <<'MAKE_FRAG', ($target) x 2; -BOOTSTRAP = $(BASEEXT).bs - + return "\nBOOTSTRAP =\n" unless $self->has_link_code(); + my @exts; + if ($self->{XSMULTI}) { + @exts = $self->_xs_list_basenames; + } else { + @exts = '$(BASEEXT)'; + } + return join "\n", + "BOOTSTRAP = @{[map { qq{$_.bs} } @exts]}\n", + map { $self->_xs_make_bs($_) } @exts; +} + +sub _xs_make_bs { + my ($self, $basename) = @_; + my ($v, $d, $f) = File::Spec->splitpath($basename); + my @d = File::Spec->splitdir($d); + shift @d if $self->{XSMULTI} and $d[0] eq 'lib'; + my $instdir = $self->catdir('$(INST_ARCHLIB)', 'auto', @d, $f); + $instdir = '$(INST_ARCHAUTODIR)' if $basename eq '$(BASEEXT)'; + my $instfile = $self->catfile($instdir, "$f.bs"); + my $exists = "$instdir\$(DFSEP).exists"; # match blibdirs_target + # 1 2 3 + return _sprintf562 <<'MAKE_FRAG', $basename, $instfile, $exists; # As 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) : $(FIRST_MAKEFILE) $(BOOTDEP) $(INST_ARCHAUTODIR)$(DFSEP).exists - $(NOECHO) $(ECHO) "Running Mkbootstrap for $(NAME) ($(BSLOADLIBS))" +%1$s.bs : $(FIRST_MAKEFILE) $(BOOTDEP) + $(NOECHO) $(ECHO) "Running Mkbootstrap for %1$s ($(BSLOADLIBS))" $(NOECHO) $(PERLRUN) \ "-MExtUtils::Mkbootstrap" \ - -e "Mkbootstrap('$(BASEEXT)','$(BSLOADLIBS)');" - $(NOECHO) $(TOUCH) "%s" - $(CHMOD) $(PERM_RW) "%s" + -e "Mkbootstrap('%1$s','$(BSLOADLIBS)');" + $(NOECHO) $(TOUCH) "%1$s.bs" + $(CHMOD) $(PERM_RW) "%1$s.bs" + +%2$s : %1$s.bs %3$s + $(NOECHO) $(RM_RF) %2$s + - $(CP_NONEMPTY) %1$s.bs %2$s $(PERM_RW) MAKE_FRAG } @@ -914,31 +929,84 @@ Defines how to produce the *.so (or equivalent) files. sub dynamic_lib { my($self, %attribs) = @_; return '' unless $self->needs_linking(); #might be because of a subdir - return '' unless $self->has_link_code; + my @m = $self->xs_dynamic_lib_macros(\%attribs); + my @libs; + if ($self->{XSMULTI}) { + my @exts = $self->_xs_list_basenames; + for my $ext (@exts) { + my ($v, $d, $f) = File::Spec->splitpath($ext); + my @d = File::Spec->splitdir($d); + shift @d if $d[0] eq 'lib'; + my $instdir = $self->catdir('$(INST_ARCHLIB)', 'auto', @d, $f); + + # Dynamic library names may need special handling. + eval { require DynaLoader }; + if (defined &DynaLoader::mod2fname) { + $f = &DynaLoader::mod2fname([@d, $f]); + } - my($otherldflags) = $attribs{OTHERLDFLAGS} || ""; - my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || ""; - my($armaybe) = $attribs{ARMAYBE} || $self->{ARMAYBE} || ":"; - my($ldfrom) = '$(LDFROM)'; - $armaybe = 'ar' if ($Is{OSF} and $armaybe eq ':'); - my(@m); - my $ld_opt = $Is{OS2} ? '$(OPTIMIZE) ' : ''; # Useful on other systems too? + my $instfile = $self->catfile($instdir, "$f.\$(DLEXT)"); + my $objfile = $self->_xsbuild_value('xs', $ext, 'OBJECT'); + $objfile = "$ext\$(OBJ_EXT)" unless defined $objfile; + my $ldfrom = $self->_xsbuild_value('xs', $ext, 'LDFROM'); + $ldfrom = $objfile unless defined $ldfrom; + my $exportlist = "$ext.def"; + push @libs, [ $objfile, $instfile, $instdir, $ldfrom, $exportlist ]; + } + } else { + @libs = ([ qw($(OBJECT) $(INST_DYNAMIC) $(INST_ARCHAUTODIR) $(LDFROM) $(EXPORT_LIST)) ]); + } + push @m, map { $self->xs_make_dynamic_lib(\%attribs, @$_); } @libs; + + return join("\n",@m); +} + +=item xs_dynamic_lib_macros + +Defines the macros for the C<dynamic_lib> section. + +=cut + +sub xs_dynamic_lib_macros { + my ($self, $attribs) = @_; + my $otherldflags = $attribs->{OTHERLDFLAGS} || ""; + my $inst_dynamic_dep = $attribs->{INST_DYNAMIC_DEP} || ""; + my $armaybe = $self->_xs_armaybe($attribs); + my $ld_opt = $Is{OS2} ? '$(OPTIMIZE) ' : ''; # Useful on other systems too? my $ld_fix = $Is{OS2} ? '|| ( $(RM_F) $@ && sh -c false )' : ''; - push(@m,' -# This section creates the dynamically loadable $(INST_DYNAMIC) -# from $(OBJECT) and possibly $(MYEXTLIB). -ARMAYBE = '.$armaybe.' -OTHERLDFLAGS = '.$ld_opt.$otherldflags.' -INST_DYNAMIC_DEP = '.$inst_dynamic_dep.' -INST_DYNAMIC_FIX = '.$ld_fix.' - -$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPORT_LIST) $(PERL_ARCHIVEDEP) $(PERL_ARCHIVE_AFTER) $(INST_DYNAMIC_DEP) -'); + sprintf <<'EOF', $armaybe, $ld_opt.$otherldflags, $inst_dynamic_dep, $ld_fix; +# This section creates the dynamically loadable objects from relevant +# objects and possibly $(MYEXTLIB). +ARMAYBE = %s +OTHERLDFLAGS = %s +INST_DYNAMIC_DEP = %s +INST_DYNAMIC_FIX = %s +EOF +} + +sub _xs_armaybe { + my ($self, $attribs) = @_; + my $armaybe = $attribs->{ARMAYBE} || $self->{ARMAYBE} || ":"; + $armaybe = 'ar' if ($Is{OSF} and $armaybe eq ':'); + $armaybe; +} + +=item xs_make_dynamic_lib + +Defines the recipes for the C<dynamic_lib> section. + +=cut + +sub xs_make_dynamic_lib { + my ($self, $attribs, $object, $to, $todir, $ldfrom, $exportlist) = @_; + $exportlist = '' if $exportlist ne '$(EXPORT_LIST)'; + my $armaybe = $self->_xs_armaybe($attribs); + my @m = sprintf '%s : %s $(MYEXTLIB) %s$(DFSEP).exists %s $(PERL_ARCHIVEDEP) $(PERL_ARCHIVE_AFTER) $(INST_DYNAMIC_DEP)'."\n", $to, $object, $todir, $exportlist; if ($armaybe ne ':'){ - $ldfrom = 'tmp$(LIB_EXT)'; - push(@m,' $(ARMAYBE) cr '.$ldfrom.' $(OBJECT)'."\n"); - push(@m,' $(RANLIB) '."$ldfrom\n"); + $ldfrom = 'tmp$(LIB_EXT)'; + push(@m," \$(ARMAYBE) cr $ldfrom $object\n"); + push(@m," \$(RANLIB) $ldfrom\n"); } $ldfrom = "-all $ldfrom -none" if $Is{OSF}; @@ -951,16 +1019,14 @@ $(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPO # is using them. This is painful if one for instance tries to restart # a failed build because the link command will fail unnecessarily 'cos # the shared object/library is 'busy'. - push(@m,' $(RM_F) $@ -'); + push(@m," \$(RM_F) \$\@\n"); my $libs = '$(LDLOADLIBS)'; - if (($Is{NetBSD} || $Is{Interix} || $Is{Android}) && $Config{'useshrplib'} eq 'true') { - # Use nothing on static perl platforms, and to the flags needed - # to link against the shared libperl library on shared perl - # platforms. We peek at lddlflags to see if we need -Wl,-R - # or -R to add paths to the run-time library search path. + # Use nothing on static perl platforms, and to the flags needed + # to link against the shared libperl library on shared perl + # platforms. We peek at lddlflags to see if we need -Wl,-R + # or -R to add paths to the run-time library search path. if ($Config{'lddlflags'} =~ /-Wl,-R/) { $libs .= ' "-L$(PERL_INC)" "-Wl,-R$(INSTALLARCHLIB)/CORE" "-Wl,-R$(PERL_ARCHLIB)/CORE" -lperl'; } elsif ($Config{'lddlflags'} =~ /-R/) { @@ -974,22 +1040,16 @@ $(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPO my $ld_run_path_shell = ""; if ($self->{LD_RUN_PATH} ne "") { - $ld_run_path_shell = 'LD_RUN_PATH="$(LD_RUN_PATH)" '; + $ld_run_path_shell = 'LD_RUN_PATH="$(LD_RUN_PATH)" '; } - push @m, sprintf <<'MAKE', $ld_run_path_shell, $ldrun, $ldfrom, $libs; - %s$(LD) %s $(LDDLFLAGS) %s $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) \ - $(PERL_ARCHIVE) %s $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST) \ + push @m, sprintf <<'MAKE', $ld_run_path_shell, $ldrun, $ldfrom, $self->xs_obj_opt('$@'), $libs, $exportlist; + %s$(LD) %s $(LDDLFLAGS) %s $(OTHERLDFLAGS) %s $(MYEXTLIB) \ + $(PERL_ARCHIVE) %s $(PERL_ARCHIVE_AFTER) %s \ $(INST_DYNAMIC_FIX) -MAKE - - push @m, <<'MAKE'; $(CHMOD) $(PERM_RWX) $@ - $(NOECHO) $(RM_RF) $(BOOTSTRAP) - - $(CP_NONEMPTY) $(BOOTSTRAP) $(INST_BOOT) $(PERM_RW) MAKE - - return join('',@m); + join '', @m; } =item exescan @@ -1050,21 +1110,26 @@ WARNING } foreach my $name (@$names){ - foreach my $dir (@$dirs){ + my ($abs, $use_dir); + if ($self->file_name_is_absolute($name)) { # /foo/bar + $abs = $name; + } elsif ($self->canonpath($name) eq + $self->canonpath(basename($name))) { # foo + $use_dir = 1; + } else { # foo/bar + $abs = $self->catfile($Curdir, $name); + } + foreach my $dir ($use_dir ? @$dirs : 1){ next unless defined $dir; # $self->{PERL_SRC} may be undefined - my ($abs, $val); - if ($self->file_name_is_absolute($name)) { # /foo/bar - $abs = $name; - } elsif ($self->canonpath($name) eq - $self->canonpath(basename($name))) { # foo - $abs = $self->catfile($dir, $name); - } else { # foo/bar - $abs = $self->catfile($Curdir, $name); - } + + $abs = $self->catfile($dir, $name) + if $use_dir; + print "Checking $abs\n" if ($trace >= 2); next unless $self->maybe_command($abs); print "Executing $abs\n" if ($trace >= 2); + my $val; my $version_check = qq{"$abs" -le "require $ver; print qq{VER_OK}"}; # To avoid using the unportable 2>&1 to suppress STDERR, @@ -1191,11 +1256,12 @@ sub _fixin_replace_shebang { = reverse grep { $self->file_name_is_absolute($_) } $self->path; $interpreter = ''; - foreach my $dir (@absdirs) { - if ( $self->maybe_command($cmd) ) { + foreach my $dir (@absdirs) { + my $maybefile = $self->catfile($dir,$cmd); + if ( $self->maybe_command($maybefile) ) { warn "Ignoring $interpreter in $file\n" if $Verbose && $interpreter; - $interpreter = $self->catfile( $dir, $cmd ); + $interpreter = $maybefile; } } } @@ -1451,7 +1517,10 @@ sub init_MAN3PODS { # To force inclusion, just name it "Configure.pod", or override # MAN3PODS foreach my $name (keys %manifypods) { - if ($self->{PERL_CORE} and $name =~ /(config|setup).*\.pm/is) { + if ( + ($self->{PERL_CORE} and $name =~ /(config|setup).*\.pm/is) or + ( $name =~ m/^README\.pod$/i ) # don't manify top-level README.pod + ) { delete $manifypods{$name}; next; } @@ -1562,7 +1631,14 @@ sub init_PM { $inst = $self->libscan($inst); print "libscan($path) => '$inst'\n" if ($Verbose >= 2); return unless $inst; - $self->{PM}{$path} = $inst; + if ($self->{XSMULTI} and $inst =~ /\.xs\z/) { + my($base); ($base = $path) =~ s/\.xs\z//; + $self->{XS}{$path} = "$base.c"; + push @{$self->{C}}, "$base.c"; + push @{$self->{O_FILES}}, "$base$self->{OBJ_EXT}"; + } else { + $self->{PM}{$path} = $inst; + } }, @{$self->{PMLIBDIRS}}); } } @@ -1987,19 +2063,22 @@ sub init_PERL { $self->{PERL_CORE} = $ENV{PERL_CORE} unless exists $self->{PERL_CORE}; $self->{PERL_CORE} = 0 unless defined $self->{PERL_CORE}; + # Make sure perl can find itself before it's installed. + my $lib_paths = $self->{UNINSTALLED_PERL} || $self->{PERL_CORE} + ? ( $self->{PERL_ARCHLIB} && $self->{PERL_LIB} && $self->{PERL_ARCHLIB} ne $self->{PERL_LIB} ) ? + q{ "-I$(PERL_LIB)" "-I$(PERL_ARCHLIB)"} : q{ "-I$(PERL_LIB)"} + : undef; + my $inst_lib_paths = $self->{INST_ARCHLIB} ne $self->{INST_LIB} + ? 'RUN)'.$perlflags.' "-I$(INST_ARCHLIB)" "-I$(INST_LIB)"' + : 'RUN)'.$perlflags.' "-I$(INST_LIB)"'; # How do we run perl? foreach my $perl (qw(PERL FULLPERL ABSPERL)) { my $run = $perl.'RUN'; $self->{$run} = qq{\$($perl)}; + $self->{$run} .= $lib_paths if $lib_paths; - # Make sure perl can find itself before it's installed. - $self->{$run} .= q{ "-I$(PERL_LIB)" "-I$(PERL_ARCHLIB)"} - if $self->{UNINSTALLED_PERL} || $self->{PERL_CORE}; - - $self->{$perl.'RUNINST'} = - sprintf q{$(%sRUN)%s "-I$(INST_ARCHLIB)" "-I$(INST_LIB)"}, - $perl, $perlflags; + $self->{$perl.'RUNINST'} = '$('.$perl.$inst_lib_paths; } return 1; @@ -2076,6 +2155,31 @@ sub init_xs { $self->catfile('$(INST_ARCHAUTODIR)', '$(DLBASE).$(DLEXT)'); $self->{INST_BOOT} = $self->catfile('$(INST_ARCHAUTODIR)', '$(BASEEXT).bs'); + if ($self->{XSMULTI}) { + my @exts = $self->_xs_list_basenames; + my (@statics, @dynamics, @boots); + for my $ext (@exts) { + my ($v, $d, $f) = File::Spec->splitpath($ext); + my @d = File::Spec->splitdir($d); + shift @d if defined $d[0] and $d[0] eq 'lib'; + my $instdir = $self->catdir('$(INST_ARCHLIB)', 'auto', @d, $f); + my $instfile = $self->catfile($instdir, $f); + push @statics, "$instfile\$(LIB_EXT)"; + + # Dynamic library names may need special handling. + my $dynfile = $instfile; + eval { require DynaLoader }; + if (defined &DynaLoader::mod2fname) { + $dynfile = $self->catfile($instdir, &DynaLoader::mod2fname([@d, $f])); + } + + push @dynamics, "$dynfile.\$(DLEXT)"; + push @boots, "$instfile.bs"; + } + $self->{INST_STATIC} = join ' ', @statics; + $self->{INST_DYNAMIC} = join ' ', @dynamics; + $self->{INST_BOOT} = join ' ', @boots; + } } else { $self->{INST_STATIC} = ''; $self->{INST_DYNAMIC} = ''; @@ -2192,7 +2296,7 @@ doc_perl_install :: all -$(NOECHO) $(MKPATH) "$(DESTINSTALLARCHLIB)" -$(NOECHO) $(DOC_INSTALL) \ "Module" "$(NAME)" \ - "installed into" $(INSTALLPRIVLIB) \ + "installed into" "$(INSTALLPRIVLIB)" \ LINKTYPE "$(LINKTYPE)" \ VERSION "$(VERSION)" \ EXE_FILES "$(EXE_FILES)" \ @@ -2203,7 +2307,7 @@ doc_site_install :: all -$(NOECHO) $(MKPATH) "$(DESTINSTALLARCHLIB)" -$(NOECHO) $(DOC_INSTALL) \ "Module" "$(NAME)" \ - "installed into" $(INSTALLSITELIB) \ + "installed into" "$(INSTALLSITELIB)" \ LINKTYPE "$(LINKTYPE)" \ VERSION "$(VERSION)" \ EXE_FILES "$(EXE_FILES)" \ @@ -2214,7 +2318,7 @@ doc_vendor_install :: all -$(NOECHO) $(MKPATH) "$(DESTINSTALLARCHLIB)" -$(NOECHO) $(DOC_INSTALL) \ "Module" "$(NAME)" \ - "installed into" $(INSTALLVENDORLIB) \ + "installed into" "$(INSTALLVENDORLIB)" \ LINKTYPE "$(LINKTYPE)" \ VERSION "$(VERSION)" \ EXE_FILES "$(EXE_FILES)" \ @@ -2249,7 +2353,7 @@ sub installbin { my($self) = shift; return "" unless $self->{EXE_FILES} && ref $self->{EXE_FILES} eq "ARRAY"; - my @exefiles = @{$self->{EXE_FILES}}; + my @exefiles = sort @{$self->{EXE_FILES}}; return "" unless @exefiles; @exefiles = map vmsify($_), @exefiles if $Is{VMS}; @@ -2265,7 +2369,7 @@ sub installbin { $to = vmsify($to) if $Is{VMS}; $fromto{$from} = $to; } - my @to = values %fromto; + my @to = sort values %fromto; my @m; push(@m, qq{ @@ -2281,17 +2385,16 @@ realclean :: push @m, map "\t$_\n", $self->split_command('$(RM_F)', @to); push @m, "\n"; - # A target for each exe file. - while (my($from,$to) = each %fromto) { - last unless defined $from; - - push @m, sprintf <<'MAKE', $to, $from, $to, $from, $to, $to, $to; -%s : %s $(FIRST_MAKEFILE) $(INST_SCRIPT)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists - $(NOECHO) $(RM_F) %s - $(CP) %s %s - $(FIXIN) %s - -$(NOECHO) $(CHMOD) $(PERM_RWX) %s + my @froms = sort keys %fromto; + for my $from (@froms) { + # 1 2 + push @m, _sprintf562 <<'MAKE', $from, $fromto{$from}; +%2$s : %1$s $(FIRST_MAKEFILE) $(INST_SCRIPT)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists + $(NOECHO) $(RM_F) %2$s + $(CP) %1$s %2$s + $(FIXIN) %2$s + -$(NOECHO) $(CHMOD) $(PERM_RWX) %2$s MAKE @@ -2300,18 +2403,21 @@ MAKE join "", @m; } - =item linkext (o) Defines the linkext target which in turn defines the LINKTYPE. =cut +# LINKTYPE => static or dynamic or '' sub linkext { my($self, %attribs) = @_; - # LINKTYPE => static or dynamic or '' - my($linktype) = defined $attribs{LINKTYPE} ? - $attribs{LINKTYPE} : '$(LINKTYPE)'; + my $linktype = $attribs{LINKTYPE}; + $linktype = $self->{LINKTYPE} unless defined $linktype; + if (defined $linktype and $linktype eq '') { + warn "Warning: LINKTYPE set to '', no longer necessary\n"; + } + $linktype = '$(LINKTYPE)' unless defined $linktype; " linkext :: $linktype \$(NOECHO) \$(NOOP) @@ -2326,14 +2432,13 @@ all entries in the directory that match the regular expression. =cut sub lsdir { - my($self) = shift; - my($dir, $regex) = @_; - my(@ls); - my $dh = new DirHandle; - $dh->open($dir || ".") or return (); - @ls = $dh->read; - $dh->close; - @ls = grep(/$regex/, @ls) if $regex; + # $self + my(undef, $dir, $regex) = @_; + opendir(my $dh, defined($dir) ? $dir : ".") + or return; + my @ls = readdir $dh; + closedir $dh; + @ls = grep(/$regex/, @ls) if defined $regex; @ls; } @@ -2346,9 +2451,9 @@ into the Makefile. sub macro { my($self,%attribs) = @_; - my(@m,$key,$val); - while (($key,$val) = each %attribs){ - last unless defined $key; + my @m; + foreach my $key (sort keys %attribs) { + my $val = $attribs{$key}; push @m, "$key = $val\n"; } join "", @m; @@ -2369,11 +2474,13 @@ sub makeaperl { my($self, %attribs) = @_; my($makefilename, $searchdirs, $static, $extra, $perlinc, $target, $tmp, $libperl) = @attribs{qw(MAKE DIRS STAT EXTRA INCL TARGET TMP LIBPERL)}; + s/^(.*)/"-I$1"/ for @{$perlinc || []}; my(@m); push @m, " # --- MakeMaker makeaperl section --- MAP_TARGET = $target FULLPERL = $self->{FULLPERL} +MAP_PERLINC = @{$perlinc || []} "; return join '', @m if $self->{PARENT}; @@ -2381,10 +2488,10 @@ FULLPERL = $self->{FULLPERL} unless ($self->{MAKEAPERL}) { push @m, q{ -$(MAP_TARGET) :: static $(MAKE_APERL_FILE) +$(MAP_TARGET) :: $(MAKE_APERL_FILE) $(MAKE) $(USEMAKEFILE) $(MAKE_APERL_FILE) $@ -$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib +$(MAKE_APERL_FILE) : static $(FIRST_MAKEFILE) pm_to_blib $(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET) $(NOECHO) $(PERLRUNINST) \ Makefile.PL DIR="}, $dir, q{" \ @@ -2392,23 +2499,18 @@ $(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib MAKEAPERL=1 NORECURS=1 CCCDLFLAGS=}; foreach (@ARGV){ - if( /\s/ ){ - s/=(.*)/='$1'/; + my $arg = $_; # avoid lvalue aliasing + if ( $arg =~ /(^.*?=)(.*['\s].*)/ ) { + $arg = $1 . $self->quote_literal($2); } - push @m, " \\\n\t\t$_"; + push @m, " \\\n\t\t$arg"; } -# push @m, map( " \\\n\t\t$_", @ARGV ); push @m, "\n"; return join '', @m; } - - - my($cccmd, $linkcmd, $lperl); - - - $cccmd = $self->const_cccmd($libperl); + my $cccmd = $self->const_cccmd($libperl); $cccmd =~ s/^CCCMD\s*=\s*//; $cccmd =~ s/\$\(INC\)/ "-I$self->{PERL_INC}" /; $cccmd .= " $Config{cccdlflags}" @@ -2416,7 +2518,7 @@ $(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib $cccmd =~ s/\(CC\)/\(PERLMAINCC\)/; # The front matter of the linkcommand... - $linkcmd = join ' ', "\$(CC)", + my $linkcmd = join ' ', "\$(CC)", grep($_, @Config{qw(ldflags ccdlflags)}); $linkcmd =~ s/\s+/ /g; $linkcmd =~ s,(perl\.exp),\$(PERL_INC)/$1,; @@ -2424,6 +2526,10 @@ $(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib # Which *.a files could we make use of... my %static; require File::Find; + # don't use File::Spec here because on Win32 F::F still uses "/" + my $installed_version = join('/', + 'auto', $self->{FULLEXT}, "$self->{BASEEXT}$self->{LIB_EXT}" + ); File::Find::find(sub { return unless m/\Q$self->{LIB_EXT}\E$/; @@ -2469,7 +2575,7 @@ $(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib # Once the patch to minimod.PL is in the distribution, I can # drop it - return if $File::Find::name =~ m:auto/$self->{FULLEXT}/$self->{BASEEXT}$self->{LIB_EXT}\z:; + return if $File::Find::name =~ m:\Q$installed_version\E\z:; use Cwd 'cwd'; $static{cwd() . "/" . $_}++; }, grep( -d $_, @{$searchdirs || []}) ); @@ -2493,15 +2599,16 @@ $(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib # MAP_STATIC doesn't look into subdirs yet. Once "all" is made and we # regenerate the Makefiles, MAP_STATIC and the dependencies for # extralibs.all are computed correctly + my @map_static = reverse sort keys %static; push @m, " MAP_LINKCMD = $linkcmd -MAP_PERLINC = @{$perlinc || []} -MAP_STATIC = ", -join(" \\\n\t", reverse sort keys %static), " +MAP_STATIC = ", join(" \\\n\t", map { qq{"$_"} } @map_static), " +MAP_STATICDEP = ", join(' ', map { $self->quote_dep($_) } @map_static), " MAP_PRELIBS = $Config{perllibs} $Config{cryptlib} "; + my $lperl; if (defined $libperl) { ($lperl = $libperl) =~ s/\$\(A\)/$self->{LIB_EXT}/; } @@ -2522,17 +2629,20 @@ MAP_PRELIBS = $Config{perllibs} $Config{cryptlib} } } - print "Warning: $libperl not found - If you're going to build a static perl binary, make sure perl is installed - otherwise ignore this warning\n" - unless (-f $lperl || defined($self->{PERL_SRC})); + print <<EOF unless -f $lperl || defined($self->{PERL_SRC}); +Warning: $libperl not found +If you're going to build a static perl binary, make sure perl is installed +otherwise ignore this warning +EOF } # SUNOS ld does not take the full path to a shared library my $llibperl = $libperl ? '$(MAP_LIBPERL)' : '-lperl'; + my $libperl_dep = $self->quote_dep($libperl); push @m, " MAP_LIBPERL = $libperl +MAP_LIBPERLDEP = $libperl_dep LLIBPERL = $llibperl "; @@ -2546,25 +2656,29 @@ $(INST_ARCHAUTODIR)/extralibs.all : $(INST_ARCHAUTODIR)$(DFSEP).exists '.join(" push @m, "\tcat $catfile >> \$\@\n"; } -push @m, " -\$(MAP_TARGET) :: $tmp/perlmain\$(OBJ_EXT) \$(MAP_LIBPERL) \$(MAP_STATIC) \$(INST_ARCHAUTODIR)/extralibs.all - \$(MAP_LINKCMD) -o \$\@ \$(OPTIMIZE) $tmp/perlmain\$(OBJ_EXT) \$(LDFROM) \$(MAP_STATIC) \$(LLIBPERL) `cat \$(INST_ARCHAUTODIR)/extralibs.all` \$(MAP_PRELIBS) - \$(NOECHO) \$(ECHO) 'To install the new \"\$(MAP_TARGET)\" binary, call' - \$(NOECHO) \$(ECHO) ' \$(MAKE) \$(USEMAKEFILE) $makefilename inst_perl MAP_TARGET=\$(MAP_TARGET)' - \$(NOECHO) \$(ECHO) 'To remove the intermediate files say' - \$(NOECHO) \$(ECHO) ' \$(MAKE) \$(USEMAKEFILE) $makefilename map_clean' + my $ldfrom = $self->{XSMULTI} ? '' : '$(LDFROM)'; + # 1 2 3 4 + push @m, _sprintf562 <<'EOF', $tmp, $ldfrom, $self->xs_obj_opt('$@'), $makefilename; +$(MAP_TARGET) :: %1$s/perlmain$(OBJ_EXT) $(MAP_LIBPERLDEP) $(MAP_STATICDEP) $(INST_ARCHAUTODIR)/extralibs.all + $(MAP_LINKCMD) %2$s $(OPTIMIZE) %1$s/perlmain$(OBJ_EXT) %3$s $(MAP_STATIC) "$(LLIBPERL)" `cat $(INST_ARCHAUTODIR)/extralibs.all` $(MAP_PRELIBS) + $(NOECHO) $(ECHO) "To install the new '$(MAP_TARGET)' binary, call" + $(NOECHO) $(ECHO) " $(MAKE) $(USEMAKEFILE) %4$s inst_perl MAP_TARGET=$(MAP_TARGET)" + $(NOECHO) $(ECHO) " $(MAKE) $(USEMAKEFILE) %4$s map_clean" -$tmp/perlmain\$(OBJ_EXT): $tmp/perlmain.c -"; +%1$s/perlmain\$(OBJ_EXT): %1$s/perlmain.c +EOF push @m, "\t".$self->cd($tmp, qq[$cccmd "-I\$(PERL_INC)" perlmain.c])."\n"; - push @m, qq{ -$tmp/perlmain.c: $makefilename}, q{ + my $maybe_DynaLoader = $Config{usedl} ? 'q(DynaLoader)' : ''; + push @m, _sprintf562 <<'EOF', $tmp, $makefilename, $maybe_DynaLoader; + +%1$s/perlmain.c: %2$s $(NOECHO) $(ECHO) Writing $@ - $(NOECHO) $(PERL) $(MAP_PERLINC) "-MExtUtils::Miniperl" \\ - -e "writemain(grep s#.*/auto/##s, split(q| |, q|$(MAP_STATIC)|))" > $@t && $(MV) $@t $@ + $(NOECHO) $(PERL) $(MAP_PERLINC) "-MExtUtils::Miniperl" \ + -e "writemain(grep(s#.*/auto/##s, @ARGV), %3$s)" $(MAP_STATIC) > $@t + $(MV) $@t $@ -}; +EOF push @m, "\t", q{$(NOECHO) $(PERL) "$(INSTALLSCRIPT)/fixpmain" } if (defined (&Dos::UseLFN) && Dos::UseLFN()==0); @@ -2694,6 +2808,7 @@ sub parse_abstract { local $/ = "\n"; open(my $fh, '<', $parsefile) or die "Could not open '$parsefile': $!"; + binmode $fh; my $inpod = 0; my $pod_encoding; my $package = $self->{DISTNAME}; @@ -2701,7 +2816,7 @@ sub parse_abstract { while (<$fh>) { $inpod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $inpod; next if !$inpod; - chop; + s#\r*\n\z##; # handle CRLF input if ( /^=encoding\s*(.*)$/i ) { $pod_encoding = $1; @@ -2766,7 +2881,7 @@ sub parse_version { next if $inpod || /^\s*#/; chop; next if /^\s*(if|unless|elsif)/; - if ( m{^ \s* package \s+ \w[\w\:\']* \s+ (v?[0-9._]+) \s* ; }x ) { + if ( m{^ \s* package \s+ \w[\w\:\']* \s+ (v?[0-9._]+) \s* (;|\{) }x ) { local $^W = 0; $result = $1; } @@ -2811,7 +2926,16 @@ sub get_version { =item pasthru (o) Defines the string that is passed to recursive make calls in -subdirectories. +subdirectories. The variables like C<PASTHRU_DEFINE> are used in each +level, and passed downwards on the command-line with e.g. the value of +that level's DEFINE. Example: + + # Level 0 has DEFINE = -Dfunky + # This code will define level 0's PASTHRU=PASTHRU_DEFINE="$(DEFINE) + # $(PASTHRU_DEFINE)" + # Level 0's $(CCCMD) will include macros $(DEFINE) and $(PASTHRU_DEFINE) + # So will level 1's, so when level 1 compiles, it will get right values + # And so ad infinitum =cut @@ -2832,8 +2956,14 @@ sub pasthru { } foreach my $key (qw(DEFINE INC)) { - next unless defined $self->{$key}; - push @pasthru, "PASTHRU_$key=\"\$(PASTHRU_$key)\""; + # default to the make var + my $val = qq{\$($key)}; + # expand within perl if given since need to use quote_literal + # since INC might include space-protecting ""! + chomp($val = $self->{$key}) if defined $self->{$key}; + $val .= " \$(PASTHRU_$key)"; + my $quoted = $self->quote_literal($val); + push @pasthru, qq{PASTHRU_$key=$quoted}; } push @m, "\nPASTHRU = ", join ($sep, @pasthru), "\n"; @@ -2913,7 +3043,7 @@ pm_to_blib({\@ARGV}, '$autodir', q[\$(PM_FILTER)], '\$(PERM_DIR)') CODE my @cmds = $self->split_command($pm_to_blib, - map { ($_, $self->{PM}->{$_}) } sort keys %{$self->{PM}}); + map { ($self->quote_literal($_) => $self->quote_literal($self->{PM}->{$_})) } sort keys %{$self->{PM}}); $r .= join '', map { "\t\$(NOECHO) $_\n" } @cmds; $r .= qq{\t\$(NOECHO) \$(TOUCH) pm_to_blib\n}; @@ -2921,39 +3051,6 @@ CODE return $r; } -=item post_constants (o) - -Returns an empty string per default. Dedicated to overrides from -within Makefile.PL after all constants have been defined. - -=cut - -sub post_constants{ - ""; -} - -=item post_initialize (o) - -Returns an empty string per default. Used in Makefile.PLs to add some -chunk of text to the Makefile after the object is initialized. - -=cut - -sub post_initialize { - ""; -} - -=item postamble (o) - -Returns an empty string. Can be used in Makefile.PLs to write some -text to the Makefile at the end. - -=cut - -sub postamble { - ""; -} - # transform dot-separated version string into comma-separated quadruple # examples: '1.2.3.4.5' => '1,2,3,4' # '1.2.3' => '1,2,3,0' @@ -2977,25 +3074,23 @@ sub ppd { $abstract =~ s/</</g; $abstract =~ s/>/>/g; - my $author = join(', ',@{$self->{AUTHOR} || []}); + my $author = join(', ',@{ ref $self->{AUTHOR} eq 'ARRAY' ? $self->{AUTHOR} : [ $self->{AUTHOR} || '']}); $author =~ s/</</g; $author =~ s/>/>/g; - my $ppd_file = '$(DISTNAME).ppd'; + my $ppd_file = "$self->{DISTNAME}.ppd"; - my @ppd_cmds = $self->echo(<<'PPD_HTML', $ppd_file, { append => 0, allow_variables => 1 }); -<SOFTPKG NAME="$(DISTNAME)" VERSION="$(VERSION)"> -PPD_HTML + my @ppd_chunks = qq(<SOFTPKG NAME="$self->{DISTNAME}" VERSION="$self->{VERSION}">\n); - my $ppd_xml = sprintf <<'PPD_HTML', $abstract, $author; + push @ppd_chunks, sprintf <<'PPD_HTML', $abstract, $author; <ABSTRACT>%s</ABSTRACT> <AUTHOR>%s</AUTHOR> PPD_HTML - $ppd_xml .= " <IMPLEMENTATION>\n"; + push @ppd_chunks, " <IMPLEMENTATION>\n"; if ( $self->{MIN_PERL_VERSION} ) { my $min_perl_version = $self->_ppd_version($self->{MIN_PERL_VERSION}); - $ppd_xml .= sprintf <<'PPD_PERLVERS', $min_perl_version; + push @ppd_chunks, sprintf <<'PPD_PERLVERS', $min_perl_version; <PERLCORE VERSION="%s" /> PPD_PERLVERS @@ -3015,7 +3110,7 @@ PPD_PERLVERS my %attrs = ( NAME => $name ); $attrs{VERSION} = $version if $version; my $attrs = join " ", map { qq[$_="$attrs{$_}"] } sort keys %attrs; - $ppd_xml .= qq( <REQUIRE $attrs />\n); + push @ppd_chunks, qq( <REQUIRE $attrs />\n); } my $archname = $Config{archname}; @@ -3025,28 +3120,28 @@ PPD_PERLVERS # version that changes when binary compatibility may change $archname .= "-$Config{PERL_REVISION}.$Config{PERL_VERSION}"; } - $ppd_xml .= sprintf <<'PPD_OUT', $archname; + push @ppd_chunks, sprintf <<'PPD_OUT', $archname; <ARCHITECTURE NAME="%s" /> PPD_OUT if ($self->{PPM_INSTALL_SCRIPT}) { if ($self->{PPM_INSTALL_EXEC}) { - $ppd_xml .= sprintf qq{ <INSTALL EXEC="%s">%s</INSTALL>\n}, + push @ppd_chunks, sprintf qq{ <INSTALL EXEC="%s">%s</INSTALL>\n}, $self->{PPM_INSTALL_EXEC}, $self->{PPM_INSTALL_SCRIPT}; } else { - $ppd_xml .= sprintf qq{ <INSTALL>%s</INSTALL>\n}, + push @ppd_chunks, sprintf qq{ <INSTALL>%s</INSTALL>\n}, $self->{PPM_INSTALL_SCRIPT}; } } if ($self->{PPM_UNINSTALL_SCRIPT}) { if ($self->{PPM_UNINSTALL_EXEC}) { - $ppd_xml .= sprintf qq{ <UNINSTALL EXEC="%s">%s</UNINSTALL>\n}, + push @ppd_chunks, sprintf qq{ <UNINSTALL EXEC="%s">%s</UNINSTALL>\n}, $self->{PPM_UNINSTALL_EXEC}, $self->{PPM_UNINSTALL_SCRIPT}; } else { - $ppd_xml .= sprintf qq{ <UNINSTALL>%s</UNINSTALL>\n}, + push @ppd_chunks, sprintf qq{ <UNINSTALL>%s</UNINSTALL>\n}, $self->{PPM_UNINSTALL_SCRIPT}; } } @@ -3054,13 +3149,13 @@ PPD_OUT my ($bin_location) = $self->{BINARY_LOCATION} || ''; $bin_location =~ s/\\/\\\\/g; - $ppd_xml .= sprintf <<'PPD_XML', $bin_location; + push @ppd_chunks, sprintf <<'PPD_XML', $bin_location; <CODEBASE HREF="%s" /> </IMPLEMENTATION> </SOFTPKG> PPD_XML - push @ppd_cmds, $self->echo($ppd_xml, $ppd_file, { append => 1 }); + my @ppd_cmds = $self->stashmeta(join('', @ppd_chunks), $ppd_file); return sprintf <<'PPD_OUT', join "\n\t", @ppd_cmds; # Creates a PPD (Perl Package Description) for a binary distribution. @@ -3138,29 +3233,29 @@ sub processPL { foreach my $plfile (sort keys %$pl_files) { my $list = ref($pl_files->{$plfile}) ? $pl_files->{$plfile} - : [$pl_files->{$plfile}]; + : [$pl_files->{$plfile}]; - foreach my $target (@$list) { + foreach my $target (@$list) { if( $Is{VMS} ) { $plfile = vmsify($self->eliminate_macros($plfile)); $target = vmsify($self->eliminate_macros($target)); } - # Normally a .PL file runs AFTER pm_to_blib so it can have - # blib in its @INC and load the just built modules. BUT if - # the generated module is something in $(TO_INST_PM) which - # pm_to_blib depends on then it can't depend on pm_to_blib - # else we have a dependency loop. - my $pm_dep; - my $perlrun; - if( defined $self->{PM}{$target} ) { - $pm_dep = ''; - $perlrun = 'PERLRUN'; - } - else { - $pm_dep = 'pm_to_blib'; - $perlrun = 'PERLRUNINST'; - } + # Normally a .PL file runs AFTER pm_to_blib so it can have + # blib in its @INC and load the just built modules. BUT if + # the generated module is something in $(TO_INST_PM) which + # pm_to_blib depends on then it can't depend on pm_to_blib + # else we have a dependency loop. + my $pm_dep; + my $perlrun; + if( defined $self->{PM}{$target} ) { + $pm_dep = ''; + $perlrun = 'PERLRUN'; + } + else { + $pm_dep = 'pm_to_blib'; + $perlrun = 'PERLRUNINST'; + } $m .= <<MAKE_FRAG; @@ -3171,7 +3266,7 @@ $target :: $plfile $pm_dep \$($perlrun) $plfile $target MAKE_FRAG - } + } } return $m; @@ -3338,29 +3433,86 @@ static :: $(FIRST_MAKEFILE) $(INST_STATIC) '; } -=item static_lib (o) +sub static_lib { + my($self) = @_; + return '' unless $self->has_link_code; + my(@m); + my @libs; + if ($self->{XSMULTI}) { + for my $ext ($self->_xs_list_basenames) { + my ($v, $d, $f) = File::Spec->splitpath($ext); + my @d = File::Spec->splitdir($d); + shift @d if $d[0] eq 'lib'; + my $instdir = $self->catdir('$(INST_ARCHLIB)', 'auto', @d, $f); + my $instfile = $self->catfile($instdir, "$f\$(LIB_EXT)"); + my $objfile = "$ext\$(OBJ_EXT)"; + push @libs, [ $objfile, $instfile, $instdir ]; + } + } else { + @libs = ([ qw($(OBJECT) $(INST_STATIC) $(INST_ARCHAUTODIR)) ]); + } + push @m, map { $self->xs_make_static_lib(@$_); } @libs; + join "\n", @m; +} + +=item xs_make_static_lib -Defines how to produce the *.a (or equivalent) files. +Defines the recipes for the C<static_lib> section. =cut -sub static_lib { - my($self) = @_; - return '' unless $self->has_link_code; +sub xs_make_static_lib { + my ($self, $from, $to, $todir) = @_; + my @m = sprintf '%s: %s $(MYEXTLIB) %s$(DFSEP).exists'."\n", $to, $from, $todir; + push @m, "\t\$(RM_F) \"\$\@\"\n"; + push @m, $self->static_lib_fixtures; + push @m, $self->static_lib_pure_cmd($from); + push @m, "\t\$(CHMOD) \$(PERM_RWX) \$\@\n"; + push @m, $self->static_lib_closures($todir); + join '', @m; +} - my(@m); - push(@m, <<'END'); +=item static_lib_closures -$(INST_STATIC) : $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists - $(RM_RF) $@ -END +Records C<$(EXTRALIBS)> in F<extralibs.ld> and F<$(PERL_SRC)/ext.libs>. + +=cut +sub static_lib_closures { + my ($self, $todir) = @_; + my @m = sprintf <<'MAKE_FRAG', $todir; + $(NOECHO) $(ECHO) "$(EXTRALIBS)" > %s$(DFSEP)extralibs.ld +MAKE_FRAG + # Old mechanism - still available: + push @m, <<'MAKE_FRAG' if $self->{PERL_SRC} && $self->{EXTRALIBS}; + $(NOECHO) $(ECHO) "$(EXTRALIBS)" >> $(PERL_SRC)$(DFSEP)ext.libs +MAKE_FRAG + @m; +} + +=item static_lib_fixtures + +Handles copying C<$(MYEXTLIB)> as starter for final static library that +then gets added to. + +=cut + +sub static_lib_fixtures { + my ($self) = @_; # If this extension has its own library (eg SDBM_File) # then copy that to $(INST_STATIC) and add $(OBJECT) into it. - push(@m, <<'MAKE_FRAG') if $self->{MYEXTLIB}; - $(CP) $(MYEXTLIB) "$@" -MAKE_FRAG + return unless $self->{MYEXTLIB}; + "\t\$(CP) \$(MYEXTLIB) \"\$\@\"\n"; +} + +=item static_lib_pure_cmd + +Defines how to run the archive utility. +=cut + +sub static_lib_pure_cmd { + my ($self, $from) = @_; my $ar; if (exists $self->{FULL_AR} && -x $self->{FULL_AR}) { # Prefer the absolute pathed ar if available so that PATH @@ -3369,18 +3521,10 @@ MAKE_FRAG } else { $ar = 'AR'; } - push @m, sprintf <<'MAKE_FRAG', $ar; - $(%s) $(AR_STATIC_ARGS) $@ $(OBJECT) && $(RANLIB) $@ - $(CHMOD) $(PERM_RWX) $@ - $(NOECHO) $(ECHO) "$(EXTRALIBS)" > "$(INST_ARCHAUTODIR)/extralibs.ld" + sprintf <<'MAKE_FRAG', $ar, $from; + $(%s) $(AR_STATIC_ARGS) "$@" %s + $(RANLIB) "$@" MAKE_FRAG - - # Old mechanism - still available: - push @m, <<'MAKE_FRAG' if $self->{PERL_SRC} && $self->{EXTRALIBS}; - $(NOECHO) $(ECHO) "$(EXTRALIBS)" >> "$(PERL_SRC)/ext.libs" -MAKE_FRAG - - join('', @m); } =item staticmake (o) @@ -3459,15 +3603,16 @@ sub subdirs { # subdirectories containing further Makefile.PL scripts. # It calls the subdir_x() method for each subdirectory. foreach my $dir (@{$self->{DIR}}){ - push(@m, $self->subdir_x($dir)); + push @m, $self->subdir_x($dir); #### print "Including $dir subdirectory\n"; } if (@m){ - unshift(@m, " + unshift @m, <<'EOF'; + # The default clean, realclean and test targets in this Makefile # have automatically been given entries for each subdir. -"); +EOF } else { push(@m, "\n# none") } @@ -3481,8 +3626,6 @@ Defines the test targets. =cut sub test { -# --- Test and Installation Sections --- - my($self, %attribs) = @_; my $tests = $attribs{TESTS} || ''; if (!$tests && -d 't' && defined $attribs{RECURSIVE_TEST_FILES}) { @@ -3494,8 +3637,9 @@ sub test { # have to do this because nmake is broken $tests =~ s!/!\\!g if $self->is_make_type('nmake'); # note: 'test.pl' name is also hardcoded in init_dirscan() - my(@m); - push(@m," + my @m; + my $default_testtype = $Config{usedl} ? 'dynamic' : 'static'; + push @m, <<EOF; TEST_VERBOSE=0 TEST_TYPE=test_\$(LINKTYPE) TEST_FILE = test.pl @@ -3503,56 +3647,59 @@ TEST_FILES = $tests TESTDB_SW = -d testdb :: testdb_\$(LINKTYPE) + \$(NOECHO) \$(NOOP) -test :: \$(TEST_TYPE) subdirs-test - -subdirs-test :: +test :: \$(TEST_TYPE) \$(NOECHO) \$(NOOP) -"); +# Occasionally we may face this degenerate target: +test_ : test_$default_testtype + \$(NOECHO) \$(NOOP) - foreach my $dir (@{ $self->{DIR} }) { - my $test = $self->cd($dir, '$(MAKE) test $(PASTHRU)'); +EOF - push @m, <<END -subdirs-test :: - \$(NOECHO) $test + for my $linktype (qw(dynamic static)) { + my $directdeps = "$linktype pure_all"; + push @m, "subdirs-test_$linktype :: $directdeps\n"; + foreach my $dir (@{ $self->{DIR} }) { + my $test = $self->cd($dir, "\$(MAKE) test_$linktype \$(PASTHRU)"); + push @m, "\t\$(NOECHO) $test\n"; + } + push @m, "\n"; + if ($tests or -f "test.pl") { + for my $testspec ([ '', '' ], [ 'db', ' $(TESTDB_SW)' ]) { + my ($db, $switch) = @$testspec; + my ($command, $deps); + # if testdb, build all but don't test all + $deps = $db eq 'db' ? $directdeps : "subdirs-test_$linktype"; + if ($linktype eq 'static' and $self->needs_linking) { + my $target = File::Spec->rel2abs('$(MAP_TARGET)'); + $command = qq{"$target" \$(MAP_PERLINC)}; + $deps .= ' $(MAP_TARGET)'; + } else { + $command = '$(FULLPERLRUN)' . $switch; + } + push @m, "test${db}_$linktype :: $deps\n"; + if ($db eq 'db') { + push @m, $self->test_via_script($command, '$(TEST_FILE)') + } else { + push @m, $self->test_via_script($command, '$(TEST_FILE)') + if -f "test.pl"; + push @m, $self->test_via_harness($command, '$(TEST_FILES)') + if $tests; + } + push @m, "\n"; + } + } else { + push @m, _sprintf562 <<'EOF', $linktype; +testdb_%1$s test_%1$s :: subdirs-test_%1$s + $(NOECHO) $(ECHO) 'No tests defined for $(NAME) extension.' -END +EOF + } } - push(@m, "\t\$(NOECHO) \$(ECHO) 'No tests defined for \$(NAME) extension.'\n") - unless $tests or -f "test.pl" or @{$self->{DIR}}; - push(@m, "\n"); - - push(@m, "test_dynamic :: pure_all\n"); - push(@m, $self->test_via_harness('$(FULLPERLRUN)', '$(TEST_FILES)')) - if $tests; - push(@m, $self->test_via_script('$(FULLPERLRUN)', '$(TEST_FILE)')) - if -f "test.pl"; - push(@m, "\n"); - - push(@m, "testdb_dynamic :: pure_all\n"); - push(@m, $self->test_via_script('$(FULLPERLRUN) $(TESTDB_SW)', - '$(TEST_FILE)')); - push(@m, "\n"); - - # Occasionally we may face this degenerate target: - push @m, "test_ : test_dynamic\n\n"; - - if ($self->needs_linking()) { - push(@m, "test_static :: pure_all \$(MAP_TARGET)\n"); - push(@m, $self->test_via_harness('./$(MAP_TARGET)', '$(TEST_FILES)')) if $tests; - push(@m, $self->test_via_script('./$(MAP_TARGET)', '$(TEST_FILE)')) if -f "test.pl"; - push(@m, "\n"); - push(@m, "testdb_static :: pure_all \$(MAP_TARGET)\n"); - push(@m, $self->test_via_script('./$(MAP_TARGET) $(TESTDB_SW)', '$(TEST_FILE)')); - push(@m, "\n"); - } else { - push @m, "test_static :: test_dynamic\n"; - push @m, "testdb_static :: testdb_dynamic\n"; - } - join("", @m); + join "", @m; } =item test_via_harness (override) @@ -3605,7 +3752,7 @@ sub tool_xsubpp { } die "ExtUtils::MM_Unix::tool_xsubpp : Can't find xsubpp" if !$foundxsubpp; - my $tmdir = File::Spec->catdir($self->{PERL_LIB},"ExtUtils"); + my $tmdir = $self->catdir($self->{PERL_LIB},"ExtUtils"); my(@tmdeps) = $self->catfile($tmdir,'typemap'); if( $self->{TYPEMAPS} ){ foreach my $typemap (@{$self->{TYPEMAPS}}){ @@ -3613,12 +3760,21 @@ sub tool_xsubpp { warn "Typemap $typemap not found.\n"; } else { - push(@tmdeps, $typemap); + $typemap = vmsify($typemap) if $Is{VMS}; + push(@tmdeps, $typemap); } } } push(@tmdeps, "typemap") if -f "typemap"; - my @tmargs = map(qq{-typemap "$_"}, @tmdeps); + # absolutised because with deep-located typemaps, eg "lib/XS/typemap", + # if xsubpp is called from top level with + # $(XSUBPP) ... -typemap "lib/XS/typemap" "lib/XS/Test.xs" + # it says: + # Can't find lib/XS/type map in (fulldir)/lib/XS + # because ExtUtils::ParseXS::process_file chdir's to .xs file's + # location. This is the only way to get all specified typemaps used, + # wherever located. + my @tmargs = map { '-typemap '.$self->quote_literal(File::Spec->rel2abs($_)) } @tmdeps; $_ = $self->quote_dep($_) for @tmdeps; if( exists $self->{XSOPT} ){ unshift( @tmargs, $self->{XSOPT} ); @@ -3679,19 +3835,21 @@ sub top_targets { push @m, $self->all_target, "\n" unless $self->{SKIPHASH}{'all'}; - push @m, ' + push @m, sprintf <<'EOF'; pure_all :: config pm_to_blib subdirs linkext $(NOECHO) $(NOOP) + $(NOECHO) $(NOOP) + subdirs :: $(MYEXTLIB) $(NOECHO) $(NOOP) config :: $(FIRST_MAKEFILE) blibdirs $(NOECHO) $(NOOP) -'; +EOF push @m, ' -$(O_FILES): $(H_FILES) +$(O_FILES) : $(H_FILES) ' if @{$self->{O_FILES} || []} && @{$self->{H} || []}; push @m, q{ @@ -3728,7 +3886,8 @@ sub xs_c { return '' unless $self->needs_linking(); ' .xs.c: - $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(XSUBPP_EXTRA_ARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.c + $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(XSUBPP_EXTRA_ARGS) $*.xs > $*.xsc + $(MV) $*.xsc $*.c '; } @@ -3743,27 +3902,73 @@ sub xs_cpp { return '' unless $self->needs_linking(); ' .xs.cpp: - $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.cpp + $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.xsc + $(MV) $*.xsc $*.cpp '; } =item xs_o (o) -Defines suffix rules to go from XS to object files directly. This is -only intended for broken make implementations. +Defines suffix rules to go from XS to object files directly. This was +originally only intended for broken make implementations, but is now +necessary for per-XS file under C<XSMULTI>, since each XS file might +have an individual C<$(VERSION)>. =cut -sub xs_o { # many makes are too dumb to use xs_c then c_o - my($self) = shift; +sub xs_o { + my ($self) = @_; return '' unless $self->needs_linking(); - ' -.xs$(OBJ_EXT): - $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.c - $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.c -'; + my $m_o = $self->{XSMULTI} ? $self->xs_obj_opt('$*$(OBJ_EXT)') : ''; + my $frag = ''; + # dmake makes noise about ambiguous rule + $frag .= sprintf <<'EOF', $m_o unless $self->is_make_type('dmake'); +.xs$(OBJ_EXT) : + $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.xsc + $(MV) $*.xsc $*.c + $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.c %s +EOF + if ($self->{XSMULTI}) { + for my $ext ($self->_xs_list_basenames) { + my $pmfile = "$ext.pm"; + croak "$ext.xs has no matching $pmfile: $!" unless -f $pmfile; + my $version = $self->parse_version($pmfile); + my $cccmd = $self->{CONST_CCCMD}; + $cccmd =~ s/^\s*CCCMD\s*=\s*//; + $cccmd =~ s/\$\(DEFINE_VERSION\)/-DVERSION=\\"$version\\"/; + $cccmd =~ s/\$\(XS_DEFINE_VERSION\)/-DXS_VERSION=\\"$version\\"/; + $self->_xsbuild_replace_macro($cccmd, 'xs', $ext, 'INC'); + my $define = '$(DEFINE)'; + $self->_xsbuild_replace_macro($define, 'xs', $ext, 'DEFINE'); + # 1 2 3 4 + $frag .= _sprintf562 <<'EOF', $ext, $cccmd, $m_o, $define; + +%1$s$(OBJ_EXT): %1$s.xs + $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.xsc + $(MV) $*.xsc $*.c + %2$s $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) %4$s $*.c %3$s +EOF + } + } + $frag; } +# param gets modified +sub _xsbuild_replace_macro { + my ($self, undef, $xstype, $ext, $varname) = @_; + my $value = $self->_xsbuild_value($xstype, $ext, $varname); + return unless defined $value; + $_[1] =~ s/\$\($varname\)/$value/; +} + +sub _xsbuild_value { + my ($self, $xstype, $ext, $varname) = @_; + return $self->{XSBUILD}{$xstype}{$ext}{$varname} + if $self->{XSBUILD}{$xstype}{$ext}{$varname}; + return $self->{XSBUILD}{$xstype}{all}{$varname} + if $self->{XSBUILD}{$xstype}{all}{$varname}; + (); +} 1; |