mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
The SDK returned by `xcrun --show-sdk-path` does not always match the SDK that is used by clang under homebrew, because homebrew has its own configurations per target that specify an SDK path to `-isysroot`. And on Darwin, the `-isysroot` flag supercedes the `--sysroot` flag entirely when present. To override homebrew, and ensure we use the SDK we expect to be using from `xcrun`, specify `-isysroot` ourselves on the command line, both when finding the include paths and when building. The compiler ends up taking a dependency on a JSON file at the root of the SDK as well, so add that to our allowlist of non-hermetic files, along-side the SDK include paths.
340 lines
13 KiB
Python
340 lines
13 KiB
Python
# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
# Exceptions. See /LICENSE for license information.
|
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
"""Definitions of general C++ `cc_toolchain_config` features."""
|
|
|
|
load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES", "ACTION_NAME_GROUPS")
|
|
load(
|
|
"@rules_cc//cc:cc_toolchain_config_lib.bzl",
|
|
"feature",
|
|
"flag_group",
|
|
"flag_set",
|
|
"with_feature_set",
|
|
)
|
|
load(
|
|
":cc_toolchain_actions.bzl",
|
|
"preprocessor_compile_actions",
|
|
)
|
|
|
|
# Sysroots and MacOS are complicated:
|
|
#
|
|
# On Darwin/MacOS, the `-isysroot` flag is used for includes *and* libraries,
|
|
# and if specified it wins over `--sysroot` which would be used for libraries
|
|
# on other platforms.
|
|
# https://discourse.llvm.org/t/silly-what-is-the-difference-between-sysroot-and-isysroot/55788/2
|
|
#
|
|
# Additionally, on a MacOS build of clang, the sysroot defaults to `/`, which
|
|
# is incorrect and it needs to be pointed to the SDK root. However, as a
|
|
# convenience, homebrew builds of clang automatically add `-isysroot` to the
|
|
# command line, so that the user doesn't have to. But the SDK it chooses does
|
|
# not always match the one returned from `xcrun --show-sdk-path`, which is the
|
|
# SDK that we want to use. So we need to override homebrew's choice and specify
|
|
# `-isysroot`. This will also supersede anything given to `--sysroot` (on
|
|
# Darwin) so we don't need to specify both. For non-homebrew clang builds on
|
|
# MacOS, specifying `-isysroot` will also work to point the compiler to the
|
|
# correct SDK instead of `--sysroot`.
|
|
_sysroot_flag_sets = [
|
|
flag_set(
|
|
actions = ACTION_NAME_GROUPS.all_cc_compile_actions + ACTION_NAME_GROUPS.all_cc_link_actions,
|
|
flag_groups = [
|
|
flag_group(
|
|
expand_if_available = "sysroot",
|
|
flags = ["--sysroot=%{sysroot}"],
|
|
),
|
|
],
|
|
with_features = [with_feature_set(not_features = ["macos_target"])],
|
|
),
|
|
flag_set(
|
|
actions = ACTION_NAME_GROUPS.all_cc_compile_actions + ACTION_NAME_GROUPS.all_cc_link_actions,
|
|
flag_groups = [
|
|
flag_group(
|
|
flags = ["-isysroot", "%{sysroot}"],
|
|
),
|
|
],
|
|
with_features = [with_feature_set(["macos_target"])],
|
|
),
|
|
]
|
|
|
|
clang_feature = feature(
|
|
name = "clang",
|
|
enabled = True,
|
|
flag_sets = _sysroot_flag_sets + [
|
|
flag_set(
|
|
actions = ACTION_NAME_GROUPS.all_cc_compile_actions + ACTION_NAME_GROUPS.all_cc_link_actions,
|
|
flag_groups = [
|
|
flag_group(flags = [
|
|
"-no-canonical-prefixes",
|
|
"-fcolor-diagnostics",
|
|
]),
|
|
],
|
|
),
|
|
flag_set(
|
|
actions = ACTION_NAME_GROUPS.all_cc_compile_actions,
|
|
flag_groups = [
|
|
flag_group(flags = [
|
|
# Compile actions shouldn't link anything.
|
|
"-c",
|
|
]),
|
|
|
|
# Flags controlling the production of specific outputs from
|
|
# compile actions.
|
|
flag_group(
|
|
expand_if_available = "output_assembly_file",
|
|
flags = ["-S"],
|
|
),
|
|
flag_group(
|
|
expand_if_available = "output_preprocess_file",
|
|
flags = ["-E"],
|
|
),
|
|
flag_group(
|
|
expand_if_available = "dependency_file",
|
|
flags = ["-MD", "-MF", "%{dependency_file}"],
|
|
),
|
|
flag_group(
|
|
expand_if_available = "output_file",
|
|
flags = ["-frandom-seed=%{output_file}"],
|
|
),
|
|
],
|
|
),
|
|
flag_set(
|
|
# Flags specific to compiling C++ sources.
|
|
actions = ACTION_NAME_GROUPS.all_cpp_compile_actions,
|
|
flag_groups = [flag_group(flags = [
|
|
"-fno-exceptions",
|
|
"-fno-rtti",
|
|
"-std=c++20",
|
|
])],
|
|
),
|
|
flag_set(
|
|
actions = ACTION_NAME_GROUPS.all_cc_compile_actions,
|
|
flag_groups = [flag_group(flags = [
|
|
"-ffunction-sections",
|
|
"-fdata-sections",
|
|
])],
|
|
),
|
|
flag_set(
|
|
actions = ACTION_NAME_GROUPS.all_cc_compile_actions,
|
|
flag_groups = [flag_group(
|
|
expand_if_available = "pic",
|
|
flags = ["-fPIC"],
|
|
)],
|
|
),
|
|
flag_set(
|
|
actions = preprocessor_compile_actions,
|
|
flag_groups = [
|
|
flag_group(flags = [
|
|
# Disable a warning and override builtin macros to
|
|
# ensure a hermetic build.
|
|
"-Wno-builtin-macro-redefined",
|
|
"-D__DATE__=\"redacted\"",
|
|
"-D__TIMESTAMP__=\"redacted\"",
|
|
"-D__TIME__=\"redacted\"",
|
|
]),
|
|
flag_group(
|
|
flags = ["-D%{preprocessor_defines}"],
|
|
iterate_over = "preprocessor_defines",
|
|
),
|
|
flag_group(
|
|
expand_if_available = "includes",
|
|
flags = ["-include", "%{includes}"],
|
|
iterate_over = "includes",
|
|
),
|
|
flag_group(
|
|
flags = ["-iquote", "%{quote_include_paths}"],
|
|
iterate_over = "quote_include_paths",
|
|
),
|
|
flag_group(
|
|
flags = ["-I%{include_paths}"],
|
|
iterate_over = "include_paths",
|
|
),
|
|
flag_group(
|
|
flags = ["-isystem", "%{system_include_paths}"],
|
|
iterate_over = "system_include_paths",
|
|
),
|
|
],
|
|
),
|
|
flag_set(
|
|
actions = [
|
|
ACTION_NAMES.cpp_link_dynamic_library,
|
|
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
|
|
],
|
|
flag_groups = [flag_group(flags = ["-shared"])],
|
|
),
|
|
flag_set(
|
|
actions = ACTION_NAME_GROUPS.all_cc_link_actions,
|
|
flag_groups = [
|
|
flag_group(
|
|
expand_if_available = "strip_debug_symbols",
|
|
flags = ["-Wl,-S"],
|
|
),
|
|
flag_group(
|
|
expand_if_available = "library_search_directories",
|
|
flags = ["-L%{library_search_directories}"],
|
|
iterate_over = "library_search_directories",
|
|
),
|
|
flag_group(
|
|
expand_if_available =
|
|
"runtime_library_search_directories",
|
|
iterate_over = "runtime_library_search_directories",
|
|
flags = [
|
|
"-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}",
|
|
],
|
|
),
|
|
],
|
|
),
|
|
flag_set(
|
|
actions = ACTION_NAME_GROUPS.all_cc_link_actions,
|
|
flag_groups = [
|
|
flag_group(
|
|
flags = [
|
|
"-fuse-ld=lld",
|
|
# Force the C++ standard library and runtime libraries
|
|
# to be statically linked. This works even with libc++
|
|
# and libunwind despite the names, provided libc++ is
|
|
# built with the CMake option:
|
|
# - `-DCMAKE_POSITION_INDEPENDENT_CODE=ON`
|
|
"-static-libstdc++",
|
|
"-static-libgcc",
|
|
# Link with Clang's runtime library. This is always
|
|
# linked statically.
|
|
"-rtlib=compiler-rt",
|
|
# Link with pthread.
|
|
"-lpthread",
|
|
],
|
|
),
|
|
],
|
|
with_features = [with_feature_set(["linux_target"])],
|
|
),
|
|
flag_set(
|
|
actions = [ACTION_NAMES.cpp_link_executable],
|
|
flag_groups = [flag_group(
|
|
expand_if_available = "force_pic",
|
|
flags = ["-pie"],
|
|
)],
|
|
with_features = [with_feature_set([
|
|
"linux_target",
|
|
"freebsd_target",
|
|
])],
|
|
),
|
|
flag_set(
|
|
actions = [ACTION_NAMES.cpp_link_executable],
|
|
flag_groups = [flag_group(
|
|
expand_if_available = "force_pic",
|
|
flags = ["-fpie"],
|
|
)],
|
|
with_features = [with_feature_set(["macos_target"])],
|
|
),
|
|
],
|
|
)
|
|
|
|
clang_warnings_feature = feature(
|
|
name = "clang_warnings",
|
|
enabled = True,
|
|
flag_sets = [flag_set(
|
|
actions = ACTION_NAME_GROUPS.all_cc_compile_actions,
|
|
flag_groups = [flag_group(flags = [
|
|
"-Werror",
|
|
"-Wall",
|
|
"-Wextra",
|
|
"-Wthread-safety",
|
|
"-Wself-assign",
|
|
"-Wimplicit-fallthrough",
|
|
"-Wctad-maybe-unsupported",
|
|
"-Wextra-semi",
|
|
"-Wmissing-prototypes",
|
|
"-Wzero-as-null-pointer-constant",
|
|
"-Wdelete-non-virtual-dtor",
|
|
|
|
# TODO: Regression that warns on anonymous unions; remove depending
|
|
# on fix.
|
|
"-Wno-missing-designated-field-initializers",
|
|
])],
|
|
)],
|
|
)
|
|
|
|
# Libc++ HARDENING_MODE has 4 possible values:
|
|
# https://libcxx.llvm.org/Hardening.html#notes-for-users
|
|
#
|
|
# Do not enable DEBUG hardening mode, even for -c dbg, because its performance
|
|
# impact on llvm-symbolizer is too severe -- this flag results in symbolization
|
|
# becoming quadratic in the number of debug symbols, in practice meaning it
|
|
# never completes.
|
|
_libcpp_debug_flags = [
|
|
"-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE",
|
|
]
|
|
_libcpp_release_flags = [
|
|
"-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST",
|
|
]
|
|
|
|
def libcxx_feature(llvm_bindir = None, clang_bindir = None):
|
|
"""Builds a libc++ feature.
|
|
|
|
Returns:
|
|
The feature for use with `cc_toolchain_config`.
|
|
|
|
Args:
|
|
llvm_bindir: Optional LLVM installation `bin` directory, causes the
|
|
feature to look for adjacent installed libraries.
|
|
clang_bindir: Optional Clang installation `bin` directory, causes the
|
|
feature to look for adjacent installed libraries if different from
|
|
`llvm_bindir`.
|
|
"""
|
|
|
|
# Explicitly add LLVM libs to the search path to preempt the
|
|
# detected GCC installation's library paths. Those might have a
|
|
# system installed libc++ and we want to find the one next to
|
|
# our Clang.
|
|
extra_link_flags = []
|
|
if llvm_bindir:
|
|
extra_link_flags.append("-L" + llvm_bindir + "/../lib")
|
|
if clang_bindir and clang_bindir != llvm_bindir:
|
|
extra_link_flags.append("-L" + clang_bindir + "/../lib")
|
|
|
|
return feature(
|
|
name = "libcxx",
|
|
enabled = True,
|
|
flag_sets = [
|
|
flag_set(
|
|
actions = ACTION_NAME_GROUPS.all_cpp_compile_actions + ACTION_NAME_GROUPS.all_cc_link_actions,
|
|
flag_groups = [flag_group(flags = [
|
|
"-stdlib=libc++",
|
|
])],
|
|
with_features = [
|
|
# libc++ is only used on non-Windows platforms.
|
|
with_feature_set(not_features = ["windows_target"]),
|
|
],
|
|
),
|
|
flag_set(
|
|
actions = ACTION_NAME_GROUPS.all_cpp_compile_actions,
|
|
flag_groups = [flag_group(flags = _libcpp_debug_flags)],
|
|
with_features = [with_feature_set(not_features = ["opt"])],
|
|
),
|
|
flag_set(
|
|
actions = ACTION_NAME_GROUPS.all_cpp_compile_actions,
|
|
flag_groups = [flag_group(flags = _libcpp_release_flags)],
|
|
with_features = [with_feature_set(features = ["opt"])],
|
|
),
|
|
flag_set(
|
|
actions = ACTION_NAME_GROUPS.all_cc_link_actions,
|
|
flag_groups = [flag_group(flags = [
|
|
"-unwindlib=libunwind",
|
|
])],
|
|
with_features = [
|
|
# libc++ is only used on non-Windows platforms.
|
|
with_feature_set(not_features = ["windows_target"]),
|
|
],
|
|
),
|
|
flag_set(
|
|
actions = ACTION_NAME_GROUPS.all_cc_link_actions,
|
|
flag_groups = [flag_group(flags = extra_link_flags + [
|
|
# Force linking the static libc++abi archive here. This
|
|
# *should* be linked automatically, but not every release of
|
|
# LLVM correctly sets the CMake flags to do so.
|
|
"-l:libc++abi.a",
|
|
])],
|
|
with_features = [with_feature_set(["linux_target"])],
|
|
),
|
|
],
|
|
)
|