On Sat, 28 Sep 2024, Pali Rohár wrote:

MinGW-w64 still does not provide full ISO C95 or C99 compatibility for
applications. I was looking what is missing to get runtime library
compatibility for ISO C95. And I identified that missing parts for C95
are wcstok() and (v)swprintf() functions, which signatures in header
files and msvcrt.dll symbols are incompatible.

This patch series implements wcstok() and (v)swprintf() functions
compatible with C95 and C99 (and should be compatible also with later
ISO C versions). And brings C95 compatibility for all CRT import
libraries.

In __USE_MINGW_ANSI_STDIO=0 mode (v)swprintf() has one deviation from
ISO C95, its %s takes wchar_t* instead of char*. This is because of
msvcrt behavior. For C99 there are more deviations: missing C99 formats
which are unsupported by msvcr* DLL. In __USE_MINGW_ANSI_STDIO=1 mode
(v)swprintf() should be fully compatible with ISO C95 and C99.

This patch series also aligns API/ABI of (v)sw(n)printf() functions
between different __USE_MINGW_ANSI_STDIO modes, to make it sane and
consistent.

There are also new automated tests for some printf functions, so I would
be happy if somebody check that they are passing also on other machine
than mine.

I do not know of any other missing C95 functionality in MinGW-w64 but it
does not mean that there cannot be something still hidden.

Note that MinGW-w64 currently has swprintf() and wcstok() incompatible
with ISO C95+ and these changes will break compilation of applications
which depends on the current behavior. But this behavior is incompatible
with MSVC and also with Linux glibc headers, so I'm not sure how big
problem it is. I think that having swprintf() and wcstok() function
signatures different from what is in ISO C is bigger problem.
Previous API could be achieved by -D_CRT_NON_CONFORMING_SWPRINTFS and
-D_CRT_NON_CONFORMING_WCSTOK options (same as with msvc).

Also note that fix for wcstok() for clang builds would require Martin's
changes to llvm dlltool and linker.


Pali Rohár (15):
 crt: Add support for C95 wcstok() function for non-UCRT import
   libraries
 headers: Fix _tcstok and _wcstok_l macros in _UNICODE mode
 crt: Add support for C95 (v)swprintf() functions when
   __USE_MINGW_ANSI_STDIO=0
 crt: Add support for C95 (v)swprintf() functions when
   __USE_MINGW_ANSI_STDIO=1
 crt: Fix non-ISO (v)snwprintf() functions when
   __USE_MINGW_ANSI_STDIO=0
 crt: Add _(v)scwprintf emulation for msvcrt.dll
 headers: Fix _stprintf and _vstprintf macros in _UNICODE mode
 headers: Fix _*tscanf and _*tprintf macros which expands to ISO C
   functions
 crt: Add snprintf test
 crt: Add swprintf test
 crt: Add snwprintf test
 crt: Add _stprintf test
 crt: crtdll and msvcrt10: Add support for C95 getwc(), getwchar(),
   putwc(), putwchar() functions
 crt: crtdll and msvcrt10: Add support for C95 fputws() function
 crt: crtdll and msvcrt10: Add support for C95 fgetws() function

I've started reading your patchset, but this will take some time to get through.

I don't have a setup ready for running the tests from mingw-w64-crt, so I can't see readily if those work as is - but I'd like to add some tests for these functions in https://github.com/mstorsjo/llvm-mingw/blob/master/test/crt-test.c where I can test that they behave as expected.

I did try to run some general testing with these patches, but it does seem break building in C++ mode, at least when building libc++ and libstdc++.


To ease validation of more complex patches for mingw-w64, like this, I've tried to set up some sort of rough CI environment for it, on github. See the topmost commit at https://github.com/mstorsjo/mingw-w64/commits/ci. (The second topmost commit is a patch to temporarily work around a recent breakage.)

It's quite easy to use this CI setup for your own patchsets, even if mingw-w64 itself isn't hosted officially on github. Just make a personal fork of https://github.com/mingw-w64/mingw-w64, and make a branch where you add your own commits, and the commit from my branch. When you push that to github, it will run the CI validation steps.

See https://github.com/mstorsjo/mingw-w64/actions/runs/11290055847 for an example of such a run.

This CI environment does this:

- It takes an existing release of llvm-mingw, and rebuilds mingw-w64 on top of it, and then rebuilds the runtimes (libunwind, libc++ etc) on top of it. This is done for all of ucrt, ucrtbase and msvcrt, for all 4 target architectures of llvm-mingw (i686, x86_64, armv7 and aarch64).

- It repackages the native Windows packages of llvm-mingw, with the newly rebuilt runtimes included

- It builds GCC from scratch, as a cross compiler, with the current mingw-w64 version to be tested, targeting x86_64. This is set up both with ucrt and msvcrt.

- With the GCC from the previous step, it cross-builds a Windows-hosted GCC compiler, both with ucrt and msvcrt.

To validate functionality of these rebuilt/updated toolchains, it does the following tests:

- Tests running the llvm-mingw suite of smoke tests (including my crt-test.c) for (i686, x86_64) x (msvcrt, ucrt, ucrtbase)

- It builds a couple of tests from my llvm-mingw testsuite, with GCC, and tests running them

- With llvm-mingw, it tests cross compiling ffmpeg for all 4 target architectures

- With llvm-mingw, it builds ffmpeg natively on i686 and x86_64 and runs the runtime tests

- It runs the full libc++ testsuite, with i686 and ucrt. (This doesn't pass with msvcrt.)

It should be fairly easy for you to look at the test setup and extend it with more tests if you like that: https://github.com/mstorsjo/mingw-w64/commit/679c506b76fad10867655e085cacac4741a9c434


With this setup, you should be able to iterate on your patchset and make sure that it doesn't break any of these cases, before returning it to review. With your patches applied, it fails like this: https://github.com/mstorsjo/mingw-w64/actions/runs/11289029592/job/31398015190

// Martin

_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to