mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 20:30:14 +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.
381 lines
13 KiB
Python
381 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",
|
|
"tool_path",
|
|
)
|
|
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 = []
|
|
sdk_settings = []
|
|
if clang_sysroot != "None" and clang_sysroot != "/":
|
|
builtin_sysroot = clang_sysroot
|
|
sysroot_include_search = ["%sysroot%/usr/include"]
|
|
|
|
# On MacOS, the compiler depends on this file at the root of the SDK,
|
|
# and it ends up in the `.d` files.
|
|
sdk_settings = ["%sysroot%/SDKSettings.json"]
|
|
|
|
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 + sdk_settings,
|
|
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) + [tool_path(name = "carbon-busybox", path = "carbon-busybox")],
|
|
)
|
|
|
|
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,
|
|
)
|