Repository: bazelbuild/bazel
Issue: C++ rules broken on macOS 12 Monterey and command line developer tools
Labels: type: bug
team-Rules-CPP
untriaged

### Description of the problem / feature request:

There are mainly two ways to install the basic apple provided clang compiler toolchain on macOS. Either you install the Command Line developer tools by invoking `xcode-select --install`, or you install the full XCode development environment, which includes a graphical IDE and tooling for application development on all of Apple's operating systems. The latter is a significantly larger download at >10GiB.

Bazel 4.2.1 will detect and use the C++ compiler and linker that is available through the command line tools, but as of macOS 12 Monterey, attempting to build C++ binaries will succeed but the resulting binaries will fail on startup with a Segmentation Fault error. This is because the linker invocation generating the binary is not invoked with the -lc++ flag, indicating that the libc++ library should be loaded by the dynamic linker on startup.

The [suggested solution](https://github.com/bazelbuild/bazel/issues/14206#issuecomment-957356014) to this problem is to install the full XCode IDE, which apparently works around this problem, but it would be neat to have this work out-of-the-box

### Feature requests: what underlying problem are you trying to solve with this feature?

Make bazel more user friendly by having it build functional c++ binaries without non-obvious workarounds such as installing XCode on a pretty standard setup on one of the more common platforms.

### Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

1. On a vanilla macOS 12 Monterey machine, install the command line devloper tools with `xcode-select --install`
2. download the latest stable bazel (I ran bazelisk that pulled bazel 4.2.1)
3. Clone the [bazelbuild/examples](https://github.com/bazelbuild/examples) repository 
4. and build the [hello world example](https://github.com/bazelbuild/examples/tree/main/cpp-tutorial/stage1):
4.1 `cd cpp-tutorial/stage1`
4.2 `bazelisk build //main:hello-world`
5. Attempt to execute the resulting binary: `./bazel-bin/main/hello-world`

```shell
% ./bazel-bin/main/hello-world
zsh: segmentation fault  ./bazel-bin/main/hello-world
```

### What operating system are you running Bazel on?

I have reproduce this with macOS 12.0.1 Monterey on an Apple Silicon M1 MacBook as well as an Intel MacBook Pro.
```shell
% gcc --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 12.0.5 (clang-1205.0.22.9)
```

### What's the output of `bazel info release`?

```shell
% bazelisk info release
release 4.2.1
```

### What's the output of `git remote get-url origin ; git rev-parse master ; git rev-parse HEAD` ?

```shell
% git remote get-url origin ; git rev-parse main ; git rev-parse HEAD
https://github.com/bazelbuild/examples
67b1ee057fb532c8e7f15e202c0d8ccef4b507b9
67b1ee057fb532c8e7f15e202c0d8ccef4b507b9
```
###  Have you found anything relevant by searching the web?

There are a few github issues describing issues building bazel with bazel on macOS Monterey, and problems with segfaulting binaries, but they seem to be closed with the recommendation to install XCode, which seems to me like a workaround.

### Any other information, logs, or outputs that you want to share?

Running `bazel build --subcommands` reveals that the required linker flag `-lc++` is missing from the linker invocation.  Adding `linkopts = ["-lc++"],` to the `cc_binary` rule will work around this problem.

Issue comments:
A simpler workaround than setting `linkopts` as a parameter to `cc_binary` is set the `BAZEL_LINKOPTS` environment variable to `-lc++`:
```shell
noa@Noas-MacBook-Air stage1 % BAZEL_LINKOPTS=-lc++ bazelisk build //main:hello-world
INFO: Analyzed target //main:hello-world (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 0.078s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
% ./bazel-bin/main/hello-world
Hello world
Sun Nov 14 20:22:54 2021
```
The `local_config_cc/BUILD` that gets generated on macOS 12 will use the `unix_cc_toolchain_config.bzl` which will silently drop any `link_libs` being passed to the cc_toolchain_config on systems that has `target_libc == "macosx"`.

As I don't have access to a macOS 11 Big Sur, it is a bit unclear what has changed, but it seems like a good idea to me to have the `user_link_flags_feature` be added to the features list being declared towards the end of `_impl()` in `unix_cc_toolchain_config.bzl` regardless of whether is_linux (i.e. target_libc != "macosx") is true or not. The consequence of user_link_flags_feature being added is that the values in the link_libs parameter list gets added to the command line arguments of the linker, which seems to me like the right thing to do.
On macOS, Bazel should be using `tools/cpp/osx_cc_configure.bzl` to configure the local C++ toolchain, so the problem is more likely that Bazel is picking the wrong file when building on Monterey.
Thanks for the fix, we should cherry-pick it for 5.0. 
Please send a PR to branch https://github.com/bazelbuild/bazel/tree/release-5.0.0rc2 after https://github.com/bazelbuild/bazel/pull/14275 is merged. 
@meteorcloudy Can this get into a 4.2.2 as well? I believe it qualifies as OS support.
@meteorcloudy I cherry-picked the commit that landed to master and opened a PR to land it in `release-5.0.0rc2` https://github.com/bazelbuild/bazel/pull/14313 Please have a look.
@brentleyjones I agree that it looks bad that all released bazel versions fails to compile the example cpp hello world in the current stable macOS release that has been out for almost a month.

One aspect that makes macOS boxes with just the developer tools so common is that as soon as a developer types for example 'git' in a Terminal window, a popup will suggest installing the developer tools. 
@nresare can you submit the 4.x PR as well? Not sure if they'll accept it but it should be the exact same as the others
@nresare Thanks, merged!
Also cherry-picking this for 4.2.2

Pull request review comments:

Patch that resolved the issue:
diff --git a/tools/cpp/unix_cc_toolchain_config.bzl b/tools/cpp/unix_cc_toolchain_config.bzl
index 1d4ee950d04980..26119141059c1f 100644
--- a/tools/cpp/unix_cc_toolchain_config.bzl
+++ b/tools/cpp/unix_cc_toolchain_config.bzl
@@ -1243,6 +1243,7 @@ def _impl(ctx):
             coverage_feature,
             default_compile_flags_feature,
             default_link_flags_feature,
+            user_link_flags_feature,
             fdo_optimize_feature,
             supports_dynamic_linker_feature,
             dbg_feature,


Test patch: