Tangential, Winamp 2.xx from the '90s runs and plays MP3s just fine on Windows 11 today. There are better apps for that today, but I still use it because nostalgia really whips the llama's ass.
Pretty wild that the same thing is not the norm in other OSs.
Even wilder is that I still have my installed copy of Unreal Tournament 99 from my childhood PC copied over to my current Win 11 machine, and guess what, it just works out of the box, 3D graphics, sound, everything. That's nearly 25 years of backwards compatibility at this point.
If that's not stable, I don't know what is.
If we look back to programs written for Windows NT 3.1, released in 1993, and assume they run on Windows 11 (because why not?) then that's 30 years of backwards compatibility.
Did I say mindblowing? It's downright mythological what Microsoft achieves and continues to do.
That would have given 16, 32, and 64 bit compatibility.
I don't want to estimate how much such hacks they accumulated over time to keep things as compatible as they could.
This seems like it was meant in a positive way, but I really don't think that if compatibility with your system requires "mythological" efforts, that should be seen as a good thing for your system.
It's also worth noting that backwards ABI compatibility only masters when people limit their software by not distributing the source. Early UNIX software can run fine on modern GNU by just compiling it.
API Compatibility Is All You Need ;)
...providing you can find a suitable compiler that isn't obsessed with exploiting undefined behaviour.
Have you ever tried building decades old programs from source? It's not as easy as you claim.
Here's source for grep from v6 unix. I'd be interested to know the smallest set of changes (or flags to gcc) needed to get it to compile under gcc on linux and work.
https://github.com/takahiro-itazuri/unix-v6/blob/0316b457acb...
Still, there is only one actual error in gcc 13.2.1 which is the use of =| instead of the later standardized |=. I'm not sure if that was a common thing back then or if it was specific to their C compiler. Either way, I don't think gcc has a switch to make it work. Switching that around in the source gives linker errors since it seems back then the way to print to or flush a particular file descriptor was to set a libc variable and then call flush or printf. If you had the right libc to use with it that one tiny change might be all you need. But you would likely need to set up a cross compile to be able to use the right libc.
My understanding is that most of the compatability issues on Linux are due to not having the right libraries rather than the kernel not supporting older system calls. It is just a lot of not that fun work to keep things working and no one is that interested (instead, some people just use decade old versions of Linux :/ and the rest use package systems to recompile stuff). NetBSD had better practical binary compatability for a long time, although I think some of it was remove fairly recently since there isn't much commercial NetBSD software (there was one lisp binary from 1992ish IIRC that some people were still using and I think that compat was kept).
But I don't think it was unfair to use that as an example of early Unix software, or to point out that it was harder than "just compiling it". One defense against my argument could be that a version of 'grep' has been maintained through C versions and operating systems, with source code availability playing a part in that (although presumably GNU grep avoided using Unix source code).
Something like xv (last release: 1994, although the binaries were built against Red Hat 5.2 from 1998) still work today, and the source still builds with one very minor patch last time I tried it.
The problem running the binaries is:
% ldd ./usr/X11R6/bin/xv
linux-gate.so.1 (0xf7f82000)
libX11.so.6 => /usr/lib32/libX11.so.6 (0xf7e22000)
libjpeg.so.62 => not found
libpng.so.2 => not found
libz.so.1 => /usr/lib32/libz.so.1 (0xf7e08000)
libm.so.6 => /usr/lib32/libm.so.6 (0xf7d0b000)
libc.so.6 => /usr/lib32/libc.so.6 (0xf7a00000)
libxcb.so.1 => /usr/lib32/libxcb.so.1 (0xf7cde000)
/lib/ld-linux.so.2 => /usr/lib/ld-linux.so.2 (0xf7f84000)
libXau.so.6 => /usr/lib32/libXau.so.6 (0xf7cd8000)
libXdmcp.so.6 => /usr/lib32/libXdmcp.so.6 (0xf7cd1000)
And Windows has exactly the same problem, but the tradition is to ship these things with the application rather than just assume they're present on the system. And you can "fix" it by getting old versions, or even: % ln -s /usr/lib/libjpeg.so.8 libjpeg.so.62
% ln -s /usr/lib/libpng16.so.16 libpng.so.2
You'll probably run in to trouble with PNG and JPEG files, but e.g. loading/saving GIF and whatnot works fine. Note how libc and libX* work out of the box.tl;dr: much of the "Windows compatibility" is just binaries shipping with all or most dependencies.
Try it yourself: http://www.trilon.com/xv/downloads.html
Available API means the whole stack, everything needed to write applications end to end, regardless of their purppose, not CLI and daemons.
And this is what Windows does too really, with MSVC and dotnet and whatnot redistributables. It's just that these things are typically included in the application if you need it.
It's really not that different aside from "Python vs. Ruby"-type-differences, which are are meaningful differences, but also actually aren't all that important.
Got no counterexamples? Then it's not FUD at all, rather a pure truth.
What is? An immense amount of resources (developers) poured into developing live patches to make applications work on each newer version of Windows (or helping the application developers fix their applications). It's an interesting conceptual grey area - I don't consider it backward compatibility in a strict sense.
This is documented in the book "The old new thing" by Raymond Chen (it's possible also to read the blog, but the book gives an organic view).
It's fascinating how far-sighted Microsoft was; this approach, clearly very expensive, has been fundamental in making Windows the dominant O/S (for desktop computers).
The user ultimately doesn't care if his computer is an x86 or an ARM or a RISC-V, or if it's running Windows or Mac or Linux or Android. What the user cares about is running Winamp to whip some llama's ass, or more likely opening Excel to get work done or fire up his favorite games to have fun.
Microsoft respects that, and so strives to make sure Windows is the stepping stone users can (and thusly will) use to get whatever it is they want to do done.
This is fundamentally different to MacOS, where Apple clearly dictates what users can and cannot do. This is fundamentally different to FOSS, where the goal is using FOSS and not what FOSS can be used for.
It's all simple and obvious in hindsight, but sometimes it's the easiest things that are also the hardest.
Windows APIs are probably a mess because of this (also ignoring the fact that only company with extremely deep pockets can afford this approach). There is at least one extreme case where Windows had to keep a bug, because a certain program relied on it, and couldn't be made to work otherwise.
Just in the sense that 100% of the people who use the phrase "backward compatibility" mean.
I also wish I could agree that win32 is a stable target on Linux; it may run old software, but in my experience it is often quirky. It's usually a better use of my time to just boot windows thanks to figure out how to get software to run under wine.
Another abi I see games target are ubuntu... 14.04, 16.04, 18.04, etc
Ubuntu seems to be stable enough for the corporate world.
I think things like flatpack or snap add bloat and behave in ways you don't want.