Introduce a Bazel-integrated build for the installed runtimes (#6872)

This shifts the Bazel toolchain configuration of our installation to
build all of the Clang runtimes Carbon uses on-demand natively in Bazel.
We export the information about how to build into a generated Starlark
file, and emit BUILD files and Starlark logic into the installation to
orchestrate the build.

This requires some complex management of Bazel toolchains -- we need to
first set-up a "runtimes toolchain" that doesn't have runtimes of its
own, but can be used to _build_ runtimes. Then we build the runtimes
using that toolchain, and assemble them into the standard layout for a
Carbon runtimes tree. Finally we configure the _actual_ toolchain with
this built tree.

Currently, this is only setup for the installed toolchain, but I plan to
factor this runtimes build into one that can be used directly as well to
break up the monolithic runtimes build step into Bazel-integrated build
of the runtimes. This will also serve as the foundation for adding
bootstrapping support directly to our Bazel build.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
This commit is contained in:
Chandler Carruth
2026-03-12 01:24:56 +00:00
committed by GitHub
co-authored by Dana Jansens
parent 0a4fd2cb7e
commit 5d41529590
12 changed files with 738 additions and 61 deletions
@@ -1,7 +1,7 @@
Commit ID: 959284a466ca392a5ccd501cf1c1622d1f423c06
Commit ID: d3b82534c2546a892a27856672ed95a7db97dba3
Change ID: zyxuvzwmzsnorloyuupuurxkppkoplnw
Author : Chandler Carruth <chandlerc@gmail.com> (2026-02-16 23:17:06)
Committer: Chandler Carruth <chandlerc@gmail.com> (2026-03-08 07:43:17)
Committer: Chandler Carruth <chandlerc@gmail.com> (2026-03-11 07:54:02)
Improve compiler-rt build structure and export compilation info
@@ -12,7 +12,7 @@ Committer: Chandler Carruth <chandlerc@gmail.com> (2026-03-08 07:43:17)
compiling these source files.
diff --git a/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel b/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel
index 4ded226174..0c3a7daaee 100644
index 4ded226174..3b5b8fc787 100644
--- a/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel
@@ -3,6 +3,7 @@
@@ -98,12 +98,14 @@ index 4ded226174..0c3a7daaee 100644
] + [
AARCH64_OUTLINE_ATOMICS_FMT.format(pat, size, model)
for (pat, size, model) in AARCH64_OUTLINE_ATOMICS
@@ -328,10 +360,18 @@
@@ -328,10 +360,20 @@
"lib/builtins/aarch64/lse.S",
# These files are provided by SME-specific file groups above.
"lib/builtins/aarch64/*sme*",
+ # This is only used with MinGW.
+ "lib/builtins/aarch64/chkstk.S",
+ # TODO: Remove this once we have a way of accessing `SipHash.h`.
+ "lib/builtins/aarch64/emupac.cpp",
],
),
)
@@ -117,7 +119,7 @@ index 4ded226174..0c3a7daaee 100644
BUILTINS_ARM_VFP_SRCS_PATTERNS = [
"lib/builtins/arm/*vfp*.S",
"lib/builtins/arm/*vfp*.c",
@@ -348,9 +388,19 @@
@@ -348,9 +390,19 @@
),
)
@@ -138,7 +140,7 @@ index 4ded226174..0c3a7daaee 100644
srcs = glob(
[
"lib/builtins/arm/*.S",
@@ -359,14 +409,52 @@
@@ -359,14 +411,52 @@
"lib/builtins/arm/*.h",
],
allow_empty = True,
@@ -196,7 +198,7 @@ index 4ded226174..0c3a7daaee 100644
[
"lib/builtins/ppc/*.S",
"lib/builtins/ppc/*.c",
@@ -377,17 +465,64 @@
@@ -377,17 +467,64 @@
),
)
@@ -272,7 +274,7 @@ index 4ded226174..0c3a7daaee 100644
)
# Source files for the x86 architecture specific builtins (both 32-bit and
@@ -402,8 +537,14 @@
@@ -402,8 +539,14 @@
# Source files for the x86-64 architecture specific builtins.
filegroup(
@@ -289,7 +291,7 @@ index 4ded226174..0c3a7daaee 100644
[
"lib/builtins/x86_64/*.S",
"lib/builtins/x86_64/*.c",
@@ -411,13 +552,29 @@
@@ -411,13 +554,29 @@
"lib/builtins/x86_64/*.h",
],
allow_empty = True,
@@ -321,7 +323,7 @@ index 4ded226174..0c3a7daaee 100644
[
"lib/builtins/i386/*.S",
"lib/builtins/i386/*.c",
@@ -429,28 +586,16 @@
@@ -429,28 +588,16 @@
# This file is used for both i386 and x86_64 and so included in the
# broader x86 sources.
"lib/builtins/i386/fp_mode.c",
+4
View File
@@ -8,6 +8,10 @@ load("runtimes_build_info.bzl", "generate_runtimes_build_info_cc_library")
package(default_visibility = ["//visibility:public"])
exports_files([
"runtimes_build_vars.tpl.bzl",
])
cc_library(
name = "block_value_store",
hdrs = ["block_value_store.h"],
+36 -13
View File
@@ -19,6 +19,7 @@ Future runtimes we plan to add support for but not yet included:
- Profiling runtimes
"""
load("@llvm-project//:vars.bzl", "LLVM_VERSION_MAJOR")
load("@llvm-project//compiler-rt:compiler-rt.bzl", "builtins_copts", "crt_copts")
load("@llvm-project//libcxx:libcxx_library.bzl", "libcxx_and_abi_copts")
load("@llvm-project//libunwind:libunwind_library.bzl", "libunwind_copts")
@@ -124,6 +125,7 @@ def _get_substitutions(ctx):
"CRT_COPTS": _format_one_per_line(crt_copts),
"LIBCXX_AND_ABI_COPTS": _format_one_per_line(libcxx_and_abi_copts),
"LIBUNWIND_COPTS": _format_one_per_line(libunwind_copts),
"LLVM_VERSION_MAJOR": LLVM_VERSION_MAJOR,
} | {
k.upper(): _get_path(key_attr(k), _builtins_path)
for k in CRT_FILES.keys()
@@ -146,6 +148,20 @@ def _get_substitutions(ctx):
)]
}
_common_runtimes_rule_attrs = {
"_" + k: attr.label(default = v, allow_single_file = True)
for k, v in CRT_FILES.items()
} | {
"_" + _get_name(g): attr.label_list(default = [g], allow_files = True)
for g in (
BUILTINS_SRCS_FILEGROUPS +
BUILTINS_TEXTUAL_SRCS_FILEGROUPS +
RUNTIMES_HDRS_FILEGROUPS +
RUNTIMES_SRCS_FILEGROUPS +
RUNTIMES_TEXTUAL_SRCS_FILEGROUPS
)
}
def _generate_runtimes_build_info_h_rule(ctx):
h_file = ctx.actions.declare_file(ctx.label.name)
ctx.actions.expand_template(
@@ -157,19 +173,7 @@ def _generate_runtimes_build_info_h_rule(ctx):
generate_runtimes_build_info_h = rule(
implementation = _generate_runtimes_build_info_h_rule,
attrs = {
"_" + k: attr.label(default = v, allow_single_file = True)
for k, v in CRT_FILES.items()
} | {
"_" + _get_name(g): attr.label_list(default = [g], allow_files = True)
for g in (
BUILTINS_SRCS_FILEGROUPS +
BUILTINS_TEXTUAL_SRCS_FILEGROUPS +
RUNTIMES_HDRS_FILEGROUPS +
RUNTIMES_SRCS_FILEGROUPS +
RUNTIMES_TEXTUAL_SRCS_FILEGROUPS
)
} | {
attrs = _common_runtimes_rule_attrs | {
"_template_file": attr.label(
default = "runtimes_build_info.tpl.h",
allow_single_file = True,
@@ -197,3 +201,22 @@ def generate_runtimes_build_info_cc_library(name, deps = [], **kwargs):
] + deps,
**kwargs
)
def _generate_runtimes_build_vars_rule(ctx):
file = ctx.actions.declare_file(ctx.label.name)
ctx.actions.expand_template(
template = ctx.file._template_file,
output = file,
substitutions = _get_substitutions(ctx),
)
return [DefaultInfo(files = depset([file]))]
generate_runtimes_build_vars = rule(
implementation = _generate_runtimes_build_vars_rule,
attrs = _common_runtimes_rule_attrs | {
"_template_file": attr.label(
default = "runtimes_build_vars.tpl.bzl",
allow_single_file = True,
),
},
)
@@ -0,0 +1,45 @@
# 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 file exporting Carbon toolchain runtimes build info variables.
This file is a template that is expanded into a starlark file for the installed
Carbon toolchain that provides a trivial textual definition of the relevant
build info in variables.
"""
llvm_version_major = LLVM_VERSION_MAJOR
crtbegin_src = CRTBEGIN_SRC
crtend_src = CRTEND_SRC
crt_copts = [CRT_COPTS]
builtins_aarch64_srcs = [BUILTINS_AARCH64_SRCS]
builtins_x86_64_srcs = [BUILTINS_X86_64_SRCS]
builtins_i386_srcs = [BUILTINS_I386_SRCS]
builtins_aarch64_textual_srcs = [BUILTINS_AARCH64_TEXTUAL_SRCS]
builtins_x86_64_textual_srcs = [BUILTINS_X86_64_TEXTUAL_SRCS]
builtins_i386_textual_srcs = [BUILTINS_I386_TEXTUAL_SRCS]
builtins_copts = [BUILTINS_COPTS]
libcxx_hdrs = [LIBCXX_HDRS]
libcxx_linux_srcs = [LIBCXX_LINUX_SRCS]
libcxx_macos_srcs = [LIBCXX_MACOS_SRCS]
libcxx_win32_srcs = [LIBCXX_WIN32_SRCS]
libc_internal_libcxx_hdrs = [LIBCXX_SHARED_HEADERS_HDRS]
libcxxabi_hdrs = [LIBCXXABI_HDRS]
libcxxabi_srcs = [LIBCXXABI_SRCS]
libcxxabi_textual_srcs = [LIBCXXABI_TEXTUAL_SRCS]
libcxx_copts = [LIBCXX_AND_ABI_COPTS]
libunwind_hdrs = [LIBUNWIND_HDRS]
libunwind_srcs = [LIBUNWIND_SRCS]
libunwind_copts = [LIBUNWIND_COPTS]
-5
View File
@@ -447,11 +447,6 @@ auto ClangResourceDirBuilder::CollectBuiltinsSrcFiles()
// Only compile source files, not headers.
llvm::erase_if(src_files,
[](llvm::StringRef file) { return file.ends_with(".h"); });
// TODO: Remove this once we have a way of accessing `SipHash.h`.
llvm::erase_if(src_files, [](llvm::StringRef file) {
return file.ends_with("emupac.cpp");
});
return src_files;
}
+11
View File
@@ -15,6 +15,7 @@ load(
"BUILTINS_SRCS_FILEGROUPS",
"BUILTINS_TEXTUAL_SRCS_FILEGROUPS",
"CRT_FILES",
"generate_runtimes_build_vars",
)
load("configure_cmake_file.bzl", "configure_cmake_file")
load("install_filegroups.bzl", "install_filegroup", "install_symlink", "install_target", "make_install_filegroups")
@@ -305,6 +306,11 @@ filegroup(
],
)
# Generate a Starlark file with all the build variables needed for our runtimes.
generate_runtimes_build_vars(
name = "staging_bazel/runtimes_build_vars.bzl",
)
# Given a CMake-style install prefix[1], the hierarchy looks like:
#
# - prefix/bin: Binaries intended for direct use.
@@ -350,7 +356,10 @@ install_dirs = {
"lib/carbon/bazel": [
install_target("carbon_cc_toolchain_config.bzl", "bazel/carbon_cc_toolchain_config.bzl"),
install_target("carbon_detected_variables.tpl.bzl", "bazel/carbon_detected_variables.tpl.bzl"),
install_target("carbon_runtimes.bzl", "bazel/carbon_runtimes.bzl"),
install_target("carbon_toolchain.bzl", "bazel/carbon_toolchain.bzl"),
install_target("make_include_copts.bzl", "bazel/make_include_copts.bzl"),
install_target("runtimes_build_vars.bzl", "staging_bazel/runtimes_build_vars.bzl"),
install_target("BUILD", "bazel/empty.BUILD"),
],
"lib/carbon/llvm/bin": [install_symlink(
@@ -367,6 +376,7 @@ install_dirs = {
install_filegroup("libcxx", ":libcxx"),
install_filegroup("libcxxabi", ":libcxxabi"),
install_filegroup("libunwind", ":libunwind"),
install_target("BUILD", "bazel/runtimes.BUILD"),
],
"lib/carbon/runtimes/libc": [
install_filegroup("internal", ":libc_internal"),
@@ -379,6 +389,7 @@ install_dirs = {
),
],
"lib/carbon/llvm/lib/clang/" + LLVM_VERSION_MAJOR: [
install_target("BUILD", "bazel/clang_resource_dir.BUILD"),
install_filegroup(
"include",
":clang_headers",
@@ -9,20 +9,86 @@ load(
"clang_include_dirs",
"clang_sysroot",
)
load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
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("//bazel:runtimes_build_vars.bzl", "llvm_version_major")
load(
":cc_toolchain_actions.bzl",
"all_c_compile_actions",
"all_cpp_compile_actions",
"all_link_actions",
)
load(":cc_toolchain_features.bzl", "clang_cc_toolchain_features")
load(
":cc_toolchain_tools.bzl",
"llvm_action_configs",
"llvm_tool_paths",
)
def _impl(ctx):
def _make_action_configs(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 = [tool(path = "llvm/bin/clang")],
)
for name in all_c_compile_actions
] + [
action_config(
action_name = name,
enabled = True,
tools = [tool(path = "llvm/bin/clang++")],
)
for name in all_cpp_compile_actions
] + [
action_config(
action_name = name,
enabled = True,
tools = [tool(path = "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 all_link_actions
] + [
action_config(
action_name = name,
enabled = True,
tools = [tool(path = "llvm/bin/llvm-ar")],
)
for name in [ACTION_NAMES.cpp_link_static_library]
] + [
action_config(
action_name = name,
enabled = True,
tools = [tool(path = "llvm/bin/llvm-strip")],
)
for name in [ACTION_NAMES.strip]
]
def _carbon_cc_toolchain_config_impl(ctx):
# Hard code the the repository-relative path of the LLVM (and Clang)
# binaries as it is a fixed aspect of the install structure.
llvm_bindir = "llvm/bin"
@@ -32,14 +98,28 @@ def _impl(ctx):
if clang_sysroot != "None" and clang_sysroot != "/":
builtin_sysroot = clang_sysroot
identifier = "carbon-toolchain-{0}-{1}".format(ctx.attr.target_cpu, ctx.attr.target_os)
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 = "carbon-toolchain-{0}-{1}".format(
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,
),
action_configs = llvm_action_configs(llvm_bindir),
action_configs = _make_action_configs(runtimes_path),
cxx_builtin_include_directories = clang_include_dirs,
builtin_sysroot = builtin_sysroot,
@@ -56,56 +136,184 @@ def _impl(ctx):
)
carbon_cc_toolchain_config = rule(
implementation = _impl,
implementation = _carbon_cc_toolchain_config_impl,
attrs = {
"runtimes": attr.label(mandatory = False),
"target_cpu": attr.string(mandatory = True),
"target_os": attr.string(mandatory = True),
},
provides = [CcToolchainConfigInfo],
)
def carbon_cc_toolchain_suite(name, configs):
def _runtimes_transition_impl(_, attr):
# Adjust the platform to the runtimes platform across the transition.
return {"//command_line_option:platforms": [str(attr.runtimes_platform)]}
runtimes_transition = transition(
inputs = [],
outputs = ["//command_line_option:platforms"],
implementation = _runtimes_transition_impl,
)
def _runtimes_filegroup_impl(ctx):
return [DefaultInfo(files = depset(ctx.files.srcs))]
runtimes_filegroup = rule(
implementation = _runtimes_filegroup_impl,
attrs = {
# The platform to use when building the runtimes.
"runtimes_platform": attr.label(mandatory = True),
# Mark that our dependencies are built through a transition.
"srcs": attr.label_list(mandatory = True, cfg = runtimes_transition),
# Enable transitions in this rule.
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
)
def carbon_cc_toolchain_suite(name, platforms):
"""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.
platforms: An array of (os, cpu) pairs to support in the toolchain.
"""
# Our base filegroup for the toolchain just includes the busybox and the
# LLVM symlinks. Importantly, this _doesn't_ include the install digest that
# would cause cache misses as-if every file in the toolchain were an input
# to every action.
native.filegroup(
name = name + "_files",
srcs = native.glob([
"**",
name = name + "_base_files",
srcs = ["carbon-busybox", "carbon_install.txt"] + native.glob([
"llvm/bin/*",
]),
)
# Create the individual local toolchains for each CPU.
for (os, cpu) in configs:
config_name = "{0}_{1}_{2}".format(name, os, cpu)
# We also need a compile-specific filegroup for use when _building_
# runtimes. This needs to include the dedicated Clang headers, but we
# require the runtimes themselves to provide the relevant headers and
# dependencies.
native.filegroup(
name = name + "_runtimes_compile_files",
srcs = [
":" + name + "_base_files",
"//llvm/lib/clang/{0}:clang_hdrs".format(llvm_version_major),
],
)
# We can build a single common compile filegroup regardless of CPU and OS.
# This needs to include all the headers of the runtimes, but those are
# architecture independent.
native.filegroup(
name = name + "_compile_files",
srcs = [
":" + name + "_runtimes_compile_files",
"//runtimes:libunwind_hdrs",
"//runtimes:libcxx_hdrs",
],
)
# Create the actual toolchains for each OS and CPU.
for (os, cpu) in platforms:
platform_name = "{0}_{1}_{2}".format(name, os, cpu)
platform_constraints = [
"@platforms//os:" + os,
"@platforms//cpu:" + cpu,
]
# First, configure a platform and toolchain for building runtimes. This
# toolchain will only have the Clang headers and no runtime libraries
# included.
native.platform(
name = platform_name + "_runtimes_platform",
constraint_values = [":is_runtimes_build"] + platform_constraints,
)
carbon_cc_toolchain_config(
name = config_name + "_config",
name = platform_name + "_runtimes_toolchain_config",
target_cpu = cpu,
target_os = os,
)
cc_toolchain(
name = config_name + "_tools",
all_files = ":" + name + "_files",
ar_files = ":" + name + "_files",
as_files = ":" + name + "_files",
compiler_files = ":" + name + "_files",
dwp_files = ":" + name + "_files",
linker_files = ":" + name + "_files",
objcopy_files = ":" + name + "_files",
strip_files = ":" + name + "_files",
supports_param_files = 1,
toolchain_config = ":" + config_name + "_config",
toolchain_identifier = config_name,
name = platform_name + "_runtimes_cc_toolchain",
all_files = ":" + name + "_runtimes_compile_files",
ar_files = ":" + name + "_base_files",
as_files = ":" + name + "_runtimes_compile_files",
compiler_files = ":" + name + "_runtimes_compile_files",
dwp_files = ":" + name + "_base_files",
linker_files = ":" + name + "_base_files",
objcopy_files = ":" + name + "_base_files",
strip_files = ":" + name + "_base_files",
toolchain_config = ":" + platform_name + "_runtimes_toolchain_config",
toolchain_identifier = platform_name + "_runtimes",
)
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",
name = platform_name + "_runtimes_toolchain",
exec_compatible_with = platform_constraints,
target_compatible_with = [":is_runtimes_build"] + platform_constraints,
toolchain = platform_name + "_runtimes_cc_toolchain",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
# Now we can use the runtimes platform to build the runtimes on-demand.
runtimes_filegroup(
name = platform_name + "_runtimes",
srcs = ["//runtimes:carbon_runtimes"],
runtimes_platform = ":" + platform_name + "_runtimes_platform",
)
# Finally, we can build the main platform and toolchain.
native.platform(
name = platform_name + "_platform",
constraint_values = platform_constraints,
)
# Build the main config with runtimes passed in. This allows the
# configuration to use these built runtimes where needed.
carbon_cc_toolchain_config(
name = platform_name + "_toolchain_config",
target_cpu = cpu,
target_os = os,
runtimes = ":" + platform_name + "_runtimes",
)
# We also include the runtimes in the linker files. We have to do this
# in addition to the config parameter as the config can't carry the
# actual dependency.
native.filegroup(
name = platform_name + "_linker_files",
srcs = [
":" + name + "_base_files",
":" + platform_name + "_runtimes",
],
)
native.filegroup(
name = platform_name + "_all_files",
srcs = [
":" + name + "_compile_files",
":" + platform_name + "_linker_files",
],
)
cc_toolchain(
name = platform_name + "_cc_toolchain",
all_files = ":" + platform_name + "_all_files",
ar_files = ":" + name + "_base_files",
as_files = ":" + name + "_compile_files",
compiler_files = ":" + name + "_compile_files",
dwp_files = ":" + platform_name + "_linker_files",
linker_files = ":" + platform_name + "_linker_files",
objcopy_files = ":" + name + "_base_files",
strip_files = ":" + name + "_base_files",
toolchain_config = ":" + platform_name + "_toolchain_config",
toolchain_identifier = platform_name,
)
native.toolchain(
name = platform_name + "_toolchain",
exec_compatible_with = platform_constraints,
target_compatible_with = platform_constraints,
toolchain = platform_name + "_cc_toolchain",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
+151
View File
@@ -0,0 +1,151 @@
# 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 rules for building a Carbon runtimes tree.
TODO: Currently, this produces a complete, static Carbon runtimes tree that
mirrors the exact style of runtimes tree the Carbon toolchain would build on its
own. However, it would be preferable to preserve the builtins, libc++, and
libunwind `cc_library` rules as "normal" library rules (if behind a transition)
and automatically depend on them. This would allow things like LTO and such to
include these. However, this requires support in `@rules_cc` for this kind of
dependency to be added.
"""
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
def _build_crt_file(ctx, cc_toolchain, feature_configuration, crt_file):
_, compilation_outputs = cc_common.compile(
name = ctx.label.name + ".compile_" + crt_file.basename,
actions = ctx.actions,
feature_configuration = feature_configuration,
cc_toolchain = cc_toolchain,
srcs = [crt_file],
user_compile_flags = ctx.attr.crt_copts,
)
# Extract the PIC object file and make sure we built one.
obj = compilation_outputs.pic_objects[0]
if not obj:
fail("The toolchain failed to produce a PIC object file. Ensure your " +
"toolchain supports PIC.")
return obj
def _removeprefix_or_fail(s, prefix):
new_s = s.removeprefix(prefix)
if new_s == s:
fail("Unable to remove prefix '{0}' from '{1}'".format(prefix, s))
return new_s
def _carbon_runtimes_impl(ctx):
outputs = []
prefix = ctx.attr.name
# Create a marker file in the runtimes root first. We'll use this to locate
# the runtimes for the toolchain.
root_out = ctx.actions.declare_file("{0}/runtimes_root".format(prefix))
ctx.actions.write(output = root_out, content = "")
outputs.append(root_out)
# Setup the C++ toolchain and configuration. We also force the `pic` feature
# to be enabled for these actions as we always want PIC generated code --
# this avoids the need to build two versions of the runtimes and doesn't
# create problems with modern code generation when linking statically. This
# also simplifies extracting the outputs as we only need to look at
# `pic_objects`.
cc_toolchain = find_cpp_toolchain(ctx)
feature_configuration = cc_common.configure_features(
ctx = ctx,
cc_toolchain = cc_toolchain,
requested_features = ctx.features + ["pic"],
unsupported_features = ctx.disabled_features,
)
if ctx.attr.target_triple != "":
builtins_lib_path = "clang_resource_dir/lib/{0}".format(ctx.attr.target_triple)
else:
builtins_lib_path = "clang_resource_dir/lib"
for filename, src in [
("crtbegin", ctx.files.crtbegin_src),
("crtend", ctx.files.crtend_src),
]:
if not src:
continue
src = src[0]
crt_obj = _build_crt_file(ctx, cc_toolchain, feature_configuration, src)
crt_out = ctx.actions.declare_file("{0}/{1}/clang_rt.{2}.o".format(
prefix,
builtins_lib_path,
filename,
))
ctx.actions.symlink(output = crt_out, target_file = crt_obj)
outputs.append(crt_out)
for runtime_dir, archive_name, archive in [
(builtins_lib_path, "libclang_rt.builtins.a", ctx.files.builtins_archive[0]),
("libcxx/lib", "libc++.a", ctx.files.libcxx_archive[0]),
("libunwind/lib", "libunwind.a", ctx.files.libunwind_archive[0]),
]:
runtime_out = ctx.actions.declare_file("{0}/{1}/{2}".format(
prefix,
runtime_dir,
archive_name,
))
ctx.actions.symlink(output = runtime_out, target_file = archive)
outputs.append(runtime_out)
for hdr in ctx.files.clang_hdrs:
# Incrementally remove prefixes of the paths to find the `include`
# directory we want to symlink into the output tree.
rel_path = hdr.path
if hdr.root.path != "":
rel_path = _removeprefix_or_fail(rel_path, hdr.root.path + "/")
rel_path = _removeprefix_or_fail(rel_path, hdr.owner.workspace_root + "/")
rel_path = _removeprefix_or_fail(rel_path, hdr.owner.package + "/")
rel_path = _removeprefix_or_fail(rel_path, "include/")
out_hdr = ctx.actions.declare_file(
"{0}/clang_resource_dir/include/{1}".format(prefix, rel_path),
)
ctx.actions.symlink(output = out_hdr, target_file = hdr)
outputs.append(out_hdr)
return [DefaultInfo(files = depset(outputs))]
carbon_runtimes = rule(
implementation = _carbon_runtimes_impl,
attrs = {
"builtins_archive": attr.label(mandatory = True, allow_files = [".a"]),
"clang_hdrs": attr.label_list(mandatory = True, allow_files = True),
"crt_copts": attr.string_list(default = []),
"crtbegin_src": attr.label(allow_files = [".c"]),
"crtend_src": attr.label(allow_files = [".c"]),
"libcxx_archive": attr.label(mandatory = True, allow_files = [".a"]),
"libunwind_archive": attr.label(mandatory = True, allow_files = [".a"]),
"target_triple": attr.string(mandatory = True),
"_cc_toolchain": attr.label(
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
),
},
toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
fragments = ["cpp"],
doc = """Builds a Carbon runtimes tree under the `name` directory.
This rule works to replicate the behavior of the Carbon toolchain building a
runtimes tree directly in Bazel to allow it to fully benefit from Bazel's
orchestration, caching, and even remote execution.
It produces a runtimes tree customized for the specific target platform,
similar to what the Carbon toolchain does on its own when invoked outside of
Bazel.
The runtimes tree includes a complete Clang resource-dir, including CRT
begin/end objects, and the builtins library. It also includes a built libc++
and libunwind library. These are arranged in the standard Carbon runtimes
layout so that they are correctly found by the toolchain.
""",
)
@@ -0,0 +1,10 @@
# 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
package(default_visibility = ["//visibility:public"])
filegroup(
name = "clang_hdrs",
srcs = glob(["include/**"]),
)
+9 -2
View File
@@ -6,9 +6,16 @@ load("//bazel:carbon_cc_toolchain_config.bzl", "carbon_cc_toolchain_suite")
package(default_visibility = ["//visibility:public"])
constraint_setting(name = "runtimes_build")
constraint_value(
name = "is_runtimes_build",
constraint_setting = ":runtimes_build",
)
carbon_cc_toolchain_suite(
name = "carbon_cc_toolchain",
configs = [
name = "carbon",
platforms = [
("linux", "aarch64"),
("linux", "x86_64"),
("freebsd", "x86_64"),
@@ -0,0 +1,25 @@
# 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
"""Workaround for lack of easy way to add private includes.
This is a workaround for the following Bazel issue:
https://github.com/bazelbuild/bazel/issues/2670
"""
def make_include_copts(include_dirs):
"""Create `copts` to search the provided directories for includes."""
copts = []
prefix = ""
repo_name = native.repository_name()
if repo_name != "@":
prefix = "external/{}/".format(repo_name[1:])
package_name = native.package_name()
for include_dir in include_dirs:
copts.append("-I{}{}/{}".format(prefix, package_name, include_dir))
copts.append("-I$(GENDIR)/{}{}/{}".format(prefix, package_name, include_dir))
return copts
+196
View File
@@ -0,0 +1,196 @@
# 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
load("@rules_cc//cc:defs.bzl", "cc_library")
load("//bazel:carbon_runtimes.bzl", "carbon_runtimes")
load("//bazel:make_include_copts.bzl", "make_include_copts")
load(
"//bazel:runtimes_build_vars.bzl",
"builtins_aarch64_srcs",
"builtins_aarch64_textual_srcs",
"builtins_copts",
"builtins_i386_srcs",
"builtins_i386_textual_srcs",
"builtins_x86_64_srcs",
"builtins_x86_64_textual_srcs",
"crt_copts",
"crtbegin_src",
"crtend_src",
"libc_internal_libcxx_hdrs",
"libcxx_copts",
"libcxx_hdrs",
"libcxx_linux_srcs",
"libcxx_macos_srcs",
"libcxx_win32_srcs",
"libcxxabi_hdrs",
"libcxxabi_srcs",
"libcxxabi_textual_srcs",
"libunwind_copts",
"libunwind_hdrs",
"libunwind_srcs",
"llvm_version_major",
)
package(default_visibility = ["//visibility:public"])
# Clang looks in a target-triple subdirectory of its resource directory for the
# builtins and CRT files. Triples capture a large range of settings and aren't
# even consistent structurally between platforms, so we expect to have roughly
# one setting per supported target triple. By convention, we name them after the
# target triple.
#
# TODO: Add constraints and other settings so we can select the correct target
# triple for different `libc`s.
#
# TODO: Add other OS and CPU triples.
config_setting(
name = "x86_64-unknown-linux-gnu",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
)
config_setting(
name = "aarch64-unknown-linux-gnu",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:aarch64",
],
)
cc_library(
name = "builtins_internal",
hdrs_check = "strict",
textual_hdrs = select({
"@platforms//cpu:aarch64": builtins_aarch64_textual_srcs,
"@platforms//cpu:i386": builtins_i386_textual_srcs,
"@platforms//cpu:x86_64": builtins_x86_64_textual_srcs,
"//conditions:default": [],
}),
)
cc_library(
name = "builtins",
srcs = select({
"@platforms//cpu:aarch64": builtins_aarch64_srcs,
"@platforms//cpu:i386": builtins_i386_srcs,
"@platforms//cpu:x86_64": builtins_x86_64_srcs,
"//conditions:default": [],
}),
copts = builtins_copts + make_include_copts([
"builtins",
]),
hdrs_check = "strict",
deps = [":builtins_internal"],
)
filegroup(
name = "builtins_archive",
srcs = [":builtins"],
output_group = "archive",
)
filegroup(
name = "libunwind_hdrs",
srcs = libunwind_hdrs,
)
cc_library(
name = "libunwind",
srcs = libunwind_srcs,
hdrs = [":libunwind_hdrs"],
copts = libunwind_copts + [
# We disable all warnings as upstream isn't clean with the common
# warning flags Carbon uses by default.
"-w",
],
hdrs_check = "strict",
includes = ["libunwind/include"],
linkstatic = 1,
)
filegroup(
name = "libunwind_archive",
srcs = [":libunwind"],
output_group = "archive",
)
cc_library(
name = "libcxxabi_internal",
hdrs_check = "strict",
textual_hdrs = libcxxabi_textual_srcs,
)
cc_library(
name = "libc_internal_libcxx",
hdrs = libc_internal_libcxx_hdrs,
hdrs_check = "strict",
)
filegroup(
name = "libcxx_hdrs",
srcs = [
"libcxx/include/__assertion_handler",
"libcxx/include/__config_site",
] + libcxx_hdrs + libcxxabi_hdrs,
)
cc_library(
name = "libcxx",
srcs = select({
"@platforms//os:macos": libcxx_macos_srcs,
"@platforms//os:windows": libcxx_win32_srcs,
"//conditions:default": libcxx_linux_srcs,
}) + libcxxabi_srcs,
hdrs = [":libcxx_hdrs"],
copts = libcxx_copts + make_include_copts([
"libcxx/src",
"libc/internal",
]) + [
# We disable all warnings as upstream isn't clean with the common
# warning flags Carbon uses by default.
"-w",
],
hdrs_check = "strict",
includes = [
"libcxx/include",
"libcxxabi/include",
],
linkstatic = 1,
deps = [
":libc_internal_libcxx",
":libcxxabi_internal",
],
)
filegroup(
name = "libcxx_archive",
srcs = [":libcxx"],
output_group = "archive",
)
carbon_runtimes(
name = "carbon_runtimes",
builtins_archive = ":builtins_archive",
clang_hdrs = [
"//llvm/lib/clang/{0}:clang_hdrs".format(llvm_version_major),
],
crt_copts = crt_copts,
crtbegin_src = select({
"@platforms//os:linux": crtbegin_src,
"//conditions:default": None,
}),
crtend_src = select({
"@platforms//os:linux": crtend_src,
"//conditions:default": None,
}),
libcxx_archive = ":libcxx_archive",
libunwind_archive = ":libunwind_archive",
target_triple = select({
":aarch64-unknown-linux-gnu": "aarch64-unknown-linux-gnu",
":x86_64-unknown-linux-gnu": "x86_64-unknown-linux-gnu",
"//conditions:default": "",
}),
)