[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