mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 20:10:13 +01:00
This PR merges the OS-specific Clang flags into the main Clang flags features using feature-based constraints instead of separate features conditionally added. Similarly for libc++. This also move flags to more correctly live in the Clang flag set vs. the libc++ flag set as some of these flags were specific to using libc++. To make this change, the libc++ feature needs to be computed rather than being fixed, as we need to add search paths based on the installed location of LLVM and Clang. All of this only works when the OS-config flags work. The earlier PR adding these had a bug -- _none_ of the OS features would ever be enabled. This didn't result in a problem as the initial use was only to _disable_ flags on the wrong OS. Now that we're enabling flags, we have to get it right by marking all of these as `enabled`.
303 lines
10 KiB
Python
303 lines
10 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
|
|
|
|
"""A Starlark cc_toolchain configuration rule"""
|
|
|
|
load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
|
|
load(
|
|
"@rules_cc//cc:cc_toolchain_config_lib.bzl",
|
|
"feature",
|
|
"feature_set",
|
|
"flag_group",
|
|
"flag_set",
|
|
"with_feature_set",
|
|
)
|
|
load("@rules_cc//cc:defs.bzl", "cc_toolchain")
|
|
load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
|
|
load(
|
|
":cc_toolchain_actions.bzl",
|
|
"all_compile_actions",
|
|
"preprocessor_compile_actions",
|
|
)
|
|
load(
|
|
":cc_toolchain_base_features.bzl",
|
|
"base_features",
|
|
"output_flags_feature",
|
|
"user_flags_feature",
|
|
)
|
|
load(":cc_toolchain_config_features.bzl", "target_os_features")
|
|
load(
|
|
":cc_toolchain_cpp_features.bzl",
|
|
"clang_feature",
|
|
"clang_warnings_feature",
|
|
"libcxx_feature",
|
|
)
|
|
load(":cc_toolchain_debugging.bzl", "debugging_features")
|
|
load(
|
|
":cc_toolchain_linking.bzl",
|
|
"default_link_libraries_feature",
|
|
"linking_features",
|
|
"macos_link_libraries_feature",
|
|
)
|
|
load(":cc_toolchain_modules.bzl", "modules_features")
|
|
load(
|
|
":cc_toolchain_optimization.bzl",
|
|
"aarch64_cpu_flags",
|
|
"optimization_features",
|
|
"x86_64_cpu_flags",
|
|
)
|
|
load(
|
|
":cc_toolchain_sanitizer_features.bzl",
|
|
"macos_asan_workarounds",
|
|
"sanitizer_features",
|
|
"sanitizer_static_lib_flags",
|
|
)
|
|
load(
|
|
":cc_toolchain_tools.bzl",
|
|
"llvm_action_configs",
|
|
"llvm_tool_paths",
|
|
)
|
|
load(
|
|
":clang_detected_variables.bzl",
|
|
"clang_bindir",
|
|
"clang_include_dirs_list",
|
|
"clang_resource_dir",
|
|
"clang_version_for_cache",
|
|
"llvm_bindir",
|
|
"sysroot_dir",
|
|
)
|
|
|
|
def _build_features(ctx):
|
|
project_flags_feature = feature(
|
|
name = "project_flags",
|
|
enabled = True,
|
|
flag_sets = [
|
|
flag_set(
|
|
actions = all_compile_actions,
|
|
flag_groups = [flag_group(flags = [
|
|
# Don't warn on external code as we can't
|
|
# necessarily patch it easily. Note that these have
|
|
# to be initial directories in the `#include` line.
|
|
"--system-header-prefix=absl/",
|
|
"--system-header-prefix=benchmark/",
|
|
"--system-header-prefix=boost/",
|
|
"--system-header-prefix=clang-tools-extra/",
|
|
"--system-header-prefix=clang/",
|
|
"--system-header-prefix=gmock/",
|
|
"--system-header-prefix=gtest/",
|
|
"--system-header-prefix=libfuzzer/",
|
|
"--system-header-prefix=llvm/",
|
|
"--system-header-prefix=re2/",
|
|
"--system-header-prefix=tools/cpp/",
|
|
"--system-header-prefix=tree_sitter/",
|
|
])],
|
|
),
|
|
flag_set(
|
|
actions = preprocessor_compile_actions,
|
|
flag_groups = [flag_group(flags = [
|
|
# Pass the Clang version to get better Bazel caching
|
|
# behavior with system-installed Clang binaries.
|
|
"-DCLANG_VERSION_FOR_CACHE=\"%s\"" % clang_version_for_cache,
|
|
])],
|
|
),
|
|
flag_set(
|
|
actions = [
|
|
ACTION_NAMES.c_compile,
|
|
ACTION_NAMES.cpp_compile,
|
|
ACTION_NAMES.cpp_header_parsing,
|
|
ACTION_NAMES.cpp_module_compile,
|
|
],
|
|
flag_groups = [flag_group(flags = ["-DHAVE_MALLCTL"])],
|
|
with_features = [with_feature_set(["freebsd_target"])],
|
|
),
|
|
],
|
|
)
|
|
|
|
# An enabled feature that requires the `fastbuild` compilation. This is used
|
|
# to toggle general features on by default, while allowing them to be
|
|
# directly enabled and disabled more generally as desired.
|
|
enable_in_fastbuild = feature(
|
|
name = "enable_in_fastbuild",
|
|
enabled = True,
|
|
requires = [feature_set(["fastbuild"])],
|
|
implies = [
|
|
"asan",
|
|
"asan_min_size",
|
|
"minimal_optimization_flags",
|
|
"minimal_debug_info_flags",
|
|
],
|
|
)
|
|
|
|
# The order of the features determines the relative order of flags used.
|
|
features = []
|
|
features += base_features
|
|
features += target_os_features(ctx.attr.target_os)
|
|
features += [
|
|
# We always use Clang in the toolchain and enable all of its warnings.
|
|
clang_feature,
|
|
clang_warnings_feature,
|
|
# Enable libc++ where supported.
|
|
libcxx_feature(llvm_bindir, clang_bindir),
|
|
|
|
# Include any project-specific flags, importantly after the Clang and
|
|
# warnings features so we can override as necessary here.
|
|
project_flags_feature,
|
|
]
|
|
features += sanitizer_features
|
|
|
|
features += optimization_features
|
|
|
|
# TODO: Refactor target-specific feature management to be part of
|
|
# `optimization_features`.
|
|
if ctx.attr.target_cpu in ["aarch64", "arm64"]:
|
|
features.append(aarch64_cpu_flags)
|
|
else:
|
|
features.append(x86_64_cpu_flags)
|
|
|
|
features += modules_features
|
|
features += debugging_features
|
|
|
|
# Next, add the features based on the target platform. Here too the
|
|
# features are order sensitive.
|
|
if ctx.attr.target_os == "linux":
|
|
features.append(sanitizer_static_lib_flags)
|
|
sysroot = None
|
|
elif ctx.attr.target_os == "windows":
|
|
# TODO: Need to figure out if we need to add windows specific features
|
|
# I think the .pdb debug files will need to be handled differently,
|
|
# so that might be an example where a feature must be added.
|
|
sysroot = None
|
|
elif ctx.attr.target_os == "macos":
|
|
features.append(macos_asan_workarounds)
|
|
sysroot = sysroot_dir
|
|
elif ctx.attr.target_os == "freebsd":
|
|
features.append(sanitizer_static_lib_flags)
|
|
sysroot = sysroot_dir
|
|
else:
|
|
fail("Unsupported target OS!")
|
|
|
|
# Next, append the libraries to link.
|
|
features += linking_features
|
|
|
|
# TODO: Refactor the target-specific feature management here to be part of
|
|
# building `linking_features`.
|
|
features += [
|
|
feature(name = "supports_dynamic_linker", enabled = ctx.attr.target_os == "linux"),
|
|
feature(name = "supports_start_end_lib", enabled = ctx.attr.target_os == "linux"),
|
|
]
|
|
if ctx.attr.target_os == "macos":
|
|
features.append(macos_link_libraries_feature)
|
|
else:
|
|
features.append(default_link_libraries_feature)
|
|
|
|
# Lastly, we add a feature that enables others in the default `fastbuild`
|
|
# mode. This is also a good place to add any project-specific features.
|
|
features.append(enable_in_fastbuild)
|
|
|
|
# Add user flags and the output flags at the end.
|
|
features.append(user_flags_feature)
|
|
features.append(output_flags_feature)
|
|
return features
|
|
|
|
def _impl(ctx):
|
|
# TODO: See if this can be refactored into platform features.
|
|
if ctx.attr.target_os == "linux":
|
|
sysroot = None
|
|
elif ctx.attr.target_os == "windows":
|
|
sysroot = None
|
|
elif ctx.attr.target_os == "macos":
|
|
sysroot = sysroot_dir
|
|
elif ctx.attr.target_os == "freebsd":
|
|
sysroot = sysroot_dir
|
|
else:
|
|
fail("Unsupported target OS!")
|
|
|
|
identifier = "local-{0}-{1}".format(ctx.attr.target_cpu, ctx.attr.target_os)
|
|
return cc_common.create_cc_toolchain_config_info(
|
|
ctx = ctx,
|
|
features = _build_features(ctx),
|
|
action_configs = llvm_action_configs(llvm_bindir, clang_bindir),
|
|
cxx_builtin_include_directories = clang_include_dirs_list + [
|
|
# Add Clang's resource directory to the end of the builtin include
|
|
# directories to cover the use of sanitizer resource files by the
|
|
# driver.
|
|
clang_resource_dir + "/share",
|
|
],
|
|
builtin_sysroot = sysroot,
|
|
|
|
# This configuration only supports local non-cross builds so derive
|
|
# everything from the target CPU selected.
|
|
toolchain_identifier = identifier,
|
|
host_system_name = identifier,
|
|
target_system_name = identifier,
|
|
target_cpu = ctx.attr.target_cpu,
|
|
|
|
# This is used to expose a "flag" that `config_setting` rules can use to
|
|
# determine if the compiler is Clang.
|
|
compiler = "clang",
|
|
|
|
# These attributes aren't meaningful at all so just use placeholder
|
|
# values.
|
|
target_libc = "local",
|
|
abi_version = "local",
|
|
abi_libc_version = "local",
|
|
|
|
# We do have to pass in our tool paths.
|
|
tool_paths = llvm_tool_paths(llvm_bindir, clang_bindir),
|
|
)
|
|
|
|
cc_toolchain_config = rule(
|
|
implementation = _impl,
|
|
attrs = {
|
|
"target_cpu": attr.string(mandatory = True),
|
|
"target_os": attr.string(mandatory = True),
|
|
},
|
|
provides = [CcToolchainConfigInfo],
|
|
)
|
|
|
|
def cc_local_toolchain_suite(name, configs):
|
|
"""Create a toolchain suite that uses the local Clang/LLVM install.
|
|
|
|
Args:
|
|
name: The name of the toolchain suite to produce.
|
|
configs: An array of (os, cpu) pairs to support in the toolchain.
|
|
"""
|
|
|
|
# An empty filegroup to use when stubbing out the toolchains.
|
|
native.filegroup(
|
|
name = name + "_empty",
|
|
srcs = [],
|
|
)
|
|
|
|
# Create the individual local toolchains for each CPU.
|
|
for (os, cpu) in configs:
|
|
config_name = "{0}_{1}_{2}".format(name, os, cpu)
|
|
cc_toolchain_config(
|
|
name = config_name + "_config",
|
|
target_os = os,
|
|
target_cpu = cpu,
|
|
)
|
|
cc_toolchain(
|
|
name = config_name + "_tools",
|
|
all_files = ":" + name + "_empty",
|
|
ar_files = ":" + name + "_empty",
|
|
as_files = ":" + name + "_empty",
|
|
compiler_files = ":" + name + "_empty",
|
|
dwp_files = ":" + name + "_empty",
|
|
linker_files = ":" + name + "_empty",
|
|
objcopy_files = ":" + name + "_empty",
|
|
strip_files = ":" + name + "_empty",
|
|
supports_param_files = 1,
|
|
toolchain_config = ":" + config_name + "_config",
|
|
toolchain_identifier = config_name,
|
|
)
|
|
compatible_with = ["@platforms//cpu:" + cpu, "@platforms//os:" + os]
|
|
native.toolchain(
|
|
name = config_name,
|
|
exec_compatible_with = compatible_with,
|
|
target_compatible_with = compatible_with,
|
|
toolchain = config_name + "_tools",
|
|
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
|
|
)
|