Invert the build logic for miniperlmain.c and ExtUtils::Miniperl
authorNicholas Clark <nick@ccl4.org>
Fri, 5 Jul 2013 21:16:12 +0000 (23:16 +0200)
committerNicholas Clark <nick@ccl4.org>
Sun, 7 Jul 2013 10:52:36 +0000 (12:52 +0200)
Now ExtUtils::Miniperl has the master version of {mini,}perlmain.c and is
checked into the repository. miniperlmain.c is now generated by a script
in regen/ which uses ExtUtils::Miniperl.

Tweak ExtUtils::Miniperl::writemain() to take an optional first argument,
a reference to a file handle. This permits the regen script to use the
regen_lib.pl functions for file opening/closing/renaming and TAP generation.

For now check in ExtUtils::Miniperl minimally modified from the version
generated by the former minimod.pl. The next commit will tidy it up.

MANIFEST
ext/ExtUtils-Miniperl/Makefile.PL [deleted file]
ext/ExtUtils-Miniperl/Miniperl_pm.PL [deleted file]
ext/ExtUtils-Miniperl/lib/ExtUtils/Miniperl.pm [new file with mode: 0644]
miniperlmain.c
regen/miniperlmain.pl [new file with mode: 0644]
t/porting/regen.t

index 26bd639..2ac0992 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -3567,8 +3567,7 @@ ext/Errno/ChangeLog       Errno changes
 ext/Errno/Errno_pm.PL  Errno perl module create script
 ext/Errno/Makefile.PL  Errno extension makefile writer
 ext/Errno/t/Errno.t    See if Errno works
-ext/ExtUtils-Miniperl/Makefile.PL      Runs Miniperl_pm.PL
-ext/ExtUtils-Miniperl/Miniperl_pm.PL   Writes ext/ExtUtils-Miniperl/Miniperl.pm
+ext/ExtUtils-Miniperl/lib/ExtUtils/Miniperl.pm Writes {mini,}perlmain.c
 ext/Fcntl/Fcntl.pm     Fcntl extension Perl module
 ext/Fcntl/Fcntl.xs     Fcntl extension external subroutines
 ext/Fcntl/Makefile.PL  Fcntl extension makefile writer
@@ -4757,6 +4756,7 @@ regen/feature.pl          Generates feature.pm
 regen/genpacksizetables.pl     Generate the size tables for pack/unpack
 regen/keywords.pl              Program to write keywords.h
 regen/mg_vtable.pl             generate mg_vtable.h
+regen/miniperlmain.pl          generate miniperlmain.c
 regen/mk_invlists.pl           Generates charclass_invlists.h
 regen/mk_PL_charclass.pl       Populate the PL_charclass table
 regen/opcode.pl                        Opcode header generator
diff --git a/ext/ExtUtils-Miniperl/Makefile.PL b/ext/ExtUtils-Miniperl/Makefile.PL
deleted file mode 100644 (file)
index 16c3ecb..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!perl -w
-
-# Blatantly copied from ext/Pod-Functions/Makefile.PL
-# If we think we want a third copy, then it's time to find a better way to do
-# this. (Note, we have no ABSTRACT_FROM here)
-# But for now, this replaces a bunch of platform specific special case code
-# in the Makefiles for *nix, Win32 and VMS with one unified implementation.
-# And in Perl, rather than 3+ different languages.
-
-use strict;
-use ExtUtils::MakeMaker;
-use File::Spec::Functions;
-
-WriteMakefile(NAME => 'ExtUtils::Miniperl',
-             VERSION_FROM => 'Miniperl_pm.PL',
-             LICENSE => 'perl',
-             PREREQ_PM => {},
-             AUTHOR => 'Perl 5 Porters <perlbug@perl.org>',
-             INSTALLDIRS => 'perl',
-             PL_FILES => {}, # Stop EU::MM defaulting this to run our PL
-             PM => {'Miniperl.pm' => '$(INST_LIBDIR)/Miniperl.pm'},
-             clean => {FILES => 'Miniperl.pm'},
-            );
-
-# There doesn't seem to be any way to get ExtUtils::MakeMaker to add a
-# dependency on another file (or target), and as it's using :: rules, not :
-# rules, then we can't simply add a one line dependency. So we need to provide
-# the entire thing. Fortunately, the same code in MM_Unix.pm is actually used
-# for all platforms, so this code below should also be portable:
-
-sub MY::postamble {
-    my $main = catfile(updir, updir, 'miniperlmain.c');
-    return <<"EOT";
-all :: Miniperl.pm
-       \$(NOECHO) \$(NOOP)
-
-Miniperl.pm :: Miniperl_pm.PL $main
-       \$(PERLRUN) Miniperl_pm.PL $main
-EOT
-}
diff --git a/ext/ExtUtils-Miniperl/Miniperl_pm.PL b/ext/ExtUtils-Miniperl/Miniperl_pm.PL
deleted file mode 100644 (file)
index a7de280..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-#./miniperl -w
-# minimod.pl writes the contents of miniperlmain.c into the module
-# ExtUtils::Miniperl for later perusal (when the perl source is
-# deleted)
-#
-# It also writes the subroutine writemain(), which takes as its
-# arguments module names that shall be statically linked into perl.
-#
-# Authors: Andreas Koenig <k@franz.ww.TU-Berlin.DE>, Tim Bunce
-#          <Tim.Bunce@ig.co.uk>
-#
-# Version 1.0, Feb 2nd 1995 by Andreas Koenig
-
-use strict;
-
-open STDOUT, '>Miniperl.pm'
-    or die "Can't open Miniperl.pm: $!";
-
-print <<'END';
-# This File keeps the contents of miniperlmain.c.
-#
-# It was generated automatically by minimod.PL from the contents
-# of miniperlmain.c. Don't edit this file!
-#
-#       ANY CHANGES MADE HERE WILL BE LOST! 
-#
-
-
-package ExtUtils::Miniperl;
-require Exporter;
-@ISA = qw(Exporter);
-@EXPORT = qw(&writemain);
-
-$head= <<'EOF!HEAD';
-END
-
-open MINI, shift;
-while (<MINI>) {
-    last if /Do not delete this line--writemain depends on it/;
-    print;
-    /#include "perl.h"/ and print qq/#include "XSUB.h"\n/;
-}
-
-print <<'END';
-EOF!HEAD
-$tail=<<'EOF!TAIL';
-END
-
-while (<MINI>) {
-    print unless /dXSUB_SYS/;
-}
-close MINI;
-
-print <<'END';
-EOF!TAIL
-
-sub writemain{
-    my(@exts) = @_;
-
-    my($pname);
-    my($dl) = canon('/','DynaLoader');
-    print $head;
-
-    foreach $_ (@exts){
-       my($pname) = canon('/', $_);
-       my($mname, $cname);
-       ($mname = $pname) =~ s!/!::!g;
-       ($cname = $pname) =~ s!/!__!g;
-        print "EXTERN_C void boot_${cname} (pTHX_ CV* cv);\n";
-    }
-
-    my ($tail1,$tail2,$tail3) = ( $tail =~ /\A(.*{\s*\n)(.*\n)(\s*\}.*)\Z/s );
-
-    print $tail1;
-    print "\tstatic const char file[] = __FILE__;\n";
-    print "\tdXSUB_SYS;\n" if $] > 5.002;
-    print $tail2;
-
-    foreach $_ (@exts){
-       my($pname) = canon('/', $_);
-       my($mname, $cname, $ccode);
-       ($mname = $pname) =~ s!/!::!g;
-       ($cname = $pname) =~ s!/!__!g;
-       print "\t{\n";
-       if ($pname eq $dl){
-           # Must NOT install 'DynaLoader::boot_DynaLoader' as 'bootstrap'!
-           # boot_DynaLoader is called directly in DynaLoader.pm
-           $ccode = "\t/* DynaLoader is a special case */\n
-\tnewXS(\"${mname}::boot_${cname}\", boot_${cname}, file);\n";
-           print $ccode unless $SEEN{$ccode}++;
-       } else {
-           $ccode = "\tnewXS(\"${mname}::bootstrap\", boot_${cname}, file);\n";
-           print $ccode unless $SEEN{$ccode}++;
-       }
-       print "\t}\n";
-    }
-    print $tail3;
-}
-
-sub canon{
-    my($as, @ext) = @_;
-       foreach(@ext){
-           # might be X::Y or lib/auto/X/Y/Y.a
-               next if s!::!/!g;
-           s:^(lib|ext)/(auto/)?::;
-           s:/\w+\.\w+$::;
-       }
-       grep(s:/:$as:, @ext) if ($as ne '/');
-       @ext;
-}
-
-1;
-__END__
-
-=head1 NAME
-
-ExtUtils::Miniperl, writemain - write the C code for perlmain.c
-
-=head1 SYNOPSIS
-
-C<use ExtUtils::Miniperl;>
-
-C<writemain(@directories);>
-
-=head1 DESCRIPTION
-
-This whole module is written when perl itself is built from a script
-called minimod.PL. In case you want to patch it, please patch
-minimod.PL in the perl distribution instead.
-
-writemain() takes an argument list of directories containing archive
-libraries that relate to perl modules and should be linked into a new
-perl binary. It writes to STDOUT a corresponding perlmain.c file that
-is a plain C file containing all the bootstrap code to make the
-modules associated with the libraries available from within perl.
-
-The typical usage is from within a Makefile generated by
-ExtUtils::MakeMaker. So under normal circumstances you won't have to
-deal with this module directly.
-
-=head1 SEE ALSO
-
-L<ExtUtils::MakeMaker>
-
-=cut
-
-END
diff --git a/ext/ExtUtils-Miniperl/lib/ExtUtils/Miniperl.pm b/ext/ExtUtils-Miniperl/lib/ExtUtils/Miniperl.pm
new file mode 100644 (file)
index 0000000..3a43094
--- /dev/null
@@ -0,0 +1,285 @@
+# This File keeps the contents of miniperlmain.c.
+#
+# It was generated automatically by minimod.PL from the contents
+# of miniperlmain.c. Don't edit this file!
+#
+#       ANY CHANGES MADE HERE WILL BE LOST! 
+#
+
+
+package ExtUtils::Miniperl;
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(&writemain);
+
+$head= <<'EOF!HEAD';
+/*    miniperlmain.c
+ *
+ *    Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003,
+ *    2004, 2005, 2006, 2007, by Larry Wall and others
+ *
+ *    You may distribute under the terms of either the GNU General Public
+ *    License or the Artistic License, as specified in the README file.
+ *
+ */
+
+/*
+ *      The Road goes ever on and on
+ *          Down from the door where it began.
+ *
+ *     [Bilbo on p.35 of _The Lord of the Rings_, I/i: "A Long-Expected Party"]
+ *     [Frodo on p.73 of _The Lord of the Rings_, I/iii: "Three Is Company"]
+ */
+
+/* This file contains the main() function for the perl interpreter.
+ * Note that miniperlmain.c contains main() for the 'miniperl' binary,
+ * while perlmain.c contains main() for the 'perl' binary.
+ *
+ * Miniperl is like perl except that it does not support dynamic loading,
+ * and in fact is used to build the dynamic modules needed for the 'real'
+ * perl executable.
+ */
+
+#ifdef OEMVS
+#ifdef MYMALLOC
+/* sbrk is limited to first heap segment so make it big */
+#pragma runopts(HEAP(8M,500K,ANYWHERE,KEEP,8K,4K) STACK(,,ANY,) ALL31(ON))
+#else
+#pragma runopts(HEAP(2M,500K,ANYWHERE,KEEP,8K,4K) STACK(,,ANY,) ALL31(ON))
+#endif
+#endif
+
+
+#include "EXTERN.h"
+#define PERL_IN_MINIPERLMAIN_C
+#include "perl.h"
+#include "XSUB.h"
+
+static void xs_init (pTHX);
+static PerlInterpreter *my_perl;
+
+#if defined(PERL_GLOBAL_STRUCT_PRIVATE)
+/* The static struct perl_vars* may seem counterproductive since the
+ * whole idea PERL_GLOBAL_STRUCT_PRIVATE was to avoid statics, but note
+ * that this static is not in the shared perl library, the globals PL_Vars
+ * and PL_VarsPtr will stay away. */
+static struct perl_vars* my_plvarsp;
+struct perl_vars* Perl_GetVarsPrivate(void) { return my_plvarsp; }
+#endif
+
+#ifdef NO_ENV_ARRAY_IN_MAIN
+extern char **environ;
+int
+main(int argc, char **argv)
+#else
+int
+main(int argc, char **argv, char **env)
+#endif
+{
+    dVAR;
+    int exitstatus, i;
+#ifdef PERL_GLOBAL_STRUCT
+    struct perl_vars *plvarsp = init_global_struct();
+#  ifdef PERL_GLOBAL_STRUCT_PRIVATE
+    my_vars = my_plvarsp = plvarsp;
+#  endif
+#endif /* PERL_GLOBAL_STRUCT */
+#ifndef NO_ENV_ARRAY_IN_MAIN
+    PERL_UNUSED_ARG(env);
+#endif
+#ifndef PERL_USE_SAFE_PUTENV
+    PL_use_safe_putenv = FALSE;
+#endif /* PERL_USE_SAFE_PUTENV */
+
+    /* if user wants control of gprof profiling off by default */
+    /* noop unless Configure is given -Accflags=-DPERL_GPROF_CONTROL */
+    PERL_GPROF_MONCONTROL(0);
+
+#ifdef NO_ENV_ARRAY_IN_MAIN
+    PERL_SYS_INIT3(&argc,&argv,&environ);
+#else
+    PERL_SYS_INIT3(&argc,&argv,&env);
+#endif
+
+#if defined(USE_ITHREADS)
+    /* XXX Ideally, this should really be happening in perl_alloc() or
+     * perl_construct() to keep libperl.a transparently fork()-safe.
+     * It is currently done here only because Apache/mod_perl have
+     * problems due to lack of a call to cancel pthread_atfork()
+     * handlers when shared objects that contain the handlers may
+     * be dlclose()d.  This forces applications that embed perl to
+     * call PTHREAD_ATFORK() explicitly, but if and only if it hasn't
+     * been called at least once before in the current process.
+     * --GSAR 2001-07-20 */
+    PTHREAD_ATFORK(Perl_atfork_lock,
+                   Perl_atfork_unlock,
+                   Perl_atfork_unlock);
+#endif
+
+    if (!PL_do_undump) {
+       my_perl = perl_alloc();
+       if (!my_perl)
+           exit(1);
+       perl_construct(my_perl);
+       PL_perl_destruct_level = 0;
+    }
+    PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
+    exitstatus = perl_parse(my_perl, xs_init, argc, argv, (char **)NULL);
+    if (!exitstatus)
+        perl_run(my_perl);
+
+#ifndef PERL_MICRO
+    /* Unregister our signal handler before destroying my_perl */
+    for (i = 1; PL_sig_name[i]; i++) {
+       if (rsignal_state(PL_sig_num[i]) == (Sighandler_t) PL_csighandlerp) {
+           rsignal(PL_sig_num[i], (Sighandler_t) SIG_DFL);
+       }
+    }
+#endif
+
+    exitstatus = perl_destruct(my_perl);
+
+    perl_free(my_perl);
+
+#if defined(USE_ENVIRON_ARRAY) && defined(PERL_TRACK_MEMPOOL) && !defined(NO_ENV_ARRAY_IN_MAIN)
+    /*
+     * The old environment may have been freed by perl_free()
+     * when PERL_TRACK_MEMPOOL is defined, but without having
+     * been restored by perl_destruct() before (this is only
+     * done if destruct_level > 0).
+     *
+     * It is important to have a valid environment for atexit()
+     * routines that are eventually called.
+     */
+    environ = env;
+#endif
+
+    PERL_SYS_TERM();
+
+#ifdef PERL_GLOBAL_STRUCT
+    free_global_struct(plvarsp);
+#endif /* PERL_GLOBAL_STRUCT */
+
+    exit(exitstatus);
+    return exitstatus;
+}
+
+/* Register any extra external extensions */
+
+EOF!HEAD
+$tail=<<'EOF!TAIL';
+
+static void
+xs_init(pTHX)
+{
+    PERL_UNUSED_CONTEXT;
+}
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set ts=8 sts=4 sw=4 et:
+ */
+EOF!TAIL
+
+sub writemain{
+    my $old_fh;
+    if (ref $_[0]) {
+        $old_fh = select shift;
+    }
+    my(@exts) = @_;
+
+    my($pname);
+    my($dl) = canon('/','DynaLoader');
+    print $head;
+
+    foreach $_ (@exts){
+       my($pname) = canon('/', $_);
+       my($mname, $cname);
+       ($mname = $pname) =~ s!/!::!g;
+       ($cname = $pname) =~ s!/!__!g;
+        print "EXTERN_C void boot_${cname} (pTHX_ CV* cv);\n";
+    }
+
+    my ($tail1,$tail2,$tail3) = ( $tail =~ /\A(.*{\s*\n)(.*\n)(\s*\}.*)\Z/s );
+
+    print $tail1;
+    print "\tstatic const char file[] = __FILE__;\n"
+        if @exts;
+    print "\tdXSUB_SYS;\n" if $] > 5.002;
+    print $tail2;
+
+    foreach $_ (@exts){
+       my($pname) = canon('/', $_);
+       my($mname, $cname, $ccode);
+       ($mname = $pname) =~ s!/!::!g;
+       ($cname = $pname) =~ s!/!__!g;
+       print "\t{\n";
+       if ($pname eq $dl){
+           # Must NOT install 'DynaLoader::boot_DynaLoader' as 'bootstrap'!
+           # boot_DynaLoader is called directly in DynaLoader.pm
+           $ccode = "\t/* DynaLoader is a special case */\n
+\tnewXS(\"${mname}::boot_${cname}\", boot_${cname}, file);\n";
+           print $ccode unless $SEEN{$ccode}++;
+       } else {
+           $ccode = "\tnewXS(\"${mname}::bootstrap\", boot_${cname}, file);\n";
+           print $ccode unless $SEEN{$ccode}++;
+       }
+       print "\t}\n";
+    }
+    print $tail3;
+    select $old_fh
+        if $fh;
+}
+
+sub canon{
+    my($as, @ext) = @_;
+       foreach(@ext){
+           # might be X::Y or lib/auto/X/Y/Y.a
+               next if s!::!/!g;
+           s:^(lib|ext)/(auto/)?::;
+           s:/\w+\.\w+$::;
+       }
+       grep(s:/:$as:, @ext) if ($as ne '/');
+       @ext;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+ExtUtils::Miniperl, writemain - write the C code for perlmain.c
+
+=head1 SYNOPSIS
+
+C<use ExtUtils::Miniperl;>
+
+C<writemain(@directories);>
+
+=head1 DESCRIPTION
+
+This whole module is written when perl itself is built from a script
+called minimod.PL. In case you want to patch it, please patch
+minimod.PL in the perl distribution instead.
+
+writemain() takes an argument list of directories containing archive
+libraries that relate to perl modules and should be linked into a new
+perl binary. It writes to STDOUT a corresponding perlmain.c file that
+is a plain C file containing all the bootstrap code to make the
+modules associated with the libraries available from within perl.
+
+The typical usage is from within a Makefile generated by
+ExtUtils::MakeMaker. So under normal circumstances you won't have to
+deal with this module directly.
+
+=head1 SEE ALSO
+
+L<ExtUtils::MakeMaker>
+
+=cut
+
index 61358f7..3a06f72 100644 (file)
@@ -38,6 +38,7 @@
 #include "EXTERN.h"
 #define PERL_IN_MINIPERLMAIN_C
 #include "perl.h"
+#include "XSUB.h"
 
 static void xs_init (pTHX);
 static PerlInterpreter *my_perl;
@@ -150,13 +151,12 @@ main(int argc, char **argv, char **env)
 
 /* Register any extra external extensions */
 
-/* Do not delete this line--writemain depends on it */
 
 static void
 xs_init(pTHX)
 {
+       dXSUB_SYS;
     PERL_UNUSED_CONTEXT;
-    dXSUB_SYS;
 }
 
 /*
diff --git a/regen/miniperlmain.pl b/regen/miniperlmain.pl
new file mode 100644 (file)
index 0000000..205c583
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/perl
+
+use strict;
+
+BEGIN {
+    # Get function prototypes
+    require 'regen/regen_lib.pl';
+    unshift @INC, 'ext/ExtUtils-Miniperl/lib';
+}
+
+use ExtUtils::Miniperl;
+
+my $fh = open_new('miniperlmain.c');
+writemain($fh);
+close_and_rename($fh);
index 194f80e..78fd64f 100644 (file)
@@ -19,7 +19,8 @@ if ( $^O eq "VMS" ) {
 my $in_regen_pl = 24; # I can't see a clean way to calculate this automatically.
 my @files = qw(perly.act perly.h perly.tab keywords.c keywords.h uconfig.h);
 my @progs = qw(regen/regcharclass.pl regen/mk_PL_charclass.pl
-               regen/unicode_constants.pl regen/genpacksizetables.pl);
+               regen/unicode_constants.pl regen/genpacksizetables.pl
+               regen/miniperlmain.pl);
 
 plan (tests => $in_regen_pl + @files + @progs + 2);