mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 19:41:07 +01:00
Without this, basic `bazel test //...` style wildcards would build a bunch of extra configurations because of gaps excluding things. With this, the action count of a normal build should be much more reasonable. The switch from `target_compatible_with` to tagging is based on looking at what ends up being most idiomatic and easiest -- trying to articulate the complex and convoluted compatible with restrictions that would avoid extraneous build configurations was really painful and this seems much simpler and easier to deploy in a systematic way. While here, also change the name of a rule that confused me to no end while debugging this -- the rule that installs a `.bzl` file that happens to be spelled `carbon_runtimes` is very different from all of the other "installed carbon runtimes" kind of things in the tree. Adding the file extension helps make that (much) more obvious. Note that this is essentially a re-do of #7088 but now without any dependencies that can mess up the merge. Assisted-by: Antigravity with Gemini
374 lines
13 KiB
Python
374 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
|
|
|
|
"""Starlark cc_toolchain configuration rules for using the Carbon toolchain"""
|
|
|
|
load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES", "ACTION_NAME_GROUPS")
|
|
load(
|
|
"@rules_cc//cc:cc_toolchain_config_lib.bzl",
|
|
"action_config",
|
|
"flag_group",
|
|
"flag_set",
|
|
"tool",
|
|
)
|
|
load(
|
|
"@rules_cc//cc:defs.bzl",
|
|
"CcToolchainConfigInfo",
|
|
"cc_toolchain",
|
|
)
|
|
load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
|
|
load(
|
|
"carbon_clang_variables.bzl",
|
|
"clang_include_dirs",
|
|
"clang_resource_dir",
|
|
"clang_sysroot",
|
|
)
|
|
load(
|
|
"cc_toolchain_actions.bzl",
|
|
"all_c_compile_actions",
|
|
)
|
|
load("cc_toolchain_carbon_project_features.bzl", "carbon_project_features")
|
|
load("cc_toolchain_features.bzl", "clang_cc_toolchain_features")
|
|
load(
|
|
":cc_toolchain_tools.bzl",
|
|
"llvm_tool_paths",
|
|
)
|
|
|
|
def _make_action_configs(tools, runtimes_path = None):
|
|
runtimes_flag = "--no-build-runtimes"
|
|
if runtimes_path:
|
|
runtimes_flag = "--prebuilt-runtimes={0}".format(runtimes_path)
|
|
|
|
return [
|
|
action_config(
|
|
action_name = name,
|
|
enabled = True,
|
|
tools = [tools.clang],
|
|
)
|
|
for name in all_c_compile_actions
|
|
] + [
|
|
action_config(
|
|
action_name = name,
|
|
enabled = True,
|
|
tools = [tools.clangpp],
|
|
)
|
|
for name in ACTION_NAME_GROUPS.all_cpp_compile_actions
|
|
] + [
|
|
action_config(
|
|
action_name = name,
|
|
enabled = True,
|
|
tools = [tools.carbon_busybox],
|
|
flag_sets = [flag_set(flag_groups = [flag_group(flags = [
|
|
runtimes_flag,
|
|
"link",
|
|
# We want to allow Bazel to intermingle linked object files and
|
|
# Clang-spelled link flags. The first `--` starts the list of
|
|
# initial object files by ending flags to the `link` subcommand,
|
|
# and the second `--` switches to Clang-spelled flags.
|
|
"--",
|
|
"--",
|
|
])])],
|
|
)
|
|
for name in ACTION_NAME_GROUPS.all_cc_link_actions
|
|
] + [
|
|
action_config(
|
|
action_name = name,
|
|
enabled = True,
|
|
tools = [tools.llvm_ar],
|
|
)
|
|
for name in [ACTION_NAMES.cpp_link_static_library]
|
|
] + [
|
|
action_config(
|
|
action_name = name,
|
|
enabled = True,
|
|
tools = [tools.llvm_strip],
|
|
)
|
|
for name in [ACTION_NAMES.strip]
|
|
]
|
|
|
|
def _compute_clang_system_include_dirs():
|
|
system_include_dirs_start_index = None
|
|
for index, dir in enumerate(clang_include_dirs):
|
|
# Skip over the include search directories until we find the resource
|
|
# directory. The system include directories are everything after that.
|
|
if dir.startswith(clang_resource_dir):
|
|
system_include_dirs_start_index = index + 1
|
|
break
|
|
if not system_include_dirs_start_index:
|
|
fail("Could not find the resource directory in the clang include " +
|
|
"directories: {}".format(clang_include_dirs))
|
|
return clang_include_dirs[system_include_dirs_start_index:]
|
|
|
|
def _carbon_cc_toolchain_config_impl(ctx):
|
|
llvm_bindir = "llvm/bin"
|
|
clang_bindir = llvm_bindir
|
|
tools = struct(
|
|
carbon_busybox = tool(path = "carbon-busybox"),
|
|
clang = tool(path = clang_bindir + "/clang"),
|
|
clangpp = tool(path = clang_bindir + "/clang++"),
|
|
llvm_ar = tool(path = llvm_bindir + "/llvm-ar"),
|
|
llvm_strip = tool(path = llvm_bindir + "/llvm-strip"),
|
|
)
|
|
if ctx.attr.bins:
|
|
carbon_busybox = None
|
|
clang = None
|
|
clangpp = None
|
|
llvm_ar = None
|
|
llvm_strip = None
|
|
for f in ctx.files.bins:
|
|
if f.basename == "carbon-busybox":
|
|
carbon_busybox = f
|
|
elif f.basename == "clang":
|
|
clang = f
|
|
elif f.basename == "clang++":
|
|
clangpp = f
|
|
elif f.basename == "llvm-ar":
|
|
llvm_ar = f
|
|
elif f.basename == "llvm-strip":
|
|
llvm_strip = f
|
|
if not all([carbon_busybox, clang, clangpp, llvm_ar, llvm_strip]):
|
|
fail("Missing required tool in bins: {0}".format(ctx.attr.bins))
|
|
llvm_bindir = llvm_ar.dirname
|
|
clang_bindir = clang.dirname
|
|
tools = struct(
|
|
carbon_busybox = tool(tool = carbon_busybox),
|
|
clang = tool(tool = clang),
|
|
clangpp = tool(tool = clangpp),
|
|
llvm_ar = tool(tool = llvm_ar),
|
|
llvm_strip = tool(tool = llvm_strip),
|
|
)
|
|
|
|
# Only use a sysroot if a non-trivial one is set in Carbon's config.
|
|
builtin_sysroot = None
|
|
sysroot_include_search = []
|
|
if clang_sysroot != "None" and clang_sysroot != "/":
|
|
builtin_sysroot = clang_sysroot
|
|
sysroot_include_search = ["%sysroot%/usr/include"]
|
|
|
|
runtimes_path = None
|
|
if ctx.attr.runtimes:
|
|
for f in ctx.files.runtimes:
|
|
if f.basename == "runtimes_root":
|
|
runtimes_path = f.dirname
|
|
break
|
|
if not runtimes_path:
|
|
fail("Unable to compute the runtimes path for: {0}".format(
|
|
ctx.attr.runtimes,
|
|
))
|
|
|
|
identifier = "{0}_toolchain_{1}_{2}".format(
|
|
ctx.attr.identifier_prefix,
|
|
ctx.attr.target_cpu,
|
|
ctx.attr.target_os,
|
|
)
|
|
return cc_common.create_cc_toolchain_config_info(
|
|
ctx = ctx,
|
|
features = clang_cc_toolchain_features(
|
|
target_os = ctx.attr.target_os,
|
|
target_cpu = ctx.attr.target_cpu,
|
|
|
|
# TODO: This should be configured externally rather than here so
|
|
# that the install Carbon toolchain doesn't automatically include
|
|
# Carbon-project-specific flags. However, that is especially awkward
|
|
# to do until we fully migrate to a rules-based toolchain, and the
|
|
# project-specific flags are largely harmless at the moment. We also
|
|
# omit a meaningful cache key as when using the Carbon toolchain we
|
|
# don't need it as it is a hermetic part of Bazel.
|
|
project_features = carbon_project_features(cache_key = ""),
|
|
),
|
|
action_configs = _make_action_configs(tools, runtimes_path),
|
|
cxx_builtin_include_directories = [
|
|
"runtimes/libunwind/include",
|
|
"runtimes/libcxx/include",
|
|
"runtimes/libcxxabi/include",
|
|
"{}/include".format(clang_resource_dir),
|
|
"runtimes/clang_resource_dir/include",
|
|
] + _compute_clang_system_include_dirs() + sysroot_include_search,
|
|
builtin_sysroot = builtin_sysroot,
|
|
|
|
# This configuration only supports local non-cross builds so derive
|
|
# everything from the target CPU selected.
|
|
toolchain_identifier = identifier,
|
|
|
|
# This is used to expose a "flag" that `config_setting` rules can use to
|
|
# determine if the compiler is Clang.
|
|
compiler = "clang",
|
|
|
|
# Pass in our tool paths to expose Make variables like $(NM) and
|
|
# $(OBJCOPY).
|
|
tool_paths = llvm_tool_paths(llvm_bindir, clang_bindir),
|
|
)
|
|
|
|
carbon_cc_toolchain_config = rule(
|
|
implementation = _carbon_cc_toolchain_config_impl,
|
|
attrs = {
|
|
"bins": attr.label(mandatory = False),
|
|
"identifier_prefix": attr.string(mandatory = True),
|
|
"runtimes": attr.label(mandatory = False),
|
|
"target_cpu": attr.string(mandatory = True),
|
|
"target_os": attr.string(mandatory = True),
|
|
},
|
|
provides = [CcToolchainConfigInfo],
|
|
)
|
|
|
|
def _runtimes_transition_impl(_, attr):
|
|
return {
|
|
"//:runtimes_build": True,
|
|
}
|
|
|
|
_runtimes_transition = transition(
|
|
inputs = [],
|
|
outputs = [
|
|
"//:runtimes_build",
|
|
],
|
|
implementation = _runtimes_transition_impl,
|
|
)
|
|
|
|
def _filegroup_with_runtimes_build_impl(ctx):
|
|
return [DefaultInfo(files = depset(ctx.files.srcs))]
|
|
|
|
filegroup_with_runtimes_build = rule(
|
|
implementation = _filegroup_with_runtimes_build_impl,
|
|
attrs = {
|
|
"srcs": attr.label_list(mandatory = True, cfg = _runtimes_transition),
|
|
"_allowlist_function_transition": attr.label(
|
|
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
|
|
),
|
|
},
|
|
doc = "A filegroup whose sources are built with or without runtimes building enabled.",
|
|
)
|
|
|
|
def carbon_cc_toolchain(
|
|
name,
|
|
platforms,
|
|
base_files_target,
|
|
runtimes_compile_files_target,
|
|
compile_files_target,
|
|
runtimes_target,
|
|
extra_toolchain_settings = [],
|
|
tags = []):
|
|
"""Create a Carbon `cc_toolchain` for the current target.
|
|
|
|
This macro constructs the configuration and toolchain rules for a baseline
|
|
Carbon toolchain, including building its own runtimes on demand.
|
|
|
|
Args:
|
|
name: The base name for the toolchain targets.
|
|
platforms: Supported platforms.
|
|
base_files_target: Target for base files.
|
|
runtimes_compile_files_target: Target for runtimes compile files.
|
|
compile_files_target: Target for compile files.
|
|
runtimes_target: Target for runtimes.
|
|
extra_toolchain_settings: Extra toolchain settings.
|
|
tags: Tags to apply to the toolchain.
|
|
"""
|
|
impl_tags = tags if "manual" in tags else tags + ["manual"]
|
|
|
|
carbon_cc_toolchain_config(
|
|
name = "{}_runtimes_toolchain_config".format(name),
|
|
identifier_prefix = "{}_runtimes".format(name),
|
|
target_cpu = select({
|
|
":is_{}_{}".format(os, cpu): cpu
|
|
for os, cpus in platforms.items()
|
|
for cpu in cpus
|
|
}),
|
|
target_os = select({
|
|
"@platforms//os:{}".format(os): os
|
|
for os in platforms.keys()
|
|
}),
|
|
bins = base_files_target,
|
|
tags = impl_tags,
|
|
)
|
|
|
|
cc_toolchain(
|
|
name = "{}_runtimes_cc_toolchain".format(name),
|
|
all_files = runtimes_compile_files_target,
|
|
ar_files = base_files_target,
|
|
as_files = runtimes_compile_files_target,
|
|
compiler_files = runtimes_compile_files_target,
|
|
dwp_files = base_files_target,
|
|
linker_files = base_files_target,
|
|
objcopy_files = base_files_target,
|
|
strip_files = base_files_target,
|
|
toolchain_config = ":{}_runtimes_toolchain_config".format(name),
|
|
toolchain_identifier = select({
|
|
":is_{}_{}".format(os, cpu): "{}_{}_{}_runtimes_toolchain".format(name, os, cpu)
|
|
for os, cpus in platforms.items()
|
|
for cpu in cpus
|
|
}),
|
|
tags = impl_tags,
|
|
)
|
|
|
|
native.toolchain(
|
|
name = "{}_runtimes_toolchain".format(name),
|
|
target_settings = [":is_runtimes_build"] + extra_toolchain_settings,
|
|
use_target_platform_constraints = True,
|
|
toolchain = ":{}_runtimes_cc_toolchain".format(name),
|
|
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
|
|
tags = tags,
|
|
)
|
|
|
|
carbon_cc_toolchain_config(
|
|
name = "{}_toolchain_config".format(name),
|
|
identifier_prefix = name,
|
|
target_cpu = select({
|
|
":is_{}_{}".format(os, cpu): cpu
|
|
for os, cpus in platforms.items()
|
|
for cpu in cpus
|
|
}),
|
|
target_os = select({
|
|
"@platforms//os:{}".format(os): os
|
|
for os in platforms.keys()
|
|
}),
|
|
runtimes = runtimes_target,
|
|
bins = base_files_target,
|
|
tags = impl_tags,
|
|
)
|
|
|
|
native.filegroup(
|
|
name = "{}_linker_files".format(name),
|
|
srcs = [
|
|
base_files_target,
|
|
runtimes_target,
|
|
],
|
|
tags = impl_tags,
|
|
)
|
|
|
|
native.filegroup(
|
|
name = "{}_all_files".format(name),
|
|
srcs = [
|
|
compile_files_target,
|
|
":{}_linker_files".format(name),
|
|
],
|
|
tags = impl_tags,
|
|
)
|
|
|
|
cc_toolchain(
|
|
name = "{}_cc_toolchain".format(name),
|
|
all_files = ":{}_all_files".format(name),
|
|
ar_files = base_files_target,
|
|
as_files = compile_files_target,
|
|
compiler_files = compile_files_target,
|
|
dwp_files = ":{}_linker_files".format(name),
|
|
linker_files = ":{}_linker_files".format(name),
|
|
objcopy_files = base_files_target,
|
|
strip_files = base_files_target,
|
|
toolchain_config = ":" + name + "_toolchain_config",
|
|
toolchain_identifier = select({
|
|
":is_{}_{}".format(os, cpu): "{}_{}_{}_toolchain".format(name, os, cpu)
|
|
for os, cpus in platforms.items()
|
|
for cpu in cpus
|
|
}),
|
|
tags = impl_tags,
|
|
)
|
|
|
|
native.toolchain(
|
|
name = name + "_toolchain",
|
|
target_settings = [":not_runtimes_build"] + extra_toolchain_settings,
|
|
use_target_platform_constraints = True,
|
|
toolchain = ":" + name + "_cc_toolchain",
|
|
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
|
|
tags = tags,
|
|
)
|