4 ms·
What the author calls "software environments" are actually called "software distributions". And yes, being able to install a single version of each package is
by WhyNotHugo 3y ago
What the author calls "software environments" are actually called "software distributions".
And yes, being able to install a single version of each package is rather limiting.
The main idea of a software distribution, is that all software is packaged in coordination, and the versions in the repositories work with one another. E.g.: the packaged firefox will be built to work with the packaged version of libpng and fontconfig. And all other software packaged works with the same version of fontconfig too.
If there is a version mismatch and conflicts, this is usually resolved at a distribution level. Keep in mind that distributions nowadays are a lot more vanilla than the original BSD idea of a distribution. In BSD, a distribution has _ports_ of the software that is packaged, which uses the upstream source (of say, Firefox) plus patches to make it build and run on the distribution with the dependencies that it provides.
This approach substantially minimises the amount of build time required, the amount of storage required for packages and the amount of network consumed for distributing. It also makes security a lot easier, because all packages link to the system openssl, so in case of a security issue, only the openssl package needs to be updated (which is also a pretty small download compared to rebuilding everything that depends on it).
The modern model of "just put each thing it its own docker container with all its dependencies" is simple and works. It takes a lot less developer time to get things working, at the expense of essentially duplicating all dependencies for each package, making security a nightmare to follow, and rebuilding and distributing becomes a lot more expensive. But hey, if developer hours are expensive, maybe the cost of duplicating so much is smaller ir comparison.
A big problem nowadays is that many modern languages have evolved without consideration for users wanting multiple versions of a given dependency.
Let's look at Python for example. If you want to install a package, it goes into /usr/lib/python3.11/site-packages/$PACKAGE. Do you want two version of it? That's not possible. This is ultimately a language design issue.
Shared objects don't have this issue. For example, libssl3 on my system provides /usr/lib/libssl.so.3, but there's nothing preventing another package from providing /usr/lib/libssl.so.4 or /usr/lib/libssl.so.2, which means that I can concurrently install multiple versions of it. The same is true for libpng and a bunch of other tools.
Finally, I'll say that while NixOS and Flatpak provide novel approaches to solving these problems, they bring with them their own pile of complexity. However, I'm still thankful that someone develops these projects: what we learn through them will definitely help us continue iterating on how we distribute package in software in the future (although I honestly don't think either of those is the future).
- rlpb 3y ago> Let's look at Python for example. If you want to install a package, it goes into /usr/lib/python3.11/site-packages/$PACKAGE. Do you want two version of it? That's not possible. This is ultimately a language design issue. Python virtualenvs make this possible, and are accommodated for in Python's design decisions. I therefore don't think it's fair to say "that's not possible". You do need entirely distinct stacks, but that's necessary by definition. You can't have package A depend on packages B and C each of which depend on a different version of package D but expect to share API objects from D back through to A and therefore with each other. This would require some level of compatibility between versions of D, and there can be no guarantee of that.
- eqvinox 3y ago> You do need entirely distinct stacks, but that's necessary by definition. You can't have package A depend on packages B and C each of which depend on a different version of package D but expect to share API objects from D back through to A and therefore with each other. Shared objects do in fact allow doing the safe subset of this, which is to load 2 versions of D that are used by packages B and C without exchanging API objects. The C language has no good mechanism for enforcing this separation, as only one version of D's headers will be in use when compiling A, B and C. That said, there is a non-negligible number of situations (especially with libssl) where this is irrelevant because D is internal to one or both of B and C.
- rlpb 3y ago> Shared objects do in fact allow doing the safe subset of this, which is to load 2 versions of D that are used by packages B and C without exchanging API objects. It's a fair point. But in practice this can only be done when the versions of D have different sonames - at least with the usual filesystem layout we use for dynamic linking. In that respect, Python can do it too - we just don't typically embed the major version into our Python module names, as is typical with sonames.