| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- # 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 + "/")
- if hdr.owner.workspace_root != "":
- rel_path = _removeprefix_or_fail(rel_path, hdr.owner.workspace_root + "/")
- if hdr.owner.package != "":
- rel_path = _removeprefix_or_fail(rel_path, hdr.owner.package + "/")
- rel_path = _removeprefix_or_fail(rel_path, ctx.attr.clang_hdrs_prefix)
- 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),
- "clang_hdrs_prefix": attr.string(default = "include/"),
- "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.
- """,
- )
|