Add support for clang's libc++ to Unix toolchain

Due to two separate issues, it is currently not possible to compile and link against clang's libc++ with Bazel's auto-configured Unix toolchain, e.g. via adding `-stdlib=libc++` as a `cxxopt` and `linkopt` on a `cc_binary`:

1. Since Bazel uses `-no-canonical-prefixes`, clang is not able to find the libc++ headers if it is invoked through a symlink in a different directory. This is fixed by fully resolving the path to the clang binary in the toolchain.

2. The list of built-in include paths does not contain the base directory of the libc++ headers, which makes Bazel's implicit dependency checker fail on targets with the `cxxopt` `-stdlib=lib++`. This is fixed by adding the search paths obtained from `clang -v` with that option to the list of built-in include paths in the toolchain.

Both 1. and 2. can be partially worked around by passing in `-stdlib=libc++` and a fully resolved `CC` via `--repo_env`. However, the former means that the choice of standard library has to be fixed for the entire workspace and the latter cannot be accomplished with a system-independent entry in `.bazelrc`. Proper fixes in Bazel thus seem vastly superior.

Fixes #13071

Closes #13666.

PiperOrigin-RevId: 389877696
diff --git a/tools/cpp/unix_cc_configure.bzl b/tools/cpp/unix_cc_configure.bzl
index 14a0ed5..371b66f 100644
--- a/tools/cpp/unix_cc_configure.bzl
+++ b/tools/cpp/unix_cc_configure.bzl
@@ -307,7 +307,15 @@
     return result
 
 def find_cc(repository_ctx, overriden_tools):
-    return _find_generic(repository_ctx, "gcc", "CC", overriden_tools)
+    cc = _find_generic(repository_ctx, "gcc", "CC", overriden_tools)
+    if _is_clang(repository_ctx, cc):
+        # If clang is run through a symlink with -no-canonical-prefixes, it does
+        # not find its own include directory, which includes the headers for
+        # libc++. Resolving the potential symlink here prevents this.
+        result = repository_ctx.execute(["readlink", "-f", cc])
+        if result.return_code == 0:
+            return result.stdout.strip()
+    return cc
 
 def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
     """Configure C++ toolchain on Unix platforms."""
@@ -333,7 +341,7 @@
     repository_ctx.file("tools/cpp/empty.cc", "int main() {}")
     darwin = cpu_value.startswith("darwin")
 
-    cc = _find_generic(repository_ctx, "gcc", "CC", overriden_tools)
+    cc = find_cc(repository_ctx, overriden_tools)
     is_clang = _is_clang(repository_ctx, cc)
     overriden_tools = dict(overriden_tools)
     overriden_tools["gcc"] = cc
@@ -428,6 +436,12 @@
         _get_cxx_include_directories(
             repository_ctx,
             cc,
+            "-xc++",
+            cxx_opts + ["-stdlib=libc++"],
+        ) +
+        _get_cxx_include_directories(
+            repository_ctx,
+            cc,
             "-xc",
             _get_no_canonical_prefixes_opt(repository_ctx, cc),
         ) +
@@ -436,6 +450,12 @@
             cc,
             "-xc++",
             cxx_opts + _get_no_canonical_prefixes_opt(repository_ctx, cc),
+        ) +
+        _get_cxx_include_directories(
+            repository_ctx,
+            cc,
+            "-xc++",
+            cxx_opts + _get_no_canonical_prefixes_opt(repository_ctx, cc) + ["-stdlib=libc++"],
         ),
     )