[Development] [RFCs] Migrate from GCC MinGW to LLVM MinGW

Martin Storsjö martin at martin.st
Thu Jul 20 08:48:43 CEST 2023


On Wed, 19 Jul 2023, Thiago Macieira wrote:

> On Wednesday, 19 July 2023 08:46:27 PDT Cristian Adam via Development wrote:
>
>> With this migration would should also switch to Universal
>> CRT<https://devblogs.microsoft.com/cppblog/introducing-the-universal-crt/>.
>> The toolchain comes in both ucrt and msvcrt variants, but the former is
>> preferrable nowadays.
>
> Indeed and that's great, but that's a BC break. That means you'll need to
> provide two sets of binaries for a time.
>
> It's also orthogonal, because GCC supports UCRT too, with this patch:
> https://github.com/msys2/MINGW-packages/raw/
> 8d9ebb74412c1faabc2a3935bfc705bec19edb9a/mingw-w64-gcc/0006-Windows-New-
> feature-to-allow-overriding.patch

Indeed UCRT support isn't Clang specific at all - but GCC doesn't really 
need that patch either.

And conversely, that patch (and a later recently upstreamed version of the 
same) gives a false sense of being able to switch between msvcrt and UCRT 
at will; that feature really needs to come with a big disclaimer.

That flag, allowing you to decide whether to target msvcrt or UCRT when 
building/linking your end user executable, only works in a small subset of 
scenarios if you're really careful and know what you're doing - if not, 
it's a very subtle footgun.

There are significant differences in how the mingw-w64 CRT headers behave 
between msvcrt and UCRT mode; in one mode, some functions may be inlined 
or directed towards a symbol with one name, and towards one with another 
name in the other mode. (If you strike that, you get a fairly visible 
linking error.) Worse, some structs have different layout, and there are 
other ABI differences (for the UCRT mode, we decided to modernize things 
with defaulting to a 64 bit time_t in 32 bit mode).

The only really safe way of doing this, is picking one as default and 
bootstrap the whole toolchain with that, and then having separate 
toolchains targeting ucrt or msvcrt. (In msys2, the mingw64 environment is 
gcc-based targeting msvcrt, while the ucrt64 environment is gcc-based 
targeting ucrt).

Switching with those flags works, as long as you're building a C-only 
executable and linking libgcc statically (and not linking in any static 
libraries that were built for another CRT). I'm pretty sure that libstdc++ 
touches lots of the things that have a differing ABI. A shared linked 
libgcc will use the CRT that the toolchain was built with - although I'm 
not sure if libgcc shares any CRT objects across the DLL boundary (whether 
it is a real issue or just messy).

So TL;DR, pretend that flag doesn't exist in GCC, and just use a toolchain 
that was bootstrapped for the desired CRT. (The flag is more useful for 
switching between older variants of the MSVC CRTs that have less hairy ABI 
differences.)

// Martin



More information about the Development mailing list