On Fri, 8 Jul 2022, Allen Hewes wrote:

I'm not the OP, but I've got some questions. I've been helping a little with mingw-builds and I am curious about ucrt as well. I don't much about ucrt/ucrtbase, so bear with me. I did find Martin's post about ucrt from 2019.

I don't know exactly what mail you're referring to, but some parts of your comments sounds like it was from early discussions, which might not entirely reflect how things ended up in practice.

I have downloaded a few of the MSYS2 mingw-w64-ucrt packages and uncompressed them. I then did ldd on the DLL/EXEs and I often find that both msvcrt.dll and ucrtbase.dll are imports. Is this correct? I was expecting to see no imports for msvcrt.dll or only imports for a single C runtime, not both. How does this work? How does this not have linking/loader issues?

Windows DLLs/EXEs load symbols explicitly from specific DLLs. You can have one DLL lib1.dll signalling "load 'malloc' from ucrtbase.dll" and another DLL lib2.dll signalling "load 'malloc' from msvcrt.dll". This doesn't conflict; lib1.dll's references to malloc gets resolved from ucrtbase.dll and lib2.dll's references get resolved from msvcrt.dll.

There's no global symbol namespace between DLLs at runtime - contrary to e.g. ELF.

The reason why you're seeing msvcrt.dll here is because many system libraries link against msvcrt.dll (that's what it is after all - the Windows system internal C runtime). Some system components link against UCRT, some against msvcrt.dll. ldd prints all libraries that end up loaded in practice, not only the ones that are referenced directly.

To see the DLLs that an executable references directly, you can run e.g. "llvm-readobj --coff-imports <exe>" (if you happen to have that tool available), or e.g. "objdump -p <exe>" (which prints a lot more, so the reference DLLs is a bit harder to see in isolation). If you look at binaries in the msys2 mingw-w64-ucrt repo, I would expect that none of them directly load msvcrt.dll.

In Martin's post, he mentions dumping the current gcc specs and modifying them, then using the gcc arg to use custom specs when linking for ucrt. I guess my question is this seems harder than sticking with msvcrt because It Just Works. Will folks ever be able to use ucrt/ucrtbase in replacement of msvcrt and just have gcc/ld/libtool use ucrt/ucrtbase?

The use of spec file hackery was only discussed early on as an alternative way of choosing what CRT to link against. It's not something that is recommended that you do in practice.

All packages in the MSYS2 mingw-w64-ucrt repo all use ucrt/ucrtbase instead of msvcrt, in all of gcc/ld/libtool etc.

I guess I'd assume mingw-w64 to set gcc specs if I used --with-default-msvcrt=ucrt. With this configure option, I still get import libs for msvcrt/msvcrt-os and ucrt/ucrtbase, why is that?

Configuring the toolchain with --with-default-msvcrt=ucrt (in both mingw-w64-headers and mingw-w64-crt, then building the rest of the toolchain, e.g. libgcc/libstdc++ on top of that) is indeed the correct way to set it up.

When you build mingw-w64-crt, you do get the import libraries for all CRT alternatives (UCRT and msvcrt) installed - you do get libucrt.a, libmsvcrt-os.a. libmsvcrt-os.a is the library that always links against "the msvcrt.dll that comes with the OS".

Now in practice, gcc and clang and possibly lots of other tools default to linking with "-lmsvcrt" (in the spec files in gcc, hardcoded in clang). So instead of trying to clumsily change that default in various places, we settled on repurposing what "libmsvcrt.a" is.

libmsvcrt.a is the import library for the default CRT that you chose with the --with-default-msvcrt= option when mingw-w64-crt was built. It's a copy of libmsvcrt-os.a or libucrt.a (or libucrtbase.a, or libmsvcr<numbers>.a if you picked that).

If using ucrt/ucrtbase is kinda this road with curves,

It really isn't a road with curves - I don't understand how you got that picture.

If you download a toolchain that is built defaulting to ucrt, it practically works just as smoothly as toolchains defaulting to msvcrt. Many such toolchains are available, e.g. the ucrt repo in msys2.

why use it over msvcrt? What are the advantages of using ucrt/ucrtbase over msvcrt? (Other than one is "legacy"...)

There's lots of various reasons one might have for wanting it.

UCRT is not "legacy" indeed - linking against msvcrt.dll is explicitly discouraged by Microsoft (other than for the small subset of MSVC6 functions).

UCRT has got working locale support, and provides functions that are C99 compliant, allowing us to potentially get rid of a bunch of statically linked mingw specific functions.

Using UCRT improves interop with code built with MSVC, if different parts of the setup pass around CRT objects between modules built with MSVC and mingw (e.g. call fopen in one DLL and fclose in another, call malloc in one DLL and free in another, etc).

For arm64, there never shipped any version of Windows supporting arm64 that didn't have ucrt, so there's no reason not to use the modern CRT as baseline by default for such configurations.

Plus possibly a bunch of other reasons.


// Martin



_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to