f0rmiga/gcc-toolchain

[Bug]: libstdc++ is not bundled

Opened this issue · 1 comments

ahans commented

What happened?

While the rules make sure to link against a rather old glibc, this is not true for libstdc++, which comes as part of gcc. The default build mode links against libstdc++ dynamically. When running on a host that has a version that is too old, things break. We can of course work around this by linking statically. But if dynamic linking is not reliable from a portability perspective, IMHO it would be cleaner to drop support for dynamically linking libstdc++ completely.

Bazel can handle dynamic libraries well: put the appropriate symlink into the runfiles dir and set RPATH properly, so that the library is found at runtime. I think using that in the gcc-toolchain rules should be possible.

Version

Development (host) and target OS/architectures:
Host: Ubuntu 22.04
Target: Debian Buster
Architecture: both x86_64

Output of bazel --version:
bazel 5.3.1

Version of the Aspect rules, or other relevant rules from your
WORKSPACE or MODULE.bazel file:

Language(s) and/or frameworks involved:

How to reproduce

# checkout branch where the C++ examples uses std::filesystem
git clone https://github.com/ahans/gcc-toolchain.git
cd gcc-toolchain
git switch use-filesystem
bazel build //examples/hello_world_cpp

# now try to run in a Debian Buster container
docker run -v $HOME:$HOME --workdir $(pwd) -ti debian:buster bazel-bin/examples/hello_world_cpp/hello_world_cpp
# results in:
# bazel-bin/examples/hello_world_cpp/hello_world_cpp: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.26' not found (required by bazel-bin/examples/hello_world_cpp/hello_world_cpp)

# Replacing buster with bullseye makes it work. Bullseye ships with gcc 10.2, so that does support 
# std::filesystem; gcc 8.x from buster does not

Any other information?

No response

Fund our work

  • Sponsor our open source work by donating a bug bounty

Hi @ahans, there are side effects in statically linking libstdc++. The 2 main ones are:

  • Binary sizes, which increase remote cache transfers significantly.
  • Inability to run sanitizers.

One trick to carry the stdlibc++ shared object provided by the sysroot with the binary is to set no_libstdcxx feature on your targets and then add @sysroot_x86_64//:libstdcxx to the deps. Notice that you would need a select to link against the correct target libstdc++.

I'm open to more suggestions.