enable statically linked extensions for Win32
Vadim Konovalov [Mon, 11 Oct 2004 22:57:00 +0000 (02:57 +0400)]
Message-ID: <80173417046.20041011225700@vkonovalov.ru>

p4raw-id: //depot/perl@23360

makedef.pl
win32/Makefile
win32/buildext.pl
win32/dl_win32.xs
win32/makefile.mk
win32/perllib.c
win32/sync_ext.pl

index 774c714..7da0575 100644 (file)
@@ -55,6 +55,7 @@ my $global_sym  = "global.sym";
 my $pp_sym      = "pp.sym";
 my $globvar_sym = "globvar.sym";
 my $perlio_sym  = "perlio.sym";
+my $static_ext = "";
 
 if ($PLATFORM eq 'aix') {
     # Nothing for now.
@@ -88,6 +89,13 @@ unless ($PLATFORM eq 'win32' || $PLATFORM eq 'wince' || $PLATFORM eq 'MacOS' ||
     }
     close(CFG);
 }
+if ($PLATFORM eq 'win32' || $PLATFORM eq 'wince') {
+    open(CFG,"<..\\$config_sh") || die "Cannot open ..\\$config_sh: $!\n";
+    if ((join '', <CFG>) =~ /^static_ext='(.*)'$/m) {
+        $static_ext = $1;
+    }
+    close(CFG);
+}
 
 open(CFG,$config_h) || die "Cannot open $config_h: $!\n";
 while (<CFG>) {
@@ -1345,6 +1353,15 @@ foreach my $symbol (qw(
     }
 }
 
+# records of type boot_module for statically linked modules (except Dynaloader)
+$static_ext =~ s/\//__/g;
+$static_ext =~ s/\bDynaLoader\b//;
+my @stat_mods = map {"boot_$_"} grep {/\S/} split /\s+/, $static_ext;
+foreach my $symbol (@stat_mods)
+    {
+       try_symbol($symbol);
+    }
+
 # Now all symbols should be defined because
 # next we are going to output them.
 
index ccdbca0..ae2ed4c 100644 (file)
@@ -816,6 +816,7 @@ CFG_VARS    =                                       \
                "libpth=$(CCLIBDIR:"=\");$(EXTRALIBDIRS:"=\")"  \
                "libc=$(LIBC)"                          \
                "make=$(MAKE_BARE)"                             \
+               "static_ext=$(STATIC_EXT)"              \
                "usethreads=$(USE_ITHREADS)"            \
                "useithreads=$(USE_ITHREADS)"           \
                "usemultiplicity=$(USE_MULTI)"          \
index 65b79be..50fe4c1 100644 (file)
@@ -4,7 +4,7 @@ buildext.pl - build extensions
 
 =head1 SYNOPSIS
 
-    buildext.pl make [-make_opts] dep directory [target] !ext1 !ext2
+    buildext.pl make [-make_opts] dep directory [target] [--static|--dynamic] !ext1 !ext2
 
 E.g.
 
@@ -19,16 +19,52 @@ E.g.
 Will skip building extensions which are marked with an '!' char.
 Mostly because they still not ported to specified platform.
 
+If '--static' specified, only static extensions will be built.
+If '--dynamic' specified, only dynamic extensions will be built.
+
+--create-perllibst-h
+    creates perllibst.h file for inclusion from perllib.c
+--list-static-libs:
+    prints libraries for static linking and exits
+
 =cut
 
 use File::Basename;
 use Cwd;
 use FindExt;
+use Config;
 
 # @ARGV with '!' at first position are exclusions
 my %excl = map {$_=>1} map {/^!(.*)$/} @ARGV;
 @ARGV = grep {!/^!/} @ARGV;
 
+# --static/--dynamic
+my %opts = map {$_=>1} map {/^--([\w\-]+)$/} @ARGV;
+@ARGV = grep {!/^--([\w\-]+)$/} @ARGV;
+my ($static,$dynamic) = ((exists $opts{static}?1:0),(exists $opts{dynamic}?1:0));
+if ("$static,$dynamic" eq "0,0") {
+  ($static,$dynamic) = (1,1);
+}
+if ($opts{'list-static-libs'} || $opts{'create-perllibst-h'}) {
+  my @statics = grep{!/^DynaLoader$/} split /\s+/, $Config{static_ext};
+  if ($opts{'create-perllibst-h'}) {
+    # at moment of creation of perllibst.h no luck consulting Config.pm,
+    # so list of static extensions passed with @ARGV
+    @statics = grep{!/^DynaLoader$/} @ARGV;
+    open my $fh, ">perllibst.h";
+    my @statics1 = map {local $_=$_;s/\//__/g;$_} @statics;
+    my @statics2 = map {local $_=$_;s/\//::/g;$_} @statics;
+    print $fh "/*DO NOT EDIT\n  this file is included from perllib.c to init static extensions */\n";
+    print $fh "#ifdef STATIC1\n",(map {"    \"$_\",\n"} @statics),"#undef STATIC1\n#endif\n";
+    print $fh "#ifdef STATIC2\n",(map {"    EXTERN_C void boot_$_ (pTHX_ CV* cv);\n"} @statics1),"#undef STATIC2\n#endif\n";
+    print $fh "#ifdef STATIC3\n",(map {"    newXS(\"$statics2[$_]::bootstrap\", boot_$statics1[$_], file);\n"} 0 .. $#statics),"#undef STATIC3\n#endif\n";
+  }
+  else {
+    print map {/([^\/]+)$/;"$_/$1.lib "} @statics;
+  }
+  exit;
+}
+
 my $here = getcwd();
 my $perl = $^X;
 $here =~ s,/,\\,g;
@@ -58,8 +94,12 @@ my $code;
 FindExt::scan_ext($ext);
 
 my @ext = FindExt::extensions();
+my %static_exts = map {$_=>1} split /\s+/, $Config{static_ext};
+
+if ("$static$dynamic" eq "01") {@ext = grep {!exists $static_exts{$_}} @ext}
+elsif ("$static$dynamic" eq "10") {@ext = grep {exists $static_exts{$_}} @ext}
 
-foreach my $dir (sort @ext)
+foreach $dir (sort @ext)
  {
   if (exists $excl{$dir}) {
     warn "Skipping extension $ext\\$dir, not ported to current platform";
@@ -72,13 +112,15 @@ foreach my $dir (sort @ext)
      {
       print "\nRunning Makefile.PL in $dir\n";
       my @perl = ($perl, "-I$here\\..\\lib", 'Makefile.PL',
-                  'INSTALLDIRS=perl', 'PERL_CORE=1');
+                  'INSTALLDIRS=perl', 'PERL_CORE=1',
+                 ($static_exts{$dir}?('LINKTYPE=static'):()), # if ext is static
+               );
       if (defined $::Cross::platform) {
        @perl = (@perl[0,1],"-MCross=$::Cross::platform",@perl[2..$#perl]);
       }
       print join(' ', @perl), "\n";
       $code = system(@perl);
-      warn "$code from $dir's Makefile.PL" if $code;
+      warn "$code from $dir\'s Makefile.PL" if $code;
       $mmod = -M 'Makefile';
       if ($mmod > $dmod)
        {
index 69910dd..4ff00a1 100644 (file)
@@ -68,7 +68,7 @@ static int
 dl_static_linked(char *filename)
 {
     char **p;
-    char* ptr;
+    char *ptr, *hptr;
     static char subStr[] = "/auto/";
     char szBuffer[MAX_PATH];
 
@@ -90,7 +90,14 @@ dl_static_linked(char *filename)
        ptr = szBuffer;
 
     for (p = staticlinkmodules; *p;p++) {
-       if (strstr(ptr, *p)) return 1;
+       if (hptr = strstr(ptr, *p)) {
+           /* found substring, need more detailed check if module name match */
+           if (hptr==ptr) {
+               return strcmp(ptr, *p)==0;
+           }
+           if (hptr[strlen(*p)] == 0)
+               return hptr[-1]=='/';
+       }
     };
     return 0;
 }
index bcb5e98..e030f2b 100644 (file)
@@ -992,9 +992,9 @@ $(MINIWIN32_OBJ) : $(CORE_NOCFG_H)
 
 perllib$(o)    : perllib.c .\perlhost.h .\vdir.h .\vmem.h
 .IF "$(USE_IMP_SYS)" == "define"
-       $(CC) -c -I. $(CFLAGS_O) $(CXX_FLAG) $(OBJOUT_FLAG)$@ perllib.c
+       $(CC) -c -I. -DWITH_STATIC $(CFLAGS_O) $(CXX_FLAG) $(OBJOUT_FLAG)$@ perllib.c
 .ELSE
-       $(CC) -c -I. $(CFLAGS_O) $(OBJOUT_FLAG)$@ perllib.c
+       $(CC) -c -I. -DWITH_STATIC $(CFLAGS_O) $(OBJOUT_FLAG)$@ perllib.c
 .ENDIF
 
 # 1. we don't want to rebuild miniperl.exe when config.h changes
@@ -1010,10 +1010,11 @@ $(DLL_OBJ)      : $(CORE_H)
 $(X2P_OBJ)     : $(CORE_H)
 
 perldll.def : $(MINIPERL) $(CONFIGPM) ..\global.sym ..\pp.sym ..\makedef.pl
+       $(MINIPERL) -I..\lib buildext.pl --create-perllibst-h $(STATIC_EXT)
        $(MINIPERL) -w ..\makedef.pl PLATFORM=win32 $(OPTIMIZE) $(DEFINES) \
        $(BUILDOPT) CCTYPE=$(CCTYPE) > perldll.def
 
-$(PERLDLL): perldll.def $(PERLDLL_OBJ) $(PERLDLL_RES)
+$(PERLDLL): perldll.def $(PERLDLL_OBJ) $(PERLDLL_RES) Extensions_static
 .IF "$(CCTYPE)" == "BORLAND"
        $(LINK32) -Tpd -ap $(BLINK_FLAGS) \
            @$(mktmp c0d32$(o) $(PERLDLL_OBJ:s,\,\\)\n \
@@ -1034,11 +1035,14 @@ $(PERLDLL): perldll.def $(PERLDLL_OBJ) $(PERLDLL_RES)
                perl.exp $(LKPOST))
 .ELSE
        $(LINK32) -dll -def:perldll.def -out:$@ \
-           @$(mktmp -base:0x28000000 $(BLINK_FLAGS) $(DELAYLOAD) $(LIBFILES) \
-               $(PERLDLL_RES) $(PERLDLL_OBJ:s,\,\\))
+           -base:0x28000000 $(BLINK_FLAGS) $(DELAYLOAD) $(LIBFILES) \
+           $(foreach,i,$(shell $(MINIPERL) -I..\lib buildext.pl $(MAKE) $(PERLDEP) ext --list-static-libs) \
+           ..\lib\auto\$i) \
+               $(PERLDLL_RES) $(PERLDLL_OBJ:s,\,\\)
 .ENDIF
        $(XCOPY) $(PERLIMPLIB) $(COREDIR)
 
+
 $(PERLEXE_ICO): $(MINIPERL) makeico.pl
        $(MINIPERL) makeico.pl > $@
 
@@ -1114,8 +1118,12 @@ $(EXTDIR)\DynaLoader\dl_win32.xs: dl_win32.xs
 
 #----------------------------------------------------------------------------------
 Extensions : buildext.pl $(PERLDEP) $(CONFIGPM)
-       $(MINIPERL) -I..\lib buildext.pl $(MAKE) $(PERLDEP) $(EXTDIR)
-       $(MINIPERL) -I..\lib buildext.pl $(MAKE) $(PERLDEP) ext
+       $(MINIPERL) -I..\lib buildext.pl $(MAKE) $(PERLDEP) $(EXTDIR) --dynamic
+       $(MINIPERL) -I..\lib buildext.pl $(MAKE) $(PERLDEP) ext --dynamic
+
+Extensions_static : buildext.pl $(PERLDEP) $(CONFIGPM)
+       $(MINIPERL) -I..\lib buildext.pl $(MAKE) $(PERLDEP) ext --static
+       $(MINIPERL) -I..\lib buildext.pl $(MAKE) $(PERLDEP) $(EXTDIR) --static
 
 # Note: The next two targets explicitly remove a "blibdirs.exists" file that
 # currerntly gets left behind, until CPAN RT Ticket #5616 is resolved.
@@ -1258,6 +1266,7 @@ distclean: realclean
        -del /f ..\config.sh ..\splittree.pl perlmain.c dlutils.c config.h.new
        -del /f $(CONFIGPM)
        -del /f bin\*.bat
+       -del /f perllibst.h
        -del /f $(PERLEXE_ICO) perl.base
        -cd .. && del /s *$(a) *.map *.pdb *.ilk *.bs *$(o) .exists pm_to_blib
        -cd $(EXTDIR) && del /s *.def Makefile Makefile.old
index f38dfa1..5bd7ee8 100644 (file)
 /* Register any extra external extensions */
 char *staticlinkmodules[] = {
     "DynaLoader",
+    /* other similar records will be included from "perllibst.h" */
+#ifdef WITH_STATIC
+#define STATIC1
+#include "perllibst.h"
+#endif
     NULL,
 };
 
 EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
+/* other similar records will be included from "perllibst.h" */
+#ifdef WITH_STATIC
+#define STATIC2
+#include "perllibst.h"
+#endif
 
 static void
 xs_init(pTHX)
@@ -27,6 +37,11 @@ xs_init(pTHX)
     char *file = __FILE__;
     dXSUB_SYS;
     newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
+    /* other similar records will be included from "perllibst.h" */
+#ifdef WITH_STATIC
+#define STATIC3
+#include "perllibst.h"
+#endif
 }
 
 #ifdef PERL_IMPLICIT_SYS
index e482b69..c0ef13b 100644 (file)
@@ -2,6 +2,13 @@
 
 Synchronize filename cases for extensions.
 
+This script could be used to perform following renaming:
+if there exist file, for example, "FiLeNaME.c" and
+filename.obj then it renames "filename.obj" to "FiLeNaME.obj".
+There is a problem when some compilers (e.g.Borland) generate
+such .obj files and then "make" process will not treat them
+as dependant and already maked files.
+
 This script takes two arguments - first and second extensions to
 synchronize filename cases with.