Skip to content

Commit

Permalink
Add support for clang's libc++ to Unix toolchain
Browse files Browse the repository at this point in the history
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
  • Loading branch information
fmeum authored and copybara-github committed Aug 10, 2021
1 parent e0d6e6f commit f1531dc
Showing 1 changed file with 22 additions and 2 deletions.
24 changes: 22 additions & 2 deletions tools/cpp/unix_cc_configure.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,15 @@ def _find_generic(repository_ctx, name, env_name, overriden_tools, warn = False,
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."""
Expand All @@ -333,7 +341,7 @@ def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
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
Expand Down Expand Up @@ -425,6 +433,12 @@ def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
builtin_include_directories = _uniq(
_get_cxx_include_directories(repository_ctx, cc, "-xc") +
_get_cxx_include_directories(repository_ctx, cc, "-xc++", cxx_opts) +
_get_cxx_include_directories(
repository_ctx,
cc,
"-xc++",
cxx_opts + ["-stdlib=libc++"],
) +
_get_cxx_include_directories(
repository_ctx,
cc,
Expand All @@ -436,6 +450,12 @@ def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
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++"],
),
)

Expand Down

0 comments on commit f1531dc

Please sign in to comment.