Frage

Context: I have an open source project which uses JNI. While it's possible to build it yourself, I expect most users will use standard Java tools like Maven, Gradle, or SBT to download the JAR, which contains the pre-compiled binary image. This is no problem on Windows, but on Linux it gets complex.

I'm wondering how much to statically link when creating these packages so it's compatible with most Linux distributions. I know that, for example, Alpine Linux does not come with libstdc++, meaning that it would fail when in a small docker container.

There's also the possibility of older versions. For example, a quick look at nm suggests it's linking _ZNSt11logic_errorC1EPKc@@GLIBCXX_3.4.21 and __vsnprintf_chk@@GLIBC_2.3.4. What if the host has versions older than 3.4.21 and 2.3.4?

However, most literature I've seen tells me not to link against libgcc. Is that still true? Is it the same if I switch to clang (which has its own standard libs?)

War es hilfreich?

Lösung

Static linking glibc is a no-no. My understanding is that is often customized for the distro, so you don't want to be distributing that to machines running different linux distros/releases. There are drop-in replacements for it that you can statically link, like MUSL. I've never tried them, so the rest in that regard is left up to the reader. Static linking everything else should be fine.

One approach I've used very successfully is to build your binary on an old Linux release (including doing static linking where you can). Those binaries will be forward compatible. So you should be able to get yourself some assurance that your binary will run on most distros from the past decade (though as you point out, Alpine is different - it uses MUSL - so you may need to build on Alpine to ensure compatibility). Technically speaking you can use modern releases to target older glibc versions for compatibility, but I found just using the old release to be the simpler.

Andere Tipps

In general, to be a good system citizen, you'll want to depend as much as possible on system libraries, and avoid static linking any libraries. Your code should only have source level dependency, rather than relying on specific ABI. Since your project is an open source project, you should be fine if you just let the person doing packaging to recompile your app with whatever system libraries are available on the target system. This produces a lean application that is as small as possible for the system, and improves overall system security as users won't have to patch twenty different programs separately when they all statically link to the same library with a security vulnerability.

If your project had been closed source software, this would've been more tricky, as you'd have to recompile for every system yourself as the packager may not be able to recompile your application.

Additionally, you can try to provide a universal app that is statically linked with all dependencies, this is to let users who are using distros that have not packaged your app to run your app without having to recompile themselves. When providing statically linked program, you have two options: try to statically link everything except the few libraries that you know are available in your supported target system (this comes with a nightmare of its own), or you can package the app as snaps or flatpak. I'd suggest the latter is the easiest way to provide a universal app.

Is it good practice to statically link libstdc++ and/or libgcc when creating distributable binaries for Linux?

You'll have to look at your planned supported target system. If you plan to support minimal distros that may not have libstdc++ preinstalled then yes, you should statically link them. Otherwise, you don't need to, they'll just bloat your app, these basic system libraries are designed to have very stable ABIs even across different distros; barring a few precautions, if they're available on the system, you can almost be sure that your app will run just fine with whatever version the system has installed.

If you plan to statically link your application, consider using a libc that's designed to be statically linked, such as musl libc.

Lizenziert unter: CC-BY-SA mit Zuschreibung
scroll top