Considering the level of the API. But it is total opposite comparing a bit deeper. Linux has a famous rule "WE DO NOT BREAK USERSPACE!" e.g. [1].
^1 https://docs.kernel.org/admin-guide/syscall-user-dispatch.ht...
A bit more comparable is OpenBSD where applications are very much expected to only use libc wrappers, which threw a wrench into the works for the Go runtime.
Which is perfectly fine to do and guaranteed to work forever because of Linus's policy that kernel updates aren't allowed to break userspace programs.
If in doubt, try and find examples of its breakage, semantic changes, etc.
It's the opposite of that. The Linux syscall is more stable than the (gnu)libc.
The right thing to do? I don't see why I would want to use libc.
And frankly, the Windows way is better. On Linux, the 'ABI' for nearly all user-mode programs is not the kernel's ABI but rather glibc's (plus the variety of third-party libraries, because Win32 has a massive surface area and is an all-in-one API). Now, glibc's ABI constantly changes, so linking against a newer glibc (almost certainly the 'host' glibc, because it is almost impossible to supply a different 'target' glibc without Docker) will result in a program that doesn't run on older glibc. So much for Torvalds' 'don't break userspace'.
Not so for a program compiled for 'newer' Win32; all that matters are API compatibilities. If one only uses old-hat interfaces that are documented to be present on Windows 2000, one can write and compile one's code on Windows 11, and the executable will run on the former with no issues. And vice versa, actually.
Glibc is userspace seen from the perspective of the Linux kernel.
Cygwin is also 'just a wrapper' for the Native API and Win32, and look how drastically it changes the ABI of applications.
Linux is the exception offering its guts to userspace with guarantees of stability.
Funny that you would be arguing for that (unless I misunderstood the intention), given your many other posts about how C is a horrible broken unsafe language that should not be used by anyone ever. I tend to agree with that, btw, even if not so much with the "memory safety" hysteria.
Should every program, now and in the future, be forced to depend on libc, just because it's "grandfathered in"?
IMO, Linux is superior because you are in fact free to ignore libc, and directly interface with the kernel. Which is of course also written in C, but that's still one less layer of crud. Syscalls returning error codes directly instead of putting them into a thread-local variable would be one example of that.
Should a hypothetical future OS written in Rust (or Ada, ALGOL-68, BLISS, ...) implement its own libc and force userspace appplications to go through it, just because that's "proper"?
In traditional UNIX, there is no libc per se, there is the stable OS API set of functions and that's it.
When C was standardised, a subset of the UNIX API became the ISO C standard library, aka libc. When it was proven that wasn't enough for portable C code, the remaining UNIX API surface became POSIX.
Outside UNIX, libc is indeed a thing, because many of those OSes aren't even written in C, just like your language lists example, in those OSes libc ships with C compiler, not the OS per se, as you can check by diving into VMS documentation before it became OpenVMS, or IBM and Unisys systems, where libc is also irrelevant if using PL/I, NEWP, whatever.
Also on Windows, you are not supposed to depend on libc unless you are writing portable C code, there isn't one libc to start with. Just like everyone else, each compiler ships their own C runtime library, and nowadays there is also universal C runtime as well, plenty of libc choices.
If not writing portable C code, you aren't supposed to use memset(), rather FillMemory ().
Same applies to other non-UNIX OSes, you would not be calling memset(), rather the OS API for such service.
To make your code portable? Linux-only software is even worse than Windows-only
Because that's the stable public interface provided by pretty much every OS except Linux. On Linux, if you don't want to depend on the OS-supplied libc, you can use musl.