StrawberryPerl/Perl-Dist-Strawberry

Perl 5.38.2.1-32bit does not find _mkgmtime32

Opened this issue · 9 comments

I downloaded the portable version from GitHub "Assets" for a quick test.

On calling portableshell.bat, the "welcome lines" output by echo command appear on the screen.
But then an error window pops up with the text "The procedure entry point _mkgmtime32 could not be located in the dynamic link library msvcrt.dll".

Tested on a WinXP machine with all patches up to EOL.
The msvcrt.dll in C:\WINDOWS\system32 is from 2008-4-14 14:00. Version number is 7.0.2600.5512.

As remedy I tried a newer version of msvcrt.dll (7.0.18362.1).
As WFP does not allow exchange of a dll in \system32, I put this new dll into the directory of "perl.exe". But still the same error message pops up.

As I can run all .msi and portable versions from 5.14 through 5.32 (including Win32:UTCFileTime) on the WinXP machine, there must have been some incompatible change.
Any ideas of the reason or for a fix?

And I want to express my thanks to all caring for the 32-bit versions of Strawberry Perl.

Regards
Wolf

genio commented

Hi Wolf,

Oof. Let me first list some older discussions on the topic of Windows XP (or, rather, Windows version support in general). While these don't describe your problem, they do provide some background information for you.

Perl/perl5@4695dc7
Perl/perl5#18243
Perl/perl5#18521
https://www.nntp.perl.org/group/perl.perl5.porters/2020/10/msg258453.html

I don't think this issue is necessarily caused by the build by the Strawberry team; I'm fairly sure @shawnlaffan used the same build setup as the previous 32bit release (same compiler as well as libraries from the 32bit v5.32 build). So, while my gut says the issue isn't on the Strawberry end of things, I'll wait for @shawnlaffan to weigh in on that build info.

What I suspect the actual problem is, is that Perl itself started fixing some things for Windows without adding the workarounds necessary for EOLed OS versions. While merely dropping support for older versions of Windows doesn't mean they'll actively be broken, there are some examples in those discussions above that exemplify the problem with trying to maintain compatibility with older versions of Windows. Some APIs didn't exist, so runtime decisions based on OS version had to be made, making the code harder to maintain, etc.

I'm not yet answering with a fist-on-the-table of "this is just how it is", but my guess is going to be that if you're still on a 32bit WinXP, you're likely going to have to be pinned at Perl v5.32. That being said, can you see if ActiveState has a 32bit release that might work on your WinXP platform? That might help us determine that it's our problem vs just a "way things are now" type of scenario. I don't have a way of testing on WinXP anymore.

-- Chase

Thanks @genio.

The 32-bit release of SP 5.38 uses the same stack as SP 5.32 so the change would seem more likely related to something in perl itself.

As WFP does not allow exchange of a dll in \system32, I put this new dll into the directory of "perl.exe". But still the same error message pops up.

I think that perl.exe will still be using the old msvcrt.dll.
The "new" msvcrt.dll would only be used by perl if msvcrt.dll has not already been loaded by something else ... and I suspect that the "old" msvcrt.dll has already been loaded.
(Maybe you could experiment by first putting the folder that contains your "new" msvcrt.dll at the beginning of your system path. Not sure if there's anything to be gained there ...)

Along the same lines as @genio and @shawnlaffan, I wonder if the problem might be in the setting of _WIN32_WINNT which is at 0x502 by default.
For example, in the 5.32.0 source, _WIN32_WINNT remains at 0x502 in win32/win32.c,.
But, in the 5.38.2 source, win32/win32.c unconditionally raises _WIN32_WINNT to 0x601 to make "CreateSymbolicLinkA()" (and other symbols) available.
To experiment with that setting, you'd need to revert the 5.38.2 win32/win32.c file and rebuild perl.
There are possibly other files in the perl source that also elevate _WIN32_WINNT.

Since perl-5.38.2 no longer supports XP, it is quite allowable for _WIN32_WINNT to be raised to a level beyond the scope of XP.
I think that Windows 7 is also officially unsupported.

On further search I found the (quite old) contribution in sourceforge on "Provide gmtime/_gmtime32/_gmtime64 for all msvcrt versions through .def files".
Could this be the reason for the failure?

https://sourceforge.net/p/mingw-w64/mailman/mingw-w64-public/thread/1365068783-8108-7-git-send-email-funman%40videolan.org/#msg30682899

Regards
Wolf

Could this be the reason for the failure?

I'm not entirely sure what that sourceforge.net thread is about.
I think it's just about getting those functions into the import libs (libmsvcrt.a, libmsvcr80.a, libmsvcr90.a, libmsvcr100.a, libmsvcr110.a, libmsvcr120.a) that form part of the mingw-w64 ports of gcc.
It's not going to help add the missing functionality to the msvcrt.dll.

The problem arises because the 5.38.2 win/win32.c, at line 1542, does:

retval = _mkgmtime(&pt);

_mkgmtime() is declared in strawberry/c/i686-w64-mingw32/include/time.h and in turn calls _mkgmtime32() (which is also declared in the same time.h file) - which is resolved by the aforementioned import libs.
Neither of those 2 functions are called in the win32/win32.c of perl-5.32.1 - so there's no such issue with perl-5.32.1.

Of course, none of that helps overcome the fact that an msvcrt.dll containing the _mkgmtime32() functionality needs to be loaded when perl-5.38.2 is run.

xenu commented

This particular issue should be resolved by upgrading the toolchain to MinGW-w64 12.0 or later. It was fixed by this commit: mingw-w64/mingw-w64@cd4cf9b

Proof:

> gc a.c
#include <time.h>
int main() {
    struct tm t = {0};
    return _mkgmtime(&t);
}
PS C:\Users\xenu\test> & winlibs-i686-posix-dwarf-gcc-13.1.0-llvm-16.0.5-mingw-w64msvcrt-11.0.0-r5\mingw32\bin\gcc.exe a.c
PS C:\Users\xenu\test> dumpbin /imports a.exe | ack _mkgmt
                  272 _mkgmtime32
PS C:\Users\xenu\test> & winlibs-i686-posix-dwarf-gcc-14.2.0-llvm-18.1.8-mingw-w64msvcrt-12.0.0-r1\mingw32\bin\gcc.exe a.c
PS C:\Users\xenu\test> dumpbin /imports a.exe | ack _mkgmt
                  327 _mkgmtime

Of course, it's possible that upgrading the toolchain will break something else on Windows XP.

BTW, XP was released 20 years ago and it's been EOL for 10 years. Why use bleeding-edge Perl on an obsolete OS?

This particular issue should be resolved by upgrading the toolchain to MinGW-w64 12.0 or later.

On my own MSWin32-x86-multi-thread-64int build of perl-5.38.0, built using MinGW-w64 13.1.0, I find that (according to dumpbin /IMPORTS) the perl538.dll still imports _mkgmtime32 from msvcrt.dll.
That leads me to speculate that it, too, would not run on @wolfdiem's XP machine.
Might it be that, in addition to using a later toolchain, it is also necessary that perl be built on @wolfdiem's XP machine ?
I don't have a personal 5.38.2 build readily available, but I would anticipate it to be the same (in this regard) as my 5.38.0 build.

In my MSWin32-x86-multi-thread-64int build of perl-5.40.0 (built using MinGW-w64 14.1.0) I find that perl540.dll imports _mkgmtime64 instead of _mkgmtime32.
I certainly wasn't expecting that - but I see that it's being imported from api-ms-win-crt-time-l1-1-0.dll, not msvcrt.dll.

Both of those builds of mine were done on a 64-bit Windows 11 system.

xenu commented

, built using MinGW-w64 13.1.0

You're confusing GCC version with MinGW-w64 version.

GCC and the accompanying MinGW-w64 toolchain are versioned separately. For example, when you have winlibs build "winlibs-i686-posix-dwarf-gcc-13.1.0-llvm-16.0.5-mingw-w64msvcrt-11.0.0-r5", GCC version is 13.1 and the version of MinGW-w64 is 11.0.

You're confusing GCC version with MinGW-w64 version.

I see.
Though I'm pretty sure my perl-5.40.0 was built with MinGW-w64 version 11.0.1, because the original 12.0 release (in winlibs gcc-14.1.0) was broken.
(See brechtsanders/winlibs_mingw#221.)