Versioned symbols get added when a function or object breaks binary compatibility. You keep around the old version, and compile against the new version. This might be something simple like a struct layout change, or a change in the size of an array. Both versions have the same name. When you compile, you'll get an unversioned symbol reference. When you link, that will get resolved to whatever the latest version is.
Windows handles this by giving a new name to new symbols. For example, MoveFile(), MoveFileA(), MoveFileW(), MoveFileExA(), MoveFileExW(). You get the correct symbol when you compile, either by calling the correct function directly, or by referring to it by macro (MoveFileEx is a macro for MoveFileExA or MoveFileExW). Newer versions of Windows also make you embed the GUID of the versions of Windows you support in your application manifest, and Windows will run your application in a compatibility environment (at runtime) matching the latest available version you specify.
On macOS, similarly, it uses the preprocessor, but it's a bit different and macOS also supports something called "weak linking" (not the same thing as weak linking in GNU Binutils / ELF). Weak linking allows you to link against an old version of a library, but use a symbol from a newer version... if the symbol is not available, it is NULL. This is done with the preprocessor and the linker in tandem... there's a preprocessor macro which specifies which minimum&maximum version of macOS (or iOS, etc) you target, and that affects which symbols are declared as being weakly linked.
The long and the short of it... you can use the latest macOS SDK to make binaries compatible with old versions of macOS, and same for Windows, but glibc maintainers have not made this possible for glibc.