Recent LLVM changes result in Mesa drivers pulling in libcurl and OpenSSL
This is a warning of future problems more than a directly actionable bug report. It's not yet clear to me whether the best place to solve it will be Mesa, or LLVM, or elsewhere; but LLVM is currently in the middle of a migration from Bugzilla to Gitlab, so they're not accepting issue reports anyway.
In recent prereleases of LLVM 14, the Debuginfod component has gained an optional dependency on libcurl, which I expect that general-purpose distributions will probably want to enable.
This pulls in all of libcurl's dependencies, notably a TLS implementation (usually OpenSSL, but sometimes GNUTLS or NSS), but depending on build configuration maybe also things like Kerberos, LDAP and RTMP.
These extra dependencies can become a problem when sharing graphics drivers between runtime environments, such as the Steam Runtime (which runs the Steam client and native Linux games in an environment compatible with Ubuntu 12.04), the newer Steam container runtime (which runs native Linux games in an environment compatible with Ubuntu 12.04, or runs Proton in a container compatible with Debian 10), or any environment where libraries get bundled (such as AppImage and many standalone/portable games). Briefly, the more dependencies Mesa drivers have, the more likely it is that we will encounter incompatible requirements.
One concrete example of a crash resulting from this is that in modern distros, libcurl exports versioned symbols under a version like CURL_OPENSSL_4
, but for unfortunate historical reasons the Steam Runtime's ABI includes a libcurl that exports its symbols under a version like CURL_OPENSSL_3
. If Mesa wants the former, but a game wants the latter, then we have a problem: there is no suitable version of libcurl that can be placed in the library search path.
I'm concerned that the indirect dependency on OpenSSL will also cause crashes, similar to the way an indirect dependency from GTK, via GLib, libmount and libcryptsetup, to OpenSSL caused crashes in https://github.com/ValveSoftware/steam-for-linux/issues/7223.
Build configurations
There seem to be three main ways LLVM can be configured:
-
-DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON
: one large shared librarylibLLVM-13.so.1
or similar, combining the functionality of many small static libraries likelibLLVMCoroutines.a
. Debian, Arch and Fedora do this, and I think most other distributions are the same. -
-DBUILD_SHARED_LIBS=ON
: one pair of small static/shared libraries per component, likelibLLVMCoroutines.a
andlibLLVMCoroutines.so
. I think this configuration is rarer, but Guix is apparently an example of a distro that uses it. [edited to add: This is apparently not recommended or supported by LLVM upstream, and noticeably slower for Mesa's use-cases.] - static-only: many small static libraries, shared linking is impossible.
And then there are two ways Mesa can be configured:
- shared LLVM (
-Dshared-llvm=enabled
or default): Mesa drivers will depend on whatever LLVM shared libraries are available at link time, either one big library such aslibLLVM-13.so.1
or multiple smaller shared libraries. Debian and Arch do this, and I think most other distributions are the same. - static LLVM (
-Dshared-llvm=disabled
): Mesa drivers will statically link only the parts of LLVM that they actually use. This is the only option if we have a static-only LLVM.
This results in three interesting configurations:
- Mesa uses one big LLVM shared library: Mesa configured with shared LLVM (
-Dshared-llvm=enabled
), LLVM configured with-DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON
. This is the one distros seem to prefer. - Mesa uses many small LLVM shared libraries: Mesa configured with shared LLVM (
-Dshared-llvm=enabled
), LLVM configured with-DBUILD_SHARED_LIBS=ON
. - Mesa uses static LLVM: Mesa configured with static LLVM (
-Dshared-llvm=disabled
), any LLVM configuration
The configuration with one big LLVM shared library gives us a libcurl dependency: the library includes the Debuginfod
component, and therefore the dependency, even if Mesa never actually calls into it.
The other two configurations might (I have not confirmed) avoid libcurl becoming part of Mesa users' process space, because in the shared case, the Mesa drivers will have DT_NEEDED
on the individual smaller libraries that they need, and in the static case, they'll include a static copy of the individual smaller libraries that they need; if that list doesn't include Debuginfod
(which it hopefully doesn't!) then the dependency is avoided.