I Fixed Windows Native Development
marler8997.github.io608 points by deevus 11 hours ago
608 points by deevus 11 hours ago
This is harder than what I do. Just install LTSC Visual Studio build tools from [1], then chuck this in a cmd file:
cl yourprogram.c /link user32.lib advapi32.lib ... etc etc ...
I've built a load of utilities that do that just fine. I use vim as an editor.The Visual Studio toolchain does have LTSC and stable releases - no one seems to know about them though. see: https://learn.microsoft.com/en-gb/visualstudio/releases/2022... - you should use these if you are not a single developer and have to collaborate with people. Back like in the old days when we had pinned versions of the toolchain across whole company.
[1] https://download.visualstudio.microsoft.com/download/pr/5d23...
> The Visual Studio toolchain does have LTSC and stable releases - no one seems to know about them though.
You only get access to the LTSC channel if you have a license for at least Visual Studio Professional (Community won't do it); so a lot of hobbyist programmers and students are not aware of it.
On the other hand, its existence is in my experience very well-known among people who use Visual Studio for work at some company.
The Visual Studio Build Tools are installable with winget (`winget search buildtools`).
There are licensing constraints, IANL but essentially you need a pro+ license on the account if you're going to use it to build commercial software or in a business environment.
You can install the LTSC toolchain without a license. Just not the IDE.
That's not correct. You don't have to give your credit card details or even be logged in but you are still required to have any Visual Studio license. For hobbyists and startups the VS Community license is enough but larger companies need a VS Professional license even for the VS Build Tools.
How strict Microsoft is with enforcement of this license is another story.
You do not need a Professional or Enterprise license to use the Visual Studio Build Tools:
> Previously, if the application you were developing was not OSS, installing VSBT was permitted only if you had a valid Visual Studio license (e.g., Visual Studio Community or higher).
From (https://devblogs.microsoft.com/cppblog/updates-to-visual-stu...). For OSS, you do not even need a Community License anymore.
This does not apply if you're developing closed source:
> if you and your team need to compile and develop proprietary C++ code with Visual Studio, a Visual Studio license will still be required.
That just confirms the parent comment's point. If you're just using the build tools directly, you're fine. If need to develop "with Visual Studio" i.e. the IDE, not just the command line tools, then you need the paid license.
Is the fancy text editor compiling, or the toolchain?
I don’t need visual to write, read, compile, or link any code using the toolchain.
Fair. Although I tend not to give a crap about Microsoft licensing :)
Well, let's say this is the world view of all companies about open-source software. Then what happens. If people "tend to not give crap" about licenses, all the nice guarantees of GPL etc also disappear.
There are zero guarantees and commercial software uses GPLd software as parts of their products all the time. Licenses do not work and you shouldn't respect them whenever you can.
And a VS license isn't too expensive if you really want to buy one. Stack Social have legit licenses discounted to $15:
https://www.stacksocial.com/sales/microsoft-visual-studio-pr...
This definetly looks like some sort of scam. Like a volume key license being resold against EULA or some such.
> Like a volume key license being resold against EULA or some such.
At least in the EU, this is legal.
Through which means?
I can only provide articles that are in German:
An article about court decision by the EuGH from 2012:
https://www.heise.de/hintergrund/EuGH-Gebrauchte-Softwareliz...
Another court decision from the BGH (the highest German civil court) from 2014 that builds on this EuGH decision:
https://www.heise.de/news/BGH-begruendet-Rechtmaessigkeit-de...
I noticed Visual Studio 2026 doesn't have an LTSC release yet. Any idea when that will come out?
They've completely reworked release plans. 2026 LTSC will come out a year after the initial VS 2026 release (at the same time as VS 2027) and be supported for 1 more year. You pretty much have to get on the rolling updates train for the IDE, which is why the C++ toolchain now follows a different schedule and you're supposed to be able to install any specific toolchain side by side.
Toolchains on linux are not clear from dependency hell either - ever install an npm package that needs cmake underneath? glibc dependencies that can't be resolved because you need two different versions simultaneously in the same build somehow... python in another realm here as well. That shiny c++ project that needs a bleeding edge boost version that is about 6 months away from being included in your package manager. Remember patching openSSL when heartbleed came around (libssHELL).
Visual studio is a dog but at least it's one dog - the real hell on windows is .net framework. The sheer incongruency of what version of windows has which version of .net framework installed and which version of .net your app will run in when launched... the actual solution at scale for universal windows compatibility on your .net app is to build a c++ shim that checks for .net beforehand and executes it with the correct version in the event of multiple version conflict - you can literally have 5 fully unique runtimes sharing the same .net target.
> glibc dependencies that can't be resolved because you need two different versions simultaneously in the same build somehow...
If you somehow experience an actual dependency issue that involves glibc itself, I'd like to hear about it. Because I don't think you ever will. The glibc people are so serious about backward and forward compatibility, you can in fact easily look up the last time they broke it: https://lwn.net/Articles/605607/
Now, if you're saying it's a dependency issue resulting from people specifying wrong glibc version constraints in their build… yeah, sure. I'm gonna say that happens because people are getting used to pinning dependency versions, which is so much the wrong thing to do with glibc it's not even funny anymore. Just remove the glibc pins if there are any.
As far as the toolchain as a whole is concerned… GCC broke compatibility a few times, mostily in C++ due to having to rework things to support newer C++ standards, but I vaguely remember there was a C ABI break somewhere on some architecture too.
When was the last time you actually used. NET? Because that's absolutely not how it is. The. NET runtime is shipped by default with Windows and updated via WU. Let alone that you're talking about .NET Framework which has been outdated for years.
.NET runtime is not shipped with Windows, but once installed can be updated by WU.
Only the latest .NET Framework 4.8 is shipped with Windows at this point.
The issue is in supporting older windows versions - which sadly is still a reality for most large-scale app developers.
https://github.com/dotnet/core/blob/main/release-notes/10.0/...
.NET 10 supports a Windows 10 build from 10 years ago.
Yes and in the wild believe it or not you'll find windows 7 and windows 8.
We had just deprecated support for XP in 2020 - this was for a relatively large app publisher ~10M daily active users on windows. The installer was a c++ stub which checked the system's installed .NET versions and manually wrote the app.config before starting the .net wrapper (or tried to install portable .NET framework installer if it wasn't found at all).
The app supported .NET 3.5* (2.0 base) and 4 originally, and the issue was there was a ".NET Framework Client Profile" install on as surprising amount of windows PCs out there, and that version was incompatible with the app. If you just have a naked .NET exe, when you launch it (without an app.config in the current folder) the CLR will decide which version to run your app in - usually the "highest" version if several are detected... which in this case would start the app in the lightweight version and error out. Also, in the app.config file you can't tell it to avoid certain versions you basically just say "use 4 then 2" and you're up to the mercy of the CLR to decide which environment it starts you in.
This obviated overrides in a static/native c++ stub that did some more intelligent verifications first before creating a tailored app.config and starting the .net app.
Hey I have a PC running 98SE ;-)
I feel for those who have to support an OS no longer supported by the vendor. That's a tough position to be in, not only if a customer comes across a bug that is due to the OS, but it keeps you from advancing your desktop application forward.
.NET versions are faster outdated then .Net Framework 4.8
Point? I’m SRE on .Net project, we have been through 6-8-10 and its cost us about 2ish hours of work each time. As long as you don’t get crazy, .Net upgrades is just matter of new SDK and runtime and away you go.
You're talking about .net for server applications right? The discussion above is for client apps being distributed for windows endusers.
We have a small MAUI part of the application, it's not massive but it's working fine with .Net Upgrades.
A .net framework 4.8 app has zero hours of work.
Why is it ok that you have to invest 2 times number of apps hours just because MS has such a short life cycle for its .NET versions.
Which has been fixed on .NET 5 and later.
.NET Framework should only be used for legacy applications.
Unfortunately there are still many around that depend on .NET Framework.
Since .NET 10 still doesn't support Type Libraries quite a few new Windows projects must be written in .NET Framework.
Microsoft sadly doesn't prioritize this so this might still be the case for a couple of years.
One thing I credit MS for is that they make it very easy to use modern C# features in .NET Framework. You can easily write new Framework assemblies with a lot of C# 14 features. You can also add a few interfaces and get most of it working (although not optimized by the CLR, e.g. Span). For an example see this project: https://www.nuget.org/packages/PolySharp/
It's also easy to target multiple framework with the same code, so you can write libraries that work in .NET programs and .NET Framework programs.
Most likely never will, because WinRT is the future and WinRT has replaced type libraries with .NET metadata. At least from MS point of view.
The current solution is to use the CLI tools just like C++.
However have you looked into ComWrappers introduced in .NET 8, with later improvements?
I still see VB 6 and Delphi as the best development experience for COM, in .NET it wasn't never that great, there are full books about doing COM in .NET.
.Net Framework 4.8 has a longer life cycle as the current .NET version
When I first worked with dot NET I was confused with the naming and version numbers.
This argument against .NET annoys me.
Because that’s pretty much any freaking thing - oh Python, oh PHP, oh driving a fork lift, oh driving a car.
Once you invest time in using and learning it is non issue.
I do get pissed off when I want to use some Python lib bit it just doesn’t work out of the box, but there is nothing that works out the box without investing some time.
Just like a car get a teenager into a car he will drive into first tree.
Posting BS on Facebook shouldn’t be benchmark for how easy things should be.
It does, but current versions can be shipped with the application.
Thus this should be less of a problem.
Well, traditionally, there was no Python/pip, JS/npm in Linux development, and for C/C++ development, the package manager approach worked surprisingly well for a long time.
However, there were version problems: some Linux distributions had only stable packages and therefore lacked the latest updates, and some had problems with multiple versions of the same library. This gave rise to the language-specific package managers. It solved one problem but created a ton of new ones.
Sometimes I wish we could just go back to system package managers, because at times, language-specific package managers do not even solve the version problem, which is their raison d'être.
Nix devShells works quite well for Python development (don't know about JS) Nixpkgs is also quite up to date. I haven't looked back, since adopting Nix for my dev environments.
This is one of the things that tilts me about C and C++ that has nothing to do with mem safety: The compile/build UX is high friction. It's a mess for embedded (No GPOS) too in comparison to rust + probe-rs.
That hasn't been my experience at all. Cross-compiling anything on Rust was an unimaginable pain (3 years or so ago). While GCCs approach of having different binaries with different targets does have its issues, cross compiling just works.
Ah sorry. I should clarify. Not referring to specifically cross compiling; just general compiling. In rust weather PC or embedded, I run Cargo run. For C or C++, it's who knows. A provincial set of steps for each project, error messages, makes me get frustrated. I keep a set of notes for each one I touch to supplement the project's own docs. I am maybe too dumb or inexperienced in some cases, but I am having a hard time understanding why someone would design that as the UX.
I want to focus on the project itself; not jump through hoops in the build process. It feels hostile.
For cross compiling to ARM from a PC in rust in particular, you do one CLI cmd to add the target. Then cargo run, and it compiles, flashes, with debug output.
These are from anecdotes. I am probably doing something wrong, but it is my experience so far.
.NET does have flags to include the necessary dependencies with the executable these days so you can just run the .exe and don't need to install .net on the host machine. Granted that does increase the size of the app (not to mention adding shitton of dll's if you don't build as single executable) but this at least is a solved problem.
They do now, after .net core and several other iterations. You'll also be shipping a huge executable compared to a clr linked .net app (which can be surprisingly small).
>Toolchains on linux are not clear from dependency hell either - ever install an npm package that needs cmake underneath?
That seems more a property of npm dependency management than linux dependency management.
To play devil's advocate, the reason npm dependency management is so much worse than kernel/os management, is because their scope is much bigger, 100x more package, each package smaller, super deep dependency chains. OS package managers like apt/yum prioritize stability more and have a different process.
I went from POP OS (Ubuntu) to EndeavourOS (Arch) Linux because some random software with an appimage or whatever refused to run with Ubuntus “latest” GLIBC and it ticked me off, I just want to run more modern tooling, havent had any software I couldnt just run on Arch, going on over a year now.
Indeed. As late as 2 hours ago I had to change the way I build a private Tauri 2.0 app (bundled as .AppImage) because it wouldn't work on latest Kubuntu, but worked on Fedora and EndeavourOS. So now I have to build it on Ubuntu 22.04 via Docker. Fun fun.
Had fewer issues on EndeavourOS (Arch) compared to Fedora overall though... I will stay on Arch from now on.
> python in another realm here as well
uv has more of less solved this (thank god). Night and day difference from Pip (or any of the other attempts to fix it honestly).
At this point they should just deprecate Pip.
Ah yes let's all depend on some startup that will surely change the license at some point.
Very clearly a better option than continuing to use Pip. Even if they do change the license in a few years I will definitely take several years of not being shat on by Pip over the comparatively minor inconvenience of having to switch to an open fork of uv when they rug-pull. If they ever do.
Continuing to use Pip because Astral might stop maintaining uv in future is stupidly masochistic.
> Toolchains on linux are not clear from dependency hell either - ever install an npm package.
That's where I stopped.
Toolchains on linux distributions with adults running packaging are just fine.
Toolchains for $hotlanguage where the project leaders insist on reinventing the packaging game, are not fine.
I once again state these languages need to give up the NIH and pay someone mature and responsible to maintain packaging.
The counterpoint of this is Linux distros trying to resolve all global dependencies into a one-size-fits-nothing solution - with every package having several dozen patches trying to make a brand-new application release work with a decade-old release of libfoobar. They are trying to fit a square peg into a round hole and act surprised when it doesn't fit.
And when it inevitably leads to all kinds of weird issues the packagers of course can't be reached for support, so users end up harassing the upstream maintainer about their "shitty broken application" and demanding they fix it.
Sure, the various language toolchains suck, but so do those of Linux distros. There's a reason all-in-one packaging solutions like Docker, AppImage, Flatpak, and Snap have gotten so popular, you know?
> The counterpoint of this is Linux distros trying to resolve all global dependencies into a one-size-fits-nothing solution - with every package having several dozen patches trying to make a brand-new application release work with a decade-old release of libfoobar. They are trying to fit a square peg into a round hole and act surprised when it doesn't fit.
This is only the case for debian and derivatives, lol. Rolling-release distributions do not have this problem. This is why most of the new distributions coming out are arch linux based.
I'm going to need a source for both of those claims.
It sure sounds very Debian-ish, at least. I’m a Fedora user, and Fedora stays veeeery close to upstream. It’s not rolling, but is very vanilla.
Agreed, but I don't think that has to do with either it's "vanillaness" or the 6 month release schedule. Fedora does a lot of compatibility work behind the scenes that distros not backed by a large company more than likely couldn't afford.
The real kicker is when old languages also fall for this trap. The latest I'm aware of is GHC, which decided to invent it's own build system and install script. I don't begrudge them from moving away from Make, but they could have used something already established.
> The build.bat above isn’t just a helper script; it’s a declaration of independence from the Visual Studio Installer.
I am so fed up with this! Please if you're writing an article using LLMs stop writing like this!
I never understood this sentence structure, it adds zero information, it always goes like:
“This isn’t just [what the thing literally is]; it’s [hyperbole on what the thing isn’t].”
It’s a perfectly fine sentence structure. It’s been around for years and years. That’s why LLMs use it!
In the UK, Marks and Spencer have a long-running ad campaign built around it (“it’s not just food, it’s...”)
Em dashes are fine too.
The purpose isn't information, the purpose is drama.
Er, sorry. I meant: the purpose isn't just drama—it's a declaration of values, a commitment to the cause of a higher purpose, the first strike in a civilizational war of independence standing strong against commercialism, corporatism, and conformity. What starts with a single sentence in an LLM-rewritten blog post ends with changing the world.
See? And I didn't even need an LLM to write that. My own brain can produce slop with an em dash just as well. :)
While this is great - Visual Studio installer has a set of "command-line parameters" for unattended installs.
You can then build a script/documentation that isolates your specific requirements and workloads:
https://learn.microsoft.com/en-us/visualstudio/install/use-c...
Had to do this back in 2018, because I worked with a client with no direct internet access on it's DEV/build machines (and even when there was connectivity it was over traditional slow/low-latency satellite connections), so part of the process was also to build an offline install package.
I tried this once. It downloaded way more stuff than needed and still required admin to actually install.
Well - "run as admin" wasn't a problem for that scenario - as I was also configuring the various servers.
(And - it is better on a shared-machine to have everything installed "machine-wide" rather than "per-user", same as PowerShell modules - had another client recently who had a small "C:" drive provisioned on their primary geo-fenced VM used for their "cloud admin" team and every single user was gobbling too much space with a multitude of "user-profile" specific PowerShell modules...)
But - yes, even with a highly trimmed workload it resulted in a 80gb+ offline installer. ... and as a server-admin, I also had physical data-center access to load that installer package directly onto the VM host server via external drive.
Looking at the script:
> curl -L -o msvcup.zip https://github.com/marler8997/msvcup/releases/download/v2026...
No thanks. I’m not going to install executables downloaded from an unknown GitHub account named marler8997 without even a simple hash check.
As others have explained the Windows situation is not as bad as this blog post suggests, but even if it was this doesn’t look like a solution. It’s just one other installation script that has sketchy sources.
You don't have to install executables downloaded from an unknown GitHub account named marler8997. You can download that script and read it just like any other shell script.
Just like those complaining about curl|sh on Linux, you are confusing install instructions with source code availability. Just download the script and read it if you want. The curl|sh workflow is no more dangerous that downloading an executable off the internet, which is very common (if stupid) and attracts no vitriol. In no way does it imply that you can not actually download and read the script - something that actually can't be done with downloaded executables.
It is somewhat different when your system forces binaries to be signed... but yeah, largely agreed. The abject refusal of curl|sh is strange to me, unless the refusers are also die-hard GPL adherents. Binaries are significantly more opaque and easier to hide malware in, in almost all cases.
Wait till they find out what the Visual Studio Installer itself does :) I guess this person just trusts a big company like Microsoft who keeps their source hidden more than a single developer who publishes all their source?
If any of this is relevant to you, you're already running Windows, which means Microsoft already has root on your machine, which means it's futile to try to limit the extent to which you trust their binaries.
I know Jonathan Marler for some of his Zig talks and his work in the win32 api bindings for Zig[0], they are even linked from Microsoft's own repo[1] (not sure why he has 2 github users/orgs but you can see it's the same person in the commits).
[0] https://github.com/marlersoft/zigwin32 [1] https://github.com/microsoft/win32metadata
I would guess one of his accounts is his corporate employee account and his other is personal.
Is this post AI-written? The repeated lists with highlighted key points, the "it's not just [x], but [y]" and "no [a] just [b]" scream LLM to me. It would be good to know how much of this post and this project was human-built.
I was on the fence about such an identification. The first "list with highlighted key points" seemed quite awkward to me and definitely raised suspicion (the overall list doesn't have quite the coherence I'd expect from someone who makes the conscious choice; and the formatting exactly matches the stereotype).
But if this is LLM content then it does seem like the LLMs are still improving. (I suppose the AI flavour could be from Grammarly's new features or something.)
> "The key insight is..."
This was either written by Claude or someone who uses Claude too much.
I wish they could be upfront about it.
Perhaps people have mimicked the style because LLMs have popularized it and clearly it serves some benefit to readers.
Perhaps LLMs have mimicked the style because authors have popularized it and clearly it serves some benefit to readers.
> have popularized it
It's hated by everyone, why would people imitate it? You're inventing a rationale that either doesn't exist or would be stupider than the alternative. The obvious answer here it they just used an LLM.
> and clearly it serves some benefit to readers.
What?
> It's hated by everyone, why would people imitate it?
It could be involuntary. People often adopt the verbal tics of the content they read and the people they talk with.
Then why does every vibe-coded "Show HN" app have it in README.md? Surely authors would edit it out if it was true that everyone hates it.
I love the style it was written in. I felt a bit like reading a detective novel, exploring all terrible things that happened and waiting for a plot twist and hero comming in and saving the day.
you know why LLMs repeat those patterns so much? because that's how real humans speak
Real humans don't speak in LinkedIn Standard English
"LinkedIn Standard English" is just the overly-enthusiastic marketing speak that all the wannabe CEOs/VCs used to spout. LLMs had to learn it somewhere
> LinkedIn Standard English
We need a dictionary like this :D
The old Unsuck-it page comes pretty close. I’m not a huge fan of the newer page though. https://www.unsuck-it.com/classics
LinkedIn and its robotic tone existed long before generative AI.
Know what's more annoying than AI posts? Seeing accusations of AI slop for every. last. god. damned. thing.
Yes that's the point. LLMs pretty much speak LinkedInglish. That existed before LLMs, but only on LinkedIn.
So if you see LinkedInglish on LinkedIn, it may or may not be an LLM. Outside of LinkedIn... probably an LLM.
It is curious why LLMs love talking in LinkedInglish so much. I have no idea what the answer to that is but they do.
It is at least thematically appropriate, of course a corporate-built language machine speaks like LinkedIn.
The actual mechanism, I have no clue.
I'm so fucking tired of this
I last developed for windows in the late 90s.
I came back around 2017*, expecting the same nice experience I had with VB3 to 6.
What a punch in the face it was...
I honestly cannot fathom anyone developing natively for windows (or even OSX) at this day and age.
Anything will be a webapp or a rust+egui multi-plataform developed on linux, or nothing. It's already enough the amount of self-hate required for android/ios.
* not sure the exact date. It was right in the middle of the WPF crap being forced as "the new default".*
> Is this post AI-written?
What if it was?
What if it wasn't?
What if you never find out definitely?
Do you wonder that about all content?
If so, doesn't that get exhausting?
Yeah, it does. Congratulations, you figured out why the future is going to be fucking awful.
"What if you can't tell the difference?" Yeah, what if it becomes impossible to spot who's a lazy faker who outsourced their thinking? Doesn't that sound great?!
What's exhausting is getting through a ten-paragraph article and realising there was only two paragraphs of actual content, then having to wade back through it to figure out which parts came from the prompt, and which parts were entirely made up by the automated sawdust injector.
That's not an AI problem, it's a a general blog post problem. Humans inject their own sawdust all the time. AI, however, can write concisely if you just tell it to. Perhaps you should call this stuff "slop" without the AI and then it doesn't matter who/what wrote it because it's still slop regardless.
I completely agree with your parent that it's tedious seeing this "fake and gay" problem everywhere and wonder what an unwinnable struggle it must be for the people who feel they have to work out if everything they read was AI written or not.
It used to require some real elbow grease to write blogspam, now it's much easier.
I hardly ever go through a post fisking it for AI tells, they leap out at me now whether I want them to or not. As the density of them increases my odds of closing the tab approach one.
It's not a pleasant time to read Show HNs but it just seems to be what's happening now.
> and wonder what an unwinnable struggle it must be for the people who feel they have to work out if everything they read was AI written or not
Exactly!
It never used to be a general blog post problem. It was a problem with the kinds of blogs I'd never read to begin with, but "look, I made a thing!" was generally worth reading. Now, I can't even rely on "look, I made a thing!" blog posts to accurately describe the author's understanding of the thing they made.
I analyzed the test using Pangram, which is apparently reliable, it say "Fully human Written" without ambiguity.[1]
I personally like the content and the style of the article. I never managed to accept going through the pain to install and use Visual Studio and all these absurd procedures they impose to their users.
[1] https://www.pangram.com/history/300b4af2-cd58-4767-aced-c4d2...
This honestly just tells me that Panagram is hot garbage
These days I'm always wondering whether what I'm reading is LLM-slop or the actual writing of a person who contracted AI-isms by spending hours a day talking to them.
Fantastic work! It's a long-needed breath of fresh air for the Visual Studio DX. I wish msvcup was existed when they made us use it back during Uni.
Alternatively, there's this:
Install Visual Studio Build Tools into a container to support a consistent build system | Microsoft Learn
https://learn.microsoft.com/en-us/visualstudio/install/build...
Why not use winget to do it?
`winget install --id Microsoft.VisualStudio.2022.BuildTools`.
If you need the Windows(/App) SDK too for the WinRT-features, you can add `winget install --id Microsoft.WindowsSDK.10.0.18362` and/or `winget install --id Microsoft.WindowsAppRuntime.1.8`
Having been the person that used to support those packages, it’s not that simple. You need to pass what workloads you need installed too, and if it’s a project you’re not familiar with god help you.
I used to just install the desktop development one and then work through the build errors until I got it to work, was somewhat painful. (Yes, .vsconfig makes this easier but it still didn’t catch everything when last I was into Windows dev).
I wish open source projects would support MingW or at least not actively blocking it's usage. It's a good compiler that provides an excellent compatibility without the need of any extra runtime DLLs.
I don't understand how open source projects can insist on requiring a proprietary compiler.
There are some pretty useful abstractions and libraries that MinGW doesn't work with. Biggest example is the WIL[1], which Windows kernel programmers use and is a massive improvement in ergonomics and safety when writing native Windows platform code.
I fail to see why this would not work with gcc if it works with clang. The runtime?
'MinGW' is not GCC; it's an ABI, and from the developer perspective it is also the headers and the libraries. You can have GCC MinGW, Clang MinGW, Rust MinGW, Zig MinGW, C# AOT MinGW.
To answer your question, the headers.
if you want to link msvc built libraries (that are external/you dont have source), mingw may not be an option. for an example you can get steamworks sdk to build with mingw but it will crash at runtime
Agreed I also like to see more support for MingW especially from open source projects. Not even a passing mention in this blog post.
Eww no. MingW is evil and no project should ever use it.
Just use Clang + MSVC STL + WinSDK. Very simple.
From the capitalization I can tell you and the parent might not be aware it's "minimal GNU for Windows" which I would tend to pronounce "min g w" and capitalize as "MinGW." I used to say ming. Now it's my little friend. Say hello to my little friend, mang.
I typically refer to it as “piece of garbage poop I don’t let infect my system”.
Or... you can
"winget install Microsoft.VisualStudio.BuildTools"
"winget install Microsoft.WindowsSDK.10.0.26100"
I thought for a moment I was missing something here. I always just use winget for this sort of thing as well. It may kickoff a bunch of things, but it’s pretty low effort and reliable.
But those are installed system wide. What if you have two different project with different requirements at the same time?
Every language should have a tool like Python uv.
> What if you have two different project with different requirements at the same time?
Install multiple versions of Windows SDK. They co-exist just fine; new versions don’t replace old ones. When I was an independent contractor, I had 4 versions of visual studio and 10 versions of windows SDK all installed at once, different projects used different ones.
You can provide custom options to winget, and in there where to install it too (and additional components you need).
Nearly all of the Windows hate i see comes from 20 year old takes . ( the bing/cortana / copilot / ads slop criticism is warranted, but is also easily disabled).
You can do a lot of "native" windows development from modern C#/.NET via win32 interop.
Newer C# features like ref returns, structs, spans, et. al., make the overhead undetectable in many cases.
Exactly, the major pain point remains the .NET allergy from Windows team, but it is workable.
> It’s so vast that Microsoft distributes it with a sophisticated GUI installer where you navigate a maze of checkboxes, hunting for which “Workloads” or “Individual Components” contain the actual compiler. Select the wrong one and you might lose hours installing something you don’t need.
I have a vague memory of stumbling upon this hell when installing the ldc compiler for dlang [1].
1. https://wiki.dlang.org/Building_and_hacking_LDC_on_Windows_u...
I’ve found that just installing LLVM, CMake and Ninja is enough to get started developing on Windows for most things C/C++.
I don't really use Windows OS much, but why not just use MinGW? Then you have Clang on all platforms you can think of: Android, all the various Darwin flavors and of course Linux and Windows; as well as on platforms you can't think of like FreeBSD or even Haiku maybe? Like honestly what's the point of supporting MSVC at all?? Maybe I'm just not enough of a Windows nerd to understand? (so I'm basically wondering if mingw has any drawbacks)
If you have a self-contained project, where you don't depend on anyone else and others don't depend on you, MinGW works great. Problems arise when you have dependencies that don't work with it. I'd love to see if MinGW could find a way to be binary compatible with MSVC-compiled binaries. Right now it's kind of an all or nothing solution which makes it hard to adopt.
Ah, binary-only dependencies, right… That's very specific though, so unless you need to drive some proprietary hardware, why bother using stuff that forces you into MSVC hell lol? Also wouldn't LLVM based MinGW benefit from Clang's MSVC compat? Not sure about this at all, that's why I'm asking, heh… ^^"
For big C++ projects, the .vsconfig import/export way of handling Visual Studio components has worked well for the large teams I'm on. Tell someone to import a .vsconfig and the Visual Studio Installer does everything. Only times we've had issues is from forgetting to update it with components/SDK changes.
Yeah, seems like this is just ignorance around .vsconfig files. Makes life way easier. You can also just use the VS Build Tools exe to install things instead of the full VS installer, if you plan to use a different IDE.
Can you use .vsconfig to tell Build Tools what your project needs?
Can you generate .vsconfig with Build Tools?
You pass in the --config param to import it.
Exporting this way might be possible but it wouldn't be as useful seeing as it would just grab everything you have installed instead of some minimal set used by some project.
What we did for out build agents was to just install the required version of build tools via chocolatey. But cool approach!
> No Visual Studio installation. No GUI. No prayer. Just a script that does exactly what it says.
Yeah its obvious clanker writing. I don't even mind using LLM for code but this rubs the wrong way.
Actually not that complicated: You simply check in a global.json [0] where you specify the sdk and workload versions.
Then you also specify target platform sdk versions in the .csproj file and VS will automatically prompt the developer to install the correct toolchain.
[0] https://learn.microsoft.com/en-us/dotnet/core/tools/global-j...
global.json is only for .NET toolchains.
What you’re actually wanting here is .vsconfig https://learn.microsoft.com/en-us/visualstudio/install/impor...
It starts by not looking into Windows through UNIX developer glasses.
The only issue currently plaguing Windows development is the mess with WinUI and WinAppSDK since Project Reunion, however they are relatively easy to ignore.
>It starts by not looking into Windows through UNIX developer glasses.
People don't need any UNIX biases to just want multiple versions of MSVS to work the way Microsoft advertises. For example, with every new version of Visual Studio, Microsoft always says you can install it side-by-side with an older version.
But every time, the new version of VS has a bug in the install somewhere that changes something that breaks old projects. It doesn't break for everybody or for all projects but it's always a recurring bug report with new versions. VS2019 broke something in existing VS2017 installs. VS2022 broke something in VS2019. etc.
The "side-by-side-installs-is-supposed-to-work-but-sometimes-doesn't" tradition continues with the latest VS2026 breaking something in VS2022. E.g. https://github.com/dotnet/sdk/issues/51796
I once installed VS2019 side-by-side with VS2017 and when I used VS2017 to re-open a VS2017 WinForms project, it had red squiggly lines in the editor when viewing cs files and the build failed. I now just install different versions of MSVS in totally separate virtual machines to avoid problems.
I predict that a future version VS2030 will have install bugs that breaks VS2026. The underlying issue that causes side-by-side bugs to re-appear is that MSVS installs are integrated very deeply into Windows. Puts files in c:\windows\system32, etc. (And sometimes you also get the random breakage with mismatched MSVCRT???.DLL files) To avoid future bugs, Microsoft would have to re-architect how MSVS works -- or "containerize" it to isolate it more.
In contrast, gcc/clang can have more isolation without each version interfering with each other.
I'm not arguing this thread's msvcup.exe tool is necessary but I understand the motivations to make MSVS less fragile and more predictable.
Note that this also doesn't work on Linux - your system's package manager probably has no idea how to install and handle having multiple versions of packages and headers.
That's why docker build environments are a thing - even on Windows.
Build scripts are complex, and even though I'm pretty sure VS offers pretty good support for having multiple SDK versions at the same time (that I've used), it only takes a single script that wasn't written with versioning in mind, to break the whole build.
> Note that this also doesn't work on Linux - your system's package manager probably has no idea how to install and handle having multiple versions of packages and headers.
But this isn’t true. Many distros package major versions of GCC/LLVM as separate packages, so you install and use more than one version in parallel, no Docker/etc required
It can indeed be true for some things-such as the C library-but often not for the compilers
The closest thing I saw to this was some vendors shipping their SDKs with half the desktop userland (in a similar 'blob' fashion the post complains about), with shell scripts setting up paths so that their libs and tools are found before system ones.
Until the day there is that symlink, or environment variable with the incorrect value.
Yes. Any user interface toolkit that isn't at least 10 years old should be ignored on windows unless you want to rewrite everything one day.
Why? You may end up with something that doesn't get much attention anymore, but none of the official gui approaches have ever been removed as far as I know. Win32, MFC, winforms, wpf, winui, maui are all still available and apps using them are functional. Even winjs still works apparently, even if it was handed over.
I wouldn't start an app in most of them today, but I wouldn't rewrite one either without a good reason.
Well a number of them have horrific bugs in them which have zero attention. At least win32 has an abstraction level which allows you to work around them.
There’s a fun bug on WPF and form backgrounds for example which means on fractional DPI screens the background is tiled unpredictably. Had to patch that one up rather quickly one day and it was a mess due to how damn complicated WPF is.
I wonder if people still use WinForms, MFC and WPF...
Still migrating an enterprise app off WPF to this day.
What are you moving to out of interest? I’ve seen people talking of moving ours to Electron which seems to just be more problems waiting.
Nitpick, "Windows Native Development" also refers to the NT native subsystem, which would be basically coding against private APIs instead of Win32. From the title I thought that's what this was. Then I realized it was about avoiding full use of Visual Studio when building C projects (something that a lot of people already do by the way)
This is amazing.
At $workplace, we have a script that extracts a toolchain from a GitHub actions windows runner, packages it up, stuffs it into git LFS, which is then pulled by bazel as C++ toolchain.
This is the more scalable way, and I assume it could still somewhat easily be integrated into a bazel build.
Keeping CI entirely out of windows desktop development is the biggest efficiency and cost improvement I've seen in the last 15 years. Our CI toolchain broke so we moved back to a release manager doing it manually. It takes him 20x less time to build it and distribute it (scripted) than it does to maintain the CI pipeline and his desktop machine is several times faster than any cloud CI node we can get hold of.
Edit: Uses a shit load less actual energy than full-building a product thousands of times that never gets run.
This is really interesting. Do you think it’s possible server-deployed software could also get similar efficiencies with adequate testing?
Yeah it really doesn’t matter where you build stuff. The big push to CI is from companies that want to sell you a service to do it.
Software should build and test the same everywhere. If you have to use it, CI should only wrap that.
* Is this allowed per VS' ToS?
* I wonder if Microsoft intentionally doesn't provide this first party to force everyone to install VS, especially the professional/enterprise versions. One could imagine that we'd have a vsproject.toml file similar to pyproject.toml that just does everything when combined with a minimal command line tool. But that doesn't exist for some reason.
Microsoft doesn't seem to care unless you're a company. That's the reason community edition is free. Individual licenses would be pennies to them, and they gain more than that by having a new person making things in their ecosystem. It's in their interest to make their platform accessible as possible.
Visual Studio does have that functionality, via vsconfig files: https://learn.microsoft.com/en-us/visualstudio/install/impor...
Doesn't look like it's versioned, or installs Visual Studio itself.
For Visual Studio components that are versioned (like the C++ compilers/libraries), the version number is included in the component name.
You still have to install the tool that processes pyproject.toml so that doesn’t seem fair to hold against it. You are right that you still have to know whether to install 2022 or 2026.
Curl the VS Build tools exe, then run the build tools command to install what's in the .vsconfig.
I hope it would work with wine. Then cross compiling Win64 binaries from Linux would become convenient without requiring spinning up a Windows VM.
Yeah I noticed wine wasn't able to execute the MSI files. It also had a problem with the lock files. Both problems should be fixable though.
Last I checked the license for the headless toolchain requires that a full licensed copy of Visual Studio be installed somewhere. So I think this violates the license terms.
A bug got opened against the rustup installing the headless toolchain by itself at some point. I'll see if I can find it
edit: VSCode bug states this more clearly https://github.com/microsoft/vscode/issues/95745
As someone who is out of the loop on Windows development, is this related to the Windows Driver Kit (WDK, I think it used to be DDK)? That's a certain type of hell I don't wish upon most.
WOW such a great work. Myself I have been struggling with Mingw just to compile from source. Of course it works much cleaner then the hated visual studio, but then when it comes to cuda compile, that´s it. Visual studio or the magority our there, It is invasive and full of bloatware like you say. Same struggle with electron.
How to match it with cuda to compile from source the repos?
> On Linux, the toolchain is usually just a package manager command away. On the other hand, “Visual Studio” is thousands of components.
That package manager command, at the very least, pulls in 50+ packages of headers, compilers, and their dependencies from tens of independent projects, nearly each of them following its own release schedule. Linux distributions have it much harder orchestrating all of this, and yet it's Microsoft that cannot get its wholly-owned thing together.
One day I decided to port my text editor to Windows. Since it depends on pcre2 and treesitter, these two libraries had to be provided by the system.
In the span of ~2hrs I didn't manage to find a way to please Zig compiler to notice "system" libraries to link against.
Perhaps I'm too spoiled by installing a system wide dependency in a single command. Or Windows took a wrong turn a couple of decades ago and is very hostile to both developers and regular users.
I think providing purely-functional libraries as system dependencies that's tied to the whole tool chain at the time was the wrong decision by the Unix world.
The system libraries should only ship system stuff: interaction with the OS (I/O, graphics basics, process management), accessing network (DNS, IP and TLS). They should have stable APIs and ABIs.
Windows isn't hostile. It has a differnt paradigm and Unix (or more correctly usually GNU/Linux) people do not want to give up their worldview.
PCRE is basically only your apps's dependency. It has nothing else to do the rest of the operating system. So it is your responsibility to know how to build and package it.
If you depend on a library and can't figure out how you would compile against it, it's probably better for the end user that you don't make anything because you'll still need to package it up later unless you link statically.
System wide dependencies is fundamentally an awful idea that is wrong and you should never ever do it.
All dependencies should be vendored into your project.
This is the answer. I don’t know what is the best practise but for windows the easiest solution is to put the DLL in the same directory as the exe
I suspect the pitfall is how you or the zig compiler is linking. Unless you're involving things which vary by OS like hardware interaction, networking, file systems etc, you should not, with a new Lang in 2026, need to do anything special for cross-platform capabilities.
My understanding that "linkSystemLibrary" abstraction in build.zig only holds for Unix systems. And this in turn makes it impossible to build my program on Windows without modifying the build script.
I don't get why people go through all these flaming hoops and hurdles to deal with MSVC when MinGW and MinGW-w64/MSYS2 are options. In the latter case you even still get (mostly complete) MSVC ABI-compatibility if you compile with clang.
MinGW and MinGW-64/MSYS2 are just as inscrutable, fragile and new-user-hostile. The fact that you have to choose between MinGW (which has a 64 bit version) or MinGW64 (completely separate codebases maintained by different people as far as I can tell) is just the first in a long obstacle course of decisions, traps, and unexplained acronyms/product names. There are dozens of different versions, pre-built toolchains and packages to throw you off-course if you choose the wrong one.
If you're just a guy trying to compile a C application on Windows, and you end up on the mingw-w64 downloads page, it's not exactly smooth sailing: https://www.mingw-w64.org/downloads/
MinGW/MSYS2 are flaming poop hurdles. That’s the bending over backwards to fake a hacky ass bad dev environment. Projects that only support MinGW on Windows are projecting “don’t take windows seriously”.
Supporting Windows without MinGW garbage is really really easy. Only supporting MinGW is saying “I don’t take this platform seriously so you should probably just ignore this project”.
Came in getting ready to hate on this article, but was actually pleasantly surprised, this is great. Good work OP.
Please add also the support for the clang-cl[1][2].
And here I was messing with MingW64…
This is fantastic and someone at Microslop should take notes.
Exacly.. I avoid Visual Studio.. I try to build everthing using Mingw..
Clang is the better alternative to MinGW because it can use standard Windows libraries and avoids the need for additional runtime.
Can you actually do cross compilation (on Linux host to win64 binary) with clang in the same way as MingW does out of the box though?
No. You cannot even do direct compilation on the same host and target with clang only.
LLVM doesn't come with the C library headers (VCRuntime) or the executable runtime startup code (VCStartup).Both of which are under Visual Studio proprietary licenses. So to use Clang on Windows without Mingw, you need Visual Studio.
I use MingW without any extra libs (no msys), it just uses the ancient msvcrt.dll that is present in all Windows versions, so my programs work even on Windows 2000.
Additionally the cross-compiler on Linux also produces binaries with no extra runtime requirements.
You can use Mingw-w64 UCRT or CLANG environments that come with MSYS2.
Compared to older Mingw64 environments those link with the latest UCRT so you get almost the same style executable as Visual Studio.
The only difference for C is that it uses Mingw exception handling and global initialization code, and it uses Itanium ABI for C++.
But that's the point, I don't want the same style executable as Visual Studio. Having to distribute bunch of DLLs and having worse compatibility is pretty bad.
A major part of the incompatibility with older versions of Windows is just because newer VS runtimes cut the support artifically. That's it. Many programs would otherwise work as-is or with just a little help.
yeah, you can get away with this now a days because Git itself installs 2/3rds of the things you need anyway. You just need to finish the job by getting the package and putting the binaries in your git folder. Bam! mingw64, clang, what ever cc you need. It all links to standard windows stuff because you have to tell the linker where your win32.lib is. But this is true no matter the compiler, it's just Visual Studio supplies this in some god awful Program Files path.
Just msys2 it all
MSYS2 is horrible. It brings a massive runtime environment and is a bad idea to foist on users.
Aren’t you thinking of Cygwin, or the MSYS2 shell (dev tooling)?
The Windows-native software you build with MSYS2 can be shipped to and run by users that don’t have anything of MSYS2 installed.
He must be thinking of Cygwin as half of this is installed when you install git ;) Git Bash, etc…
MSYS2 is repacked Cygwin though. It is literally the same codebase compiled with slightly different flags. You need a full Unix environment for Bash to run, not just Mingw toolchain. The difference is Cygwin aims to create a full Unix system while MSYS2 just enough development environment to run bash, make etc to build native Windows programs with Mingw.
Git installs its own Mingw and Msys2 stuff but mostly compiled for a Mingw environment so they consume Windows paths natively instead of using MSYS2/Cygwin path conversion. That's why when you have mixed PATH variable all hell breaks loose with Git.
A repacked Cygwin is one environment, but the default uses the UCRT from Microsoft.