bazel-contrib / bazel-contrib/rules_foreign_cc
Put toolchain default library flags in LDFLAGS broke many projects on Darwin
- Dominant language
- Starlark
- Stars
- 737
- Forks
- 270
- PR merge metrics
- No merged PRs in 30d
Description
I started this quest as `@rules_foreign_cc//toolchains/private:make_tool` segfaults when `wildcard` is used. It turned out that `make` was not linking against the `glob()` function from the source tree, but a version from some system libraries. The version from the system library is not compatible with gnulib's `glob()` and caused segfault.
### TLDR
We need to strip `-lXX` flags from `LDFLAGS` to make autoconfig and linker sane on Darwin.
### Root cause
Standard cpp toolchain includes defaults libs [`-lc++` (or `-lstdc++`) and `-lm`](https://cs.opensource.google/bazel/bazel/+/master:tools/cpp/unix_cc_configure.bzl;l=465;drc=9e913fbfa2e3930742fc30dfb60ac5e2694c70cf) for linking flags. Which also uses `-as-needed` around those flags. However, Darwin's `ld` doesn't support the `--as-needed` feature, which means, all these libraries are loaded even if it's not required.
And here comes the interesting part. Those libs are presented as `LDFLAGS` to foreign cc build actions, and `LDFLAGS` almost always come before the actual object files from the target project. Take GNUMake's makefile as an example:
```make
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
make$(EXEEXT): $(make_OBJECTS) $(make_DEPENDENCIES) $(EXTRA_make_DEPENDENCIES)
@rm -f make$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(make_OBJECTS) $(make_LDADD) $(LIBS)
```
As well as the gettext's auto-configure script:
```autoconf
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
```
This means, `ld` will try to link against the libs defined by the cpp toolchain and then with the object files from the project. On contrast, the `cc_binary` will put those flags after the object files:
```paramfile
-o
bazel-out/darwin_arm64-fastbuild/bin/external/zstd/zstd_cli
bazel-out/darwin_arm64-fastbuild/bin/external/zstd/_objs/zstd_cli/benchfn.o
bazel-out/darwin_arm64-fastbuild/bin/external/zstd/_objs/zstd_cli/benchzstd.o
bazel-out/darwin_arm64-fastbuild/bin/external/zstd/_objs/zstd_cli/dibio.o
bazel-out/darwin_arm64-fastbuild/bin/external/zstd/_objs/zstd_cli/fileio.o
bazel-out/darwin_arm64-fastbuild/bin/external/zstd/_objs/zstd_cli/fileio_asyncio.o
bazel-out/darwin_arm64-fastbuild/bin/external/zstd/_objs/zstd_cli/lorem.o
bazel-out/darwin_arm64-fastbuild/bin/external/zstd/_objs/zstd_cli/timefn.o
bazel-out/darwin_arm64-fastbuild/bin/external/zstd/_objs/zstd_cli/util.o
bazel-out/darwin_arm64-fastbuild/bin/external/zstd/_objs/zstd_cli/zstdcli.o
bazel-out/darwin_arm64-fastbuild/bin/external/zstd/_objs/zstd_cli/zstdcli_trace.o
bazel-out/darwin_arm64-fastbuild/bin/external/zstd/libdatagen.a
bazel-out/darwin_arm64-fastbuild/bin/external/zstd/libutil.a
bazel-out/darwin_arm64-fastbuild/bin/external/zstd/libzstd.a
-Wl,-S
-mmacosx-version-min=14.5
-no-canonical-prefixes
-fobjc-link-runtime
--target=aarch64-apple-macosx
-lm
-no-canonical-prefixes
-headerpad_max_install_names
-fobjc-link-runtime
-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib
-lc++
-lc++abi
-Bstatic
-lunwind
-Bdynamic
-Lexternal/llvm_toolchain_llvm/lib
-pthread
--sysroot=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
```
Those standard libraries won't be a big deal in a perfect world. However, Darwin is weird, especially the math lib (try `open /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/libm.tbd`) re-exports a lot of symbols from other libs, including `libsystem_c.dylib`, which is not fully POSIX-compliant. Linking against it broke auto-config and caused segfault.
As a result, `foreign_cc` cannot build many projects on Darwin, while `homebrew` can.
Contributor guide
Research direction
Start by tracing how the C++ toolchain's default libraries become LDFLAGS for foreign_cc actions, then reproduce the configure or GNU Make link failure on Darwin. Done means library flags such as -lXX are no longer passed through LDFLAGS and affected Darwin builds no longer fail or segfault.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100