digitalmars.D - [Proposal] Switch to the Universal CRT on Windows.
- Adam Wilson (38/38) Jun 30 I recently got hit by a rather esoteric bug that looked like a
- Adam Wilson (11/18) Jun 30 It was noted to me by ADR on Discord that we could keep the
- Dennis (15/17) Jul 01 I'm in favor, but can I say that this shows how much of a
- Denis Feklushkin (9/20) Jul 01 I also agree with this, for the reason that libc slows down
- Guillaume Piolat (7/13) Jul 02 I'm not sure if it's easy to implement and maintain fopen for
- Denis Feklushkin (6/12) Jul 03 Seems this isn't used in the druntime.
- Adam Wilson (14/20) Jul 02 There is a technical argument for leaving `libc` behind as well.
- Richard (Rikki) Andrew Cattermole (4/26) Jul 02 This is sounding far too platform specific, and will make it so it
- Adam Wilson (6/11) Jul 02 And how do you avoid making it platform specific? The reason I
- Richard (Rikki) Andrew Cattermole (9/23) Jul 02 Simple, you won't be doing these things in it.
- Adam Wilson (9/10) Jul 04 That is nothing like what I proposed last year or what we have
- Richard (Rikki) Andrew Cattermole (5/17) Jul 04 Indeed.
- Walter Bright (1/1) Jul 03 https://github.com/dlang/dmd/pull/23351
- Walter Bright (2/3) Jul 03 This should be picked up by chkformat.d ?
- Walter Bright (2/4) Jul 03 I agree. fopen() is not used in dmd.
- Lance Bachmeier (5/7) Jul 01 It's 2026 so I agree. I don't do much with Windows beyond my work
I recently got hit by a rather esoteric bug that looked like a real bug, but was actually not a bug, but also kind of a bug. Specifically, on Windows the printf `%zd` format would fail with a Segfault. The simple fix was to delete `%zd` and use `%d` with a cast to a fixed size int type. But it was the wrong fix. The actual root cause is that I was running `build.d` and `build.d` decided to use the 13 year old MSVCR120.dll, which does not support `%zd` printf formats. Despite the fact that I have the most modern C++ build tools and SDK's that you can get installed on my machine. (I work on Windows for a living, to my enduring shame) The result is that we ship a fallback CRT that doesn't even support building the compiler itself. Egg, meet face. The solution is pretty straight-forward. Use the Universal CRT for everything on Windows. And it turns out that there is another reason to abandon everything but UCRT. MINGW64 is now deprecated in favor of UCRT. (See blog post [here](https://www.msys2.org/news/#2026-03-15-deprecating-the-m ngw64-environment)) Therefore, we will be required to make this change at some point in the near future because MinGW is forcing us too. Moving to UCRT will also allow us to deprecate and eventually remove the giant bag of hacks that is our MINGW64 support. Anybody not using Windows 10 or greater will need to install the UCRT as a minimum from [here](https://support.microsoft.com/en-us/topic/update-for-universal-c-runtime-in-windows-322bf30f-4735-bb94-3949-49f5c49f4732). However, I think this is acceptable because our policy is that we only officially support the versions of Windows that Microsoft does for ESU, which means Win10 22H2 (until October 2028) or Win11. And since UCRT has been back-ported to older systems by Microsoft itself, it's an easy problem to handle for people deploying D-code. Note for Walter: You will need at least the 2015 Build Tools on Win7, which you can get [here](https://www.microsoft.com/en-us/download/details.aspx?id=48159). Or if you want something a little newer, the VS2017 build tools are [here](https://aka.ms/vs/15/release/vs_buildtools.exe). I have posted a PR [here](https://github.com/dlang/dmd/pull/23345). This PR deprecates (but still allows) the msvcr120 fallback path as well as updating various detection routines to include the latest versions of VS and deprecate anything prior to VS2015. If no WinSDK or VS installation is detected then the compiler throws an error.
Jun 30
On Wednesday, 1 July 2026 at 01:24:05 UTC, Adam Wilson wrote:I have posted a PR [here](https://github.com/dlang/dmd/pull/23345). This PR deprecates (but still allows) the msvcr120 fallback path as well as updating various detection routines to include the latest versions of VS and deprecate anything prior to VS2015. If no WinSDK or VS installation is detected then the compiler throws an error.It was noted to me by ADR on Discord that we could keep the ability to build without the WinSDK/VS if we included the appropriate UCRT library files from MinGW and updated `lld-link.exe`. We might want to consider including more than just the UCRT library files from MinGW so we can support building projects that need more than the UCRT without requiring the WinSDK. Although, I would note that this is a bigger shift into a policy of shipping our own complete development environment, with the attendant overhead of making sure that environment is up-to-date.
Jun 30
On Wednesday, 1 July 2026 at 01:24:05 UTC, Adam Wilson wrote:The solution is pretty straight-forward. Use the Universal CRT for everything on Windows.I'm in favor, but can I say that this shows how much of a nuisance depending on libc is? Walter often says how printf is the most debugged function ever so we should leverage that in dmd, but here we are getting bitten by libc nonsense yet again. Between that, its [unsafe interface](https://github.com/dlang/dmd/pull/13987), stupid [global locale system](https://github.com/dlang/dmd/blob/cfae207a4dfa38bdc67b28986e263365adc577c3/compiler/src/dmd/r ot/port.d#L93-L104) and [random breakages](https://bugzilla-archive.dlang.org/bugs/23846/), are we really better off than if we just wrote our own D function to interpolate numbers in strings? In my own code I avoid libc as much as I can, using `CreateFileW` instead of `fopen` for example. Only a few essentials like memcpy and memset remain since LDC sometimes emits calls to that even when you don't write them yourself. At least those are simple and deterministic: I haven't found a libc yet that implements them visibly different than the rest.
Jul 01
On Wednesday, 1 July 2026 at 12:37:22 UTC, Dennis wrote:On Wednesday, 1 July 2026 at 01:24:05 UTC, Adam Wilson wrote:I also agree with this, for the reason that libc slows down porting to systems where it is not present. Maybe we need to get together somewhere and discuss it? My proposal was outlined [here](https://forum.dlang.org/post/mssdrzylsdqmpcnvakar forum.dlang.org): "druntime should not import core.stdc" Let the druntime use these functions through wrapper functions or aliases. There will be only about 10 of them in total, I think: malloc/free, some sync methods...The solution is pretty straight-forward. Use the Universal CRT for everything on Windows.I'm in favor, but can I say that this shows how much of a nuisance depending on libc is? Walter often says how printf is the most debugged function ever so we should leverage that in dmd, but here we are getting bitten by libc nonsense yet again. Between that, its [unsafe interface](https://github.com/dlang/dmd/pull/13987), stupid [global locale system](https://github.com/dlang/dmd/blob/cfae207a4dfa38bdc67b28986e263365adc577c3/compiler/src/dmd/r ot/port.d#L93-L104) and [random breakages](https://bugzilla-archive.dlang.org/bugs/23846/), are we really better off than if we just wrote our own D function to interpolate numbers in strings?
Jul 01
On Wednesday, 1 July 2026 at 12:37:22 UTC, Dennis wrote:In my own code I avoid libc as much as I can, using `CreateFileW` instead of `fopen` for example. Only a few essentials like memcpy and memset remain since LDC sometimes emits calls to that even when you don't write them yourself. At least those are simple and deterministic: I haven't found a libc yet that implements them visibly different than the rest.I'm not sure if it's easy to implement and maintain fopen for many systems. At least the libc is maintained by others. Other small challenges involves: emitting and parsing floating-point correctly. And the transcendental functions, that are not especially better in Phobos than in libc.
Jul 02
On Thursday, 2 July 2026 at 16:32:06 UTC, Guillaume Piolat wrote:I'm not sure if it's easy to implement and maintain fopen for many systems. At least the libc is maintained by others.It can be "implemented" by bypassing alias to libc's `fopen`Other small challenges involves: emitting and parsing floating-point correctly.Seems this isn't used in the druntime.And the transcendental functions, that are not especially better in Phobos than in libc.And the Phobos problem is a Phobos problem, essentially unrelated to the compiler and druntime. It will even be possible to disable some of its parts for which there will be no implementations.
Jul 03
On Wednesday, 1 July 2026 at 12:37:22 UTC, Dennis wrote:In my own code I avoid libc as much as I can, using `CreateFileW` instead of `fopen` for example. Only a few essentials like memcpy and memset remain since LDC sometimes emits calls to that even when you don't write them yourself. At least those are simple and deterministic: I haven't found a libc yet that implements them visibly different than the rest.There is a technical argument for leaving `libc` behind as well. Specifically if you want to do anything with async operations you're going to have to use the API's specific to that platform. For example: Linux has `io_uring` where Windows has I/O Completion Ports. `libc` stops working as a universal system interface when you need to do async work, which means that anywhere we might want to support an async interface, we'll need to use something other than `libc`. Another example is terminal colors. Windows has `SetConsoleTextAttribute()` where `libc` is the only choice on Linux. Which means we really should be abstracting away `libc`. IMO, BaseD is going to become that abstraction.
Jul 02
On 03/07/2026 5:14 PM, Adam Wilson wrote:On Wednesday, 1 July 2026 at 12:37:22 UTC, Dennis wrote:This is sounding far too platform specific, and will make it so it cannot be the base most library for D. This is what druntime is for.In my own code I avoid libc as much as I can, using `CreateFileW` instead of `fopen` for example. Only a few essentials like memcpy and memset remain since LDC sometimes emits calls to that even when you don't write them yourself. At least those are simple and deterministic: I haven't found a libc yet that implements them visibly different than the rest.There is a technical argument for leaving `libc` behind as well. Specifically if you want to do anything with async operations you're going to have to use the API's specific to that platform. For example: Linux has `io_uring` where Windows has I/O Completion Ports. `libc` stops working as a universal system interface when you need to do async work, which means that anywhere we might want to support an async interface, we'll need to use something other than `libc`. Another example is terminal colors. Windows has `SetConsoleTextAttribute()` where `libc` is the only choice on Linux. Which means we really should be abstracting away `libc`. IMO, BaseD is going to become that abstraction.
Jul 02
On Friday, 3 July 2026 at 05:18:38 UTC, Richard (Rikki) Andrew Cattermole wrote:On 03/07/2026 5:14 PM, Adam Wilson wrote:And how do you avoid making it platform specific? The reason I ask is that DRT does not yet exist in BaseD code. DRT would be after it in the build chain (BaseD->DRT->Phobos). So everything you write is going to be platform specific.IMO, BaseD is going to become that abstraction.This is sounding far too platform specific, and will make it so it cannot be the base most library for D. This is what druntime is for.
Jul 02
On 03/07/2026 5:57 PM, Adam Wilson wrote:On Friday, 3 July 2026 at 05:18:38 UTC, Richard (Rikki) Andrew Cattermole wrote:Simple, you won't be doing these things in it. They belong much further up the dependency graph. Based can only really do simple stuff like bit manipulation, memory copying byte by byte. Trying to expand the scope of it beyond this is just going to lead to massive problems both with binary sizes, as in 64k limit and make porting extremely difficult to even get off the ground. The scope is basically the same as compiler-rt builtins.On 03/07/2026 5:14 PM, Adam Wilson wrote:And how do you avoid making it platform specific? The reason I ask is that DRT does not yet exist in BaseD code. DRT would be after it in the build chain (BaseD->DRT->Phobos). So everything you write is going to be platform specific.IMO, BaseD is going to become that abstraction.This is sounding far too platform specific, and will make it so it cannot be the base most library for D. This is what druntime is for.
Jul 02
On Friday, 3 July 2026 at 06:08:39 UTC, Richard (Rikki) Andrew Cattermole wrote:The scope is basically the same as compiler-rt builtins.That is nothing like what I proposed last year or what we have discussed since then. The idea for BaseD has always been a trimmed-down no-gc standard library for projects that need it. That means basic terminal I/O, data structures, etc. If your goal for BaseD is limited "things the compiler needs to link successfully" then we have fundamentally different views on the topic.
Jul 04
On 05/07/2026 4:50 PM, Adam Wilson wrote:On Friday, 3 July 2026 at 06:08:39 UTC, Richard (Rikki) Andrew Cattermole wrote:Indeed. The biggest difference is I know for a fact that what you want as-is is going to be a nightmare to fix. It will appear to work, right up until we can't do a release anymore.The scope is basically the same as compiler-rt builtins.That is nothing like what I proposed last year or what we have discussed since then. The idea for BaseD has always been a trimmed-down no-gc standard library for projects that need it. That means basic terminal I/O, data structures, etc. If your goal for BaseD is limited "things the compiler needs to link successfully" then we have fundamentally different views on the topic.
Jul 04
On 7/1/2026 5:37 AM, Dennis wrote:its [unsafe interface](https://github.com/dlang/dmd/pull/13987)This should be picked up by chkformat.d ?
Jul 03
On 7/1/2026 5:37 AM, Dennis wrote:In my own code I avoid libc as much as I can, using `CreateFileW` instead of `fopen` for example.I agree. fopen() is not used in dmd.
Jul 03
On Wednesday, 1 July 2026 at 01:24:05 UTC, Adam Wilson wrote:The solution is pretty straight-forward. Use the Universal CRT for everything on Windows.It's 2026 so I agree. I don't do much with Windows beyond my work with R (much of it being interoperability with D), but they changed to UCRT years ago, and it made everything easier. Windows was a nightmare for R before the change.
Jul 01









Adam Wilson <flyboynw gmail.com> 