This is a live mirror of the Perl 5 development currently hosted at
fix win32 with GCC 3.4.5 build
authorDaniel Dragan <>
Fri, 6 Apr 2018 22:41:22 +0000 (18:41 -0400)
committerSteve Hay <>
Thu, 12 Apr 2018 16:58:27 +0000 (17:58 +0100)
dlltool from Strawberry 5.12 and
dlltool 2.17.50 20060824 from Strawberry 5.8.9 were making a libperl527.a
that caused perl.exe and all XS DLLs to import "perl527.exp.dll" while
the disk file is called perl527.dll.

This bug was eventually fixed, since in my testing dlltool 2.25 no date
code, Copyright 2014 from Strawberry 5.22.1 doesn't have this problem. I
suspect the bug was fixed in binutils commit 04276a0cf5
"2010-12-01 Kai Tietz <>"
in version "AM_INIT_AUTOMAKE(bfd, 2.21.51)" or 1 ver bump higher. Just
always pass an explicit DLL name to dlltool instead of any kind of
dlltool version checking at build time and then optional arg.

The breakage for 3.4.5 was introduced in
commit bf543eaf90d "add parallelness to win32/GNUmakefile" where I added
parallelness by making the import lib .a file from just perldll.def,
rather than the import lib being a build product coming out of g++
linking perl527.dll. The old serial build recipie passed --dllname
to dlltool, my newer code didn't.

Passing $(PERLDLL) to dlltool's -D causes this harmless but scary warning

"dlltool: Path components stripped from dllname, '..\perl527.dll'."

So create PERLDLLBASE to silence the warning.

win32.h: In old GCCs, a function marked
declspec(dllimport) is not a constant. VC from day 1, and newer GCCs use
the address of a 1 instruction jump stub function if a constant function
pointer is needed to a function from a DLL that wont be known till runtime.
This can be worked around in older GCCs by deoptimizing them to always
use the jump stub for all references, and not the newer GCC and VC way
where x86 call instructions directly read the import table in the caller,
while constant functions ptrs in data or vars always refer to the jump
stubs. Since these are old GCCs, performance isn't the highest priority
and building at all is a more important goal. I suspect gcc 3.4.5 has
been broken since 5.13.6 when the declspec(dllimport) code was added.


index ac4632b..82bf593 100644 (file)
@@ -963,6 +963,7 @@ PERLIMPLIBBASE      ?= perl527$(a)
 PERLEXPLIB     ?= $(COREDIR)\perl527.exp
 PERLSTATICLIB  ?= ..\perl527s$(a)
 PERLDLL                = ..\perl527.dll
+PERLDLLBASE    = perl527.dll
 # don't let "gmake -n all" try to run "miniperl.exe"
 PLMAKE         = gmake
@@ -1478,7 +1479,7 @@ $(PERLEXPLIB) : $(PERLIMPLIB)
 $(PERLIMPLIB) : perldll.def
 ifeq ($(CCTYPE),GCC)
-       $(IMPLIB) -k -d perldll.def -l $(PERLIMPLIB) -e $(PERLEXPLIB)
+       $(IMPLIB) -k -d perldll.def -D $(PERLDLLBASE) -l $(PERLIMPLIB) -e $(PERLEXPLIB)
        lib -def:perldll.def -machine:$(ARCHITECTURE) /OUT:$(PERLIMPLIB)
index 57563c4..265e93b 100644 (file)
@@ -937,6 +937,7 @@ PERLIMPLIB  *= $(COREDIR)\perl527$(a)
 PERLEXPLIB     *= $(COREDIR)\perl527.exp
 PERLSTATICLIB  *= ..\perl527s$(a)
 PERLDLL                = ..\perl527.dll
+PERLDLLBASE    = perl527.dll
 #EUMM on Win32 isn't ready for parallel make, so only allow this file to be parallel
 #$(MAKE) will contain the -P that this makefile was called with, which is bad for
@@ -1427,7 +1428,7 @@ perldll.def : $(HAVEMINIPERL) $(CONFIGPM) ..\embed.fnc ..\
 .IF "$(CCTYPE)" == "GCC"
-       $(IMPLIB) -k -d perldll.def -l $(PERLIMPLIB) -e $(PERLEXPLIB)
+       $(IMPLIB) -k -d perldll.def -D $(PERLDLLBASE) -l $(PERLIMPLIB) -e $(PERLEXPLIB)
 .ELSE #VC family
        lib -def:perldll.def -machine:$(ARCHITECTURE) /OUT:$(PERLIMPLIB)
index cdfadfe..29621c0 100644 (file)
  * The XS code in the re extension is special, in that it redefines
  * core APIs locally, so don't mark them as "dllimport" because GCC
  * cannot handle this situation.
+ *
+ * Certain old GCCs will not allow the function pointer of dllimport marked
+ * function to be "const". This was fixed later on. Since this is a
+ * deoptimization, target "gcc version 3.4.5 (mingw-vista special r3)" only,
+ * The GCC bug was fixed in GCC patch "varasm.c (initializer_constant_valid_p):
+ * Don't deny DECL_DLLIMPORT_P on functions", which probably was first released
+ * in GCC 4.3.0, this #if can be expanded upto but not including 4.3.0 if more
+ * deployed GCC are found that wont build with the follow error, initializer
+ * element is a PerlIO func exported from perl5xx.dll.
+ *
+ * encoding.xs:610: error: initializer element is not constant
+ * encoding.xs:610: error: (near initialization for `PerlIO_encode.Open')
-#if !defined(PERLDLL) && !defined(PERL_EXT_RE_BUILD)
-#  ifdef __cplusplus
-#    define PERL_CALLCONV extern "C" __declspec(dllimport)
-#    ifdef _MSC_VER
-#      define PERL_CALLCONV_NO_RET extern "C" __declspec(dllimport) __declspec(noreturn)
+#if (defined(__GNUC__) && defined(__MINGW32__) && \
+     !defined(__MINGW64_VERSION_MAJOR) && !defined(__clang__) && \
+       ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ <= 5))))
+/* use default fallbacks from perl.h for this particular GCC */
+#  if !defined(PERLDLL) && !defined(PERL_EXT_RE_BUILD)
+#    ifdef __cplusplus
+#      define PERL_CALLCONV extern "C" __declspec(dllimport)
+#      ifdef _MSC_VER
+#        define PERL_CALLCONV_NO_RET extern "C" __declspec(dllimport) __declspec(noreturn)
+#      endif
+#    else
+#      define PERL_CALLCONV __declspec(dllimport)
+#      ifdef _MSC_VER
+#        define PERL_CALLCONV_NO_RET __declspec(dllimport) __declspec(noreturn)
+#      endif
 #    endif
-#  else
-#    define PERL_CALLCONV __declspec(dllimport)
+#  else /* MSVC noreturn support inside the interp */
 #    ifdef _MSC_VER
-#      define PERL_CALLCONV_NO_RET __declspec(dllimport) __declspec(noreturn)
+#      define PERL_CALLCONV_NO_RET __declspec(noreturn)
 #    endif
 #  endif
-#else /* MSVC noreturn support inside the interp */
-#  ifdef _MSC_VER
-#    define PERL_CALLCONV_NO_RET __declspec(noreturn)
-#  endif
 #ifdef _MSC_VER