by 1718627440 | 2025-10-27 10:01:10+00:00
> On Linux it's shared, on Windows its not.

Yes, the default compiler invocation makes all symbols exported. But leaving it like that is super lazy, it will likely break things (like you wrote). You can change the default with -fvisibility=[default|internal|hidden|protected] and it's kind of expected that you do. Oh, and I just found out that GCC has -fvisibility-ms-compat, to make it work like the MS compiler.

> Instead you link against a thin, small import lib called (ideally) foo.imp.lib.

Interesting. How is that file created? Is it created automatically, when you build foo.dll? How is it shipped? Is it generally distributed with foo.dll, because then I don't really see the benefit of linking against foo2.15.imp.lib compared to foo2.15.dll.

> It should be trivial to link against glibc2.15 even if your system is on glibc2.40.

It don't know if you know that, but on Linux glibc2.40 is not really only version 2.40. It includes all the versions up to 2.40. When you link against a symbol that was last changed in 2.15, you link against glibc2.15, not against glibc2.40. If you only use symbols from glibc2.15, then you have effectively linked the complete program against glibc2.15.

But yes, enforcing this should be trivial. I think this a common complaint.

> The Linux Way is to install shared libraries into the global path.

Only in so far, as on Windows you put the libraries into 'C:\Program Files\PROGRAM\' and on Linux into '/usr/lib/PROGRAM/'. You of course shouldn't dump all your libraries into '/usr/lib'. That's different when you install a library by itself. I don't know how common that is on Windows?

I don't really know what problems you have in mind, but it seems like you think a program would have a dependency on 'libfoo.so', so at runtime it could randomly break by getting linked against another libfoo, that happens to be in the library path. But that is not the case, you link against '/usr/lib/foo.so.6'. Relying on runtime environment paths for linking is as bad as calling execve("bash foo") and this is a security bug. Paths are for the user, so that he doesn't need to specify the full path, not for programs to use for dependency management. Also when you don't want updates to minor versions, then you can link to '/usr/lib/foo.so.6.2'. And when you don't want bugfixes, you can link against '/usr/lib/foo.so.6.2.15', but that would be super dumb in my opinion. On Linux ABIs have there own versions differently from the library versions, I agree that this can be confusing for newcomers.

A fundamentally difference is also that there is a single entity controlling installation on Linux. It is the responsibility of the OS to install programs, bypassing that just creates a huge mess. I think that is the better way and both Apple and Microsoft are moving to that way, but likely for other reasons (corporate control). This doesn't mean, that the user can't install his own programs which aren't included in the OS repository. OS repository != OS package manager. I think when you can bother to create foo-installer.exe, you should also create foo.deb . Extracting foo.zip into C:\ is also a dumb idea, yet some people think it suddenly isn't dumb anymore when doing it on Linux.

PIP and similar projects are a bad idea, in my opinion. When someone wants to create their own package system breaking the OS, they should have at least the decency to roll it in /opt. Actually that is not a problem in Python proper. They have essentially solved that for decades and all that dance with venv, uv and what else is completely unnecessary. You can install different Python installation into the OS path. Python installs into /usr/bin/python3.x and creates /usr/lib/python3.x/ by default. Each python version will only use the appropriate libraries. That's my unpopular opinion. That mess is why Docker was created, but in my opinion that does not come from following the Linux way, but by actively sabotaging it.

> Also, super duper unpopular opinion, but bash sucks and any script longer than 10 lines should be written in a real language with a debugger.

Bash's purpose is to cobble programs together and setup pipes and process hierarchies and job control. It excels at this task. Using it for anything else sucks, but I don't think that is widely disputed.