| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- # 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,
- )
|