Retiring the multilib project

I created the Multilib project back in November 2013 (though the effort itself started roughly a year earlier) with the goal of maintaining the multilib eclasses and porting Gentoo packages to them. Back in the day, we were even requested to co-maintain a few packages whose maintainers were opposed to multilib ports. In June 2015, last of the emul-linux-x86 packages were removed and our work has concluded.

The project continued to exist for the purpose of maintaining the eclasses and providing advice. Today, I can say that the project has served its purpose and it is time to retire it. Most of the team members have already left, the multilib knowledge that we advised on before is now common developer knowledge. I am planning to take care of the project-maintained eclasses personally, and move the relevant documentation to the general wiki space.

At the same time, I would like to take this opportunity to tell the history of our little multilib project.

Gentoo before gx86-multilib

In the old days, the multilib as seen by the majority of Gentoo users consisted of two components: multilib toolchain packages and emul-linux-x86 packages.

The toolchain multilib support exists pretty much in its original form to this day. It consists of a multilib USE flag and an ABI list stored in the selected profile. The rough idea is that bootstrapping a toolchain with a superset of its current ABIs is non-trivial, so the users generally choose a particular multilib or non-multilib variant when installing Gentoo, and do not change it afterwards. The multilib project didn’t really touch this part.

The emul-linux-x86 packages were specifically focused on non-toolchain packages. Back in the day, they consisted of a few sets of precompiled 32-bit libraries for amd64. If you needed to run a proprietary 32-bit app or compile wine, they had to depend on a few sets, e.g.:

amd64? (
    app-emulation/emul-linux-x86-xlibs
    app-emulation/emul-linux-x86-soundlibs
)

The sets generally included the current stable versions of packages and were rebuilt every few months.

Simultaneously, an alternative to this solution was developed (and is being developed to this day): multilib-portage, a Portage fork that was designed specifically to build all packages for multiple ABIs. Unlike the other solutions, multilib-portage minimized development effort and worked on top of regular Gentoo packages. However, it never reached production readiness.

The gx86-multilib design

The gx86-multilib effort was intended to provide a multilib solution entirely within the scope of the Gentoo repository (still named gentoo-x86 at the time, hence the name), i.e. without having to modify EAPI or package managers. It was supposed to be something between emul-linux-x86 and multilib-portage, building all non-native libraries from source but requiring explicit support from packages.

It only seemed natural to utilize USE_EXPAND the same way as PYTHON_TARGETS did for Python. At the same time, splitting ABIs per architecture made it possible to use USE_EXPAND_HIDDEN to hide irrelevant flags from users. So e.g. amd64 multilib users see only ABI_X86, PPC64 users see ABI_PPC and so on.

The default ABI for a given platform is always forced on. This made it possible to keep things working for non-multilib packages without adding any multilib awareness to them, and at the same time cleanly handle profiles that do not do multilib at all. Multilib packages use ${MULTILIB_USEDEP} to enforce ABI match on their multilib depdencies; non-multilib packages just use plain deps and can expect the native ABI to be always enabled.

Eclasses were a natural place to implement all this logic. In the end, they formed a hierarchical structure. The pre-existing multilib.eclass already provided a few low-level functions needed to set up multilib builds. On top of it, multilib-build.eclass was created that provided low-level functions specific to the gx86-multilib — handling USE flags, running the builds and some specific helper functions. On top of it, high-level sub-phase-based multilib-minimal.eclass was created that made writing generic ebuilds easy. Then, on top of that the specific autotools-multilib.eclass and cmake-multilib.eclass existed.

Historically, the order was a little different. autotools-multilib.eclass came first. Then, the common logic was split into multilib-build.eclass and cmake-multilib.eclass came to be. Finally, multilib-minimal.eclass was introduced and a few months later the other eclasses started reusing it.

The reception and porting efforts

The eclasses had a mixed reception. They followed my philosophy of getting things done, today. This disagreed with purists who believed we should look for a better solution. Many of the developers believed that multilib-portage was the way forward (after all, it did not require changing ebuilds), though they did not seem to be that much concerned about having a clear plan of action. When I’ve pointed out that things need to be formally specified, the answer was roughly to dump whatever’s in multilib-portage at the time into the spec. As you can guess, no spec was ever written.

Nevertheless, porting ebuilds to the new framework proceeded over time. In some cases, we had to deal with varying level of opposition. In the most extreme cases, we had to work out a compromise and become co-maintainers of these packages in order to provide direct support for any port-related problems. However, as time went by more people joined the cause, and today it is pretty natural that maintainers add multilib support themselves. In fact, I believe that things went a bit out of control, as multilib is being added to packages where it is not really needed.

In its early years, gx86-multilib had to coexist with the older emul-linux-x86 packages. Since both groups of packages installed the same files, collisions were inevitable. Every few converted packages, we had to revbump the respective emul-linux-x86 sets dropping the colliding libraries. Later on, we had to start replacing old dependencies on emul-linux-x86 packages (now metapackages) with the actual lists of needed libraries. Naturally, this meant that someone actually had to figure out what the dependencies were — often for fetch-restricted packages that we simply didn’t have distfiles for.

In the end, everything went fine. All relevant packages were ported, emul-linux-x86 sets were retired. The team stayed around for a few years, updating the eclasses as need be. Many new packages gained multilib support even though it wasn’t strictly needed for anything. Multilib-foo became common knowledge.

The future

Our multilib effort is still alive and kicking. At the very least, it serves as the foundation for 32-bit Wine. While the Multilib project itself has been disbanded, its legacy lives on and it is not likely to become obsolete anytime soon. From a quick grep, there are around 600 multilib-enabled packages in ::gentoo at the moment and it is quite likely that there will be more.

The multilib-portage project is still being developed but it does not seem likely to be able to escape its niche. The eclass approach is easier, more portable and more efficient. You don’t have to modify the package manager, you don’t have to build everything multiple times; ideally, you only build library parts for all ABIs.

Support for multilib on non-x86 platforms is an open question. After all, the whole multilib effort was primarily focused on providing compatibility with old 32-bit executables on x86. While some platforms technically can provide multilib, it is not clear how much of that is actually useful to the users, and how much is a cargo cult. Support for additional targets has historically proven troublesome by causing exponential explosion of USE flags.

Some people were proposing switching to Debian-style multiarch layout (e.g. /usr/lib/x86_64-linux-gnu instead of /usr/lib64). However, I have never seen a strong reason to do that. After all, traditional libdirs are well-defined in the ABI specifications while multiarch is a custom Debian invention. In the end, it would be about moving things around and then patching packages into supporting non-standard locations. It would go against one of the primary Gentoo principles of providing a vanilla development environment. And that only shortly after we’ve finally gotten rid of the custom /usr/lib32 in favor of backwards-compatible /usr/lib.

So, while the Multilib project has been retired now, multilib itself is all but dead. We still use it, we still need it and we will probably still work on it in the future.

2 thoughts on “Retiring the multilib project”

  1. Thanks for keeping this going, some other big distros dropped 32 bit emulation, or made it unsupported for security updates, claiming there isn’t enough manpower or need for it. Gentoo is great for keeping it as an option. (Though one can disable it if one doesn’t like it.)

  2. You did an awesome job on the then far better multilib solution. A big thanks to you and everyone involved!

    I also liked the history blog post.

Leave a Reply

Your email address will not be published.