mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
This also switches to a more Bazel-based install layout, skipping the FHS-based synthetic layout. The FHS-based layout is still reconstructed explicitly when building an installable tar-ball. The biggest change is to configure the just-built install as a Bazel toolchain, including allowing it to build its own runtime libraries as native Bazel libraries. This removes the need for a monolithic runtimes build, all of that code logic is removed. This should also pave the way to using the just-built toolchain for doing a full 3-stage bootstrap. Building the 2nd stage is included here as it was a particularly effective way to test that the Bazel integration was fully working. Adding a 3rd-stage check for stability is future work, but should be pretty easy. There is a down-side: this uses the busybox to do the runtimes compilation, which means they will be re-built after ~any change to Carbon. However, the integration with Bazel should largely pay for this, and we can continue to factor the tests away from depending on built runtimes in most cases. Now that we're building and testing the runtimes more directly, this surfaced a problem with the layout of runtimes on macOS that is fixed here. All of the Darwin OSes use a custom layout for their resource directory compared to other targets. We now model this in both the C++ built runtimes and the Bazel built runtimes. Assisted-by: Gemini via Antigravity
200 lines
6.5 KiB
Python
200 lines
6.5 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
|
|
|
|
"""Rules for constructing install information."""
|
|
|
|
load("@rules_pkg//pkg:mappings.bzl", "pkg_attributes", "pkg_filegroup", "pkg_files", "pkg_mklink", "strip_prefix")
|
|
load("//toolchain/base:llvm_tools.bzl", "LLVM_MAIN_TOOLS", "LLVM_TOOL_ALIASES")
|
|
|
|
_clang_aliases = [
|
|
"clang",
|
|
"clang++",
|
|
"clang-cl",
|
|
"clang-cpp",
|
|
]
|
|
|
|
# TODO: Add remaining aliases of LLD for Windows and WASM when we have support
|
|
# for them wired up through the busybox.
|
|
_lld_aliases = [
|
|
"ld.lld",
|
|
"ld64.lld",
|
|
]
|
|
|
|
_llvm_binaries = _clang_aliases + _lld_aliases + [
|
|
tool.bin_name
|
|
for tool in LLVM_MAIN_TOOLS.values()
|
|
] + [
|
|
"llvm-" + alias
|
|
for (_, aliases) in LLVM_TOOL_ALIASES.items()
|
|
for alias in aliases
|
|
]
|
|
|
|
def _toolchain_llvm_binaries_impl(ctx):
|
|
outputs = []
|
|
for bin in _llvm_binaries:
|
|
out = ctx.actions.declare_file(ctx.attr.prefix + "llvm/bin/" + bin)
|
|
ctx.actions.symlink(
|
|
output = out,
|
|
target_file = ctx.files.carbon_binary[0],
|
|
)
|
|
outputs.append(out)
|
|
|
|
return [DefaultInfo(files = depset(direct = outputs))]
|
|
|
|
toolchain_llvm_binaries = rule(
|
|
doc = "Creates symlinks for LLVM binaries pointing to a single Carbon binary.",
|
|
implementation = _toolchain_llvm_binaries_impl,
|
|
attrs = {
|
|
"carbon_binary": attr.label(
|
|
allow_single_file = True,
|
|
#executable = True,
|
|
mandatory = True,
|
|
#cfg = None,
|
|
),
|
|
"prefix": attr.string(default = ""),
|
|
},
|
|
)
|
|
|
|
def _removeprefix_or_fail(s, prefix):
|
|
if prefix == "":
|
|
return s
|
|
new_s = s.removeprefix(prefix)
|
|
if new_s == s:
|
|
fail("Unable to remove prefix '{0}' from '{1}'".format(prefix, s))
|
|
return new_s
|
|
|
|
def _get_pkg_relative_path(file):
|
|
path = file.path
|
|
if file.root.path != "":
|
|
path = _removeprefix_or_fail(path, file.root.path + "/")
|
|
if file.owner.workspace_root != "":
|
|
path = _removeprefix_or_fail(path, file.owner.workspace_root + "/")
|
|
return _removeprefix_or_fail(path, file.owner.package + "/")
|
|
|
|
def _toolchain_files_impl(ctx):
|
|
prefix = ctx.attr.prefix
|
|
outputs = []
|
|
for src in ctx.files.srcs:
|
|
rel_path = _get_pkg_relative_path(src)
|
|
rel_path = _removeprefix_or_fail(rel_path, ctx.attr.remove_prefix)
|
|
if rel_path in ctx.attr.renames:
|
|
rel_path = ctx.attr.renames[rel_path]
|
|
out = ctx.actions.declare_file("{0}{1}".format(prefix, rel_path))
|
|
ctx.actions.symlink(output = out, target_file = src)
|
|
outputs.append(out)
|
|
|
|
return [DefaultInfo(files = depset(outputs))]
|
|
|
|
toolchain_files = rule(
|
|
doc = "Arranges files into a directory structure by symlinking them with prefix removal and renames.",
|
|
implementation = _toolchain_files_impl,
|
|
attrs = {
|
|
"prefix": attr.string(default = ""),
|
|
"remove_prefix": attr.string(default = ""),
|
|
"renames": attr.string_dict(default = {}),
|
|
"srcs": attr.label_list(allow_files = True),
|
|
},
|
|
)
|
|
|
|
def _filtered_files_impl(ctx):
|
|
include_set = set()
|
|
for filter_src in ctx.files.filter_to_srcs:
|
|
rel_path = _get_pkg_relative_path(filter_src)
|
|
include_set.add(_removeprefix_or_fail(rel_path, ctx.attr.filter_to_srcs_prefix))
|
|
|
|
outputs = []
|
|
for src in ctx.files.srcs:
|
|
rel_path = _get_pkg_relative_path(src)
|
|
if _removeprefix_or_fail(rel_path, ctx.attr.srcs_prefix) in include_set:
|
|
outputs.append(src)
|
|
|
|
return [DefaultInfo(files = depset(outputs))]
|
|
|
|
filtered_files = rule(
|
|
doc = "Filters a set of files based on their relative paths matching another set of files.",
|
|
implementation = _filtered_files_impl,
|
|
attrs = {
|
|
"filter_to_srcs": attr.label_list(),
|
|
"filter_to_srcs_prefix": attr.string(default = ""),
|
|
"srcs": attr.label_list(),
|
|
"srcs_prefix": attr.string(default = ""),
|
|
},
|
|
)
|
|
|
|
def filtered_toolchain_files(name, prefix, remove_prefix, srcs_groups):
|
|
"""A collection of filtered toolchain files from overlapping `srcs`."""
|
|
name_base = name.removesuffix("_srcs")
|
|
if name_base == "" or name_base == name:
|
|
fail("Invalid name for building a set of filtered toolchain files.")
|
|
toolchain_files(
|
|
name = name_base + "_all_srcs",
|
|
srcs = srcs_groups,
|
|
prefix = prefix,
|
|
remove_prefix = remove_prefix,
|
|
)
|
|
|
|
for srcs in srcs_groups:
|
|
suffix = srcs.partition(":")[2].removeprefix(name_base)
|
|
filtered_files(
|
|
name = name_base + suffix,
|
|
srcs = [":" + name_base + "_all_srcs"],
|
|
srcs_prefix = prefix,
|
|
filter_to_srcs = [srcs],
|
|
filter_to_srcs_prefix = remove_prefix,
|
|
)
|
|
|
|
def toolchain_pkg_filegroup(name, carbon_busybox, srcs, tags = []):
|
|
"""Given a CMake-style install prefix[1], the hierarchy looks like:
|
|
|
|
- prefix/bin: Binaries intended for direct use.
|
|
- prefix/lib/carbon: Private data and files.
|
|
- prefix/lib/carbon/core: The `Core` package files.
|
|
- prefix/lib/carbon/llvm/bin: LLVM binaries.
|
|
|
|
This will be how installs are provided on Unix-y platforms, and is loosely
|
|
based on the FHS (Filesystem Hierarchy Standard). See the CMake install prefix
|
|
documentation[1] for more details.
|
|
|
|
[1]: https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html
|
|
"""
|
|
pkg_srcs = []
|
|
|
|
# Separately handle the busybox so that we can set its attributes.
|
|
pkg_files(
|
|
name = name + "_busybox",
|
|
srcs = [carbon_busybox],
|
|
prefix = "lib/carbon",
|
|
attributes = pkg_attributes(mode = "0755"),
|
|
tags = tags,
|
|
)
|
|
pkg_srcs.append(":" + name + "_busybox")
|
|
|
|
pkg_files(
|
|
name = name + "_srcs",
|
|
srcs = srcs,
|
|
prefix = "lib/carbon",
|
|
strip_prefix = strip_prefix.from_pkg(),
|
|
tags = tags,
|
|
)
|
|
pkg_srcs.append(":" + name + "_srcs")
|
|
|
|
for bin in _llvm_binaries:
|
|
pkg_mklink(
|
|
name = name + "_llvm_symlink_" + bin,
|
|
link_name = "lib/carbon/llvm/bin/" + bin,
|
|
target = "../../carbon-busybox",
|
|
tags = tags,
|
|
)
|
|
pkg_srcs.append(":" + name + "_llvm_symlink_" + bin)
|
|
|
|
pkg_mklink(
|
|
name = name + "_bin_symlink",
|
|
link_name = "bin/carbon",
|
|
target = "../lib/carbon/carbon-busybox",
|
|
tags = tags,
|
|
)
|
|
pkg_srcs.append(":" + name + "_bin_symlink")
|
|
|
|
pkg_filegroup(name = name, srcs = pkg_srcs, tags = tags)
|