mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 21:10:12 +01:00
Begin building libunwind.a as part of the runtimes (#6381)
This is the first real step towards building libc++ itself, and fleshes out both the core runtimes management logic and the archive-based runtimes logic for a quite simple runtime. Nothing here causes us to _use_ libunwind, and in fact this doesn't include even the "on-demand" aspect of building `libunwind`. Instead, this just wires it up to the explicit `build-runtimes` subcommand for simple testing. The full integration along side the target directory is future work.
This commit is contained in:
@@ -116,6 +116,7 @@ http_archive(
|
||||
"@carbon//bazel/llvm_project:0001_Patch_for_mallinfo2_when_using_Bazel_build_system.patch",
|
||||
"@carbon//bazel/llvm_project:0002_Added_Bazel_build_for_compiler_rt_fuzzer.patch",
|
||||
"@carbon//bazel/llvm_project:0003_Comment_out_unloaded_proto_library_dependencies.patch",
|
||||
"@carbon//bazel/llvm_project:0004_Introduce_basic_sources_exporting_for_libunwind.patch",
|
||||
],
|
||||
strip_prefix = "llvm-project-{0}".format(llvm_project_version),
|
||||
urls = ["https://github.com/llvm/llvm-project/archive/{0}.tar.gz".format(llvm_project_version)],
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
Commit ID: a79f1facf56cc5772557cdb09d811aa11a22e43b
|
||||
Change ID: sxspxmonsuvqzuvxvrvorlumwpwromsv
|
||||
Author : Chandler Carruth <chandlerc@gmail.com> (2025-09-25 22:55:26)
|
||||
Committer: Chandler Carruth <chandlerc@gmail.com> (2025-11-17 09:59:25)
|
||||
|
||||
Introduce basic sources exporting for libunwind
|
||||
|
||||
This exports the source files directly so that they can be used to build
|
||||
this runtime library on demand.
|
||||
|
||||
diff --git a/utils/bazel/llvm-project-overlay/libunwind/BUILD.bazel b/utils/bazel/llvm-project-overlay/libunwind/BUILD.bazel
|
||||
index c9fdc819c0..7d734c5a06 100644
|
||||
--- a/utils/bazel/llvm-project-overlay/libunwind/BUILD.bazel
|
||||
+++ b/utils/bazel/llvm-project-overlay/libunwind/BUILD.bazel
|
||||
@@ -21,3 +21,19 @@
|
||||
],
|
||||
strip_include_prefix = "include",
|
||||
)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "libunwind_hdrs",
|
||||
+ srcs = glob(["include/**/*.h"]),
|
||||
+)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "libunwind_srcs",
|
||||
+ srcs = glob([
|
||||
+ "src/*.cpp",
|
||||
+ "src/*.hpp",
|
||||
+ "src/*.c",
|
||||
+ "src/*.h",
|
||||
+ "src/*.S",
|
||||
+ ]),
|
||||
+)
|
||||
@@ -37,6 +37,10 @@ BUILTINS_FILEGROUPS = {
|
||||
"x86_fp80_srcs": "@llvm-project//compiler-rt:builtins_x86_fp80_srcs",
|
||||
}
|
||||
|
||||
RUNTIMES_FILEGROUPS = {
|
||||
"libunwind_srcs": "@llvm-project//libunwind:libunwind_srcs",
|
||||
}
|
||||
|
||||
_TEMPLATE = """
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
@@ -85,6 +89,10 @@ inline constexpr llvm::StringLiteral BuiltinsI386Srcs[] = {{
|
||||
{i386_srcs}
|
||||
}};
|
||||
|
||||
constexpr inline llvm::StringLiteral LibunwindSrcs[] = {{
|
||||
{libunwind_srcs}
|
||||
}};
|
||||
|
||||
}} // namespace Carbon::RuntimeSources
|
||||
|
||||
#endif // CARBON_TOOLCHAIN_BASE_RUNTIME_SOURCES_H_
|
||||
@@ -99,6 +107,10 @@ def _builtins_path(file):
|
||||
# label name.
|
||||
return file.owner.name.removeprefix("lib/")
|
||||
|
||||
def _runtimes_path(file):
|
||||
"""Returns the runtime install path for a file in a normal runtimes library."""
|
||||
return file.owner.name
|
||||
|
||||
def _get_path(file_attr, to_path_fn):
|
||||
files = file_attr[DefaultInfo].files.to_list()
|
||||
if len(files) > 1:
|
||||
@@ -125,6 +137,9 @@ def _generate_runtime_sources_h_rule(ctx):
|
||||
} | {
|
||||
k: _get_paths(getattr(ctx.attr, "_" + k), _builtins_path)
|
||||
for k in BUILTINS_FILEGROUPS.keys()
|
||||
} | {
|
||||
k: _get_paths(getattr(ctx.attr, "_" + k), _runtimes_path)
|
||||
for k in RUNTIMES_FILEGROUPS.keys()
|
||||
})))
|
||||
return [DefaultInfo(files = depset([h_file]))]
|
||||
|
||||
@@ -135,7 +150,8 @@ generate_runtime_sources_h = rule(
|
||||
for k, v in CRT_FILES.items()
|
||||
} | {
|
||||
"_" + k: attr.label_list(default = [v], allow_files = True)
|
||||
for k, v in BUILTINS_FILEGROUPS.items()
|
||||
for k, v in BUILTINS_FILEGROUPS.items() + RUNTIMES_FILEGROUPS.items()
|
||||
} | {
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ cc_library(
|
||||
"//common:latch",
|
||||
"//common:ostream",
|
||||
"//common:vlog",
|
||||
"//toolchain/base:kind_switch",
|
||||
"//toolchain/base:runtime_sources",
|
||||
"//toolchain/install:install_paths",
|
||||
"@llvm-project//clang:basic",
|
||||
|
||||
@@ -94,8 +94,12 @@ auto BuildRuntimesSubcommand::RunInternal(DriverEnv& driver_env)
|
||||
ClangResourceDirBuilder resource_dir_builder(&runner, driver_env.thread_pool,
|
||||
llvm::Triple(features.target),
|
||||
&runtimes);
|
||||
ClangArchiveRuntimesBuilder<Runtimes::LibUnwind> lib_unwind_builder(
|
||||
&runner, driver_env.thread_pool, llvm::Triple(features.target),
|
||||
&runtimes);
|
||||
|
||||
CARBON_RETURN_IF_ERROR(std::move(resource_dir_builder).Wait());
|
||||
CARBON_RETURN_IF_ERROR(std::move(lib_unwind_builder).Wait());
|
||||
|
||||
return runtimes.base_path();
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/TargetParser/Host.h"
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
#include "toolchain/base/kind_switch.h"
|
||||
#include "toolchain/base/runtime_sources.h"
|
||||
#include "toolchain/driver/clang_runner.h"
|
||||
#include "toolchain/driver/runtimes_cache.h"
|
||||
@@ -210,6 +211,126 @@ auto ClangRuntimesBuilderBase::ArchiveBuilder::CompileMember(
|
||||
return std::move(*obj_result);
|
||||
}
|
||||
|
||||
template <Runtimes::Component Component>
|
||||
requires(Component == Runtimes::LibUnwind)
|
||||
ClangArchiveRuntimesBuilder<Component>::ClangArchiveRuntimesBuilder(
|
||||
ClangRunner* clang, llvm::ThreadPoolInterface* threads,
|
||||
llvm::Triple target_triple, Runtimes* runtimes)
|
||||
: ClangRuntimesBuilderBase(clang, threads, std::move(target_triple)) {
|
||||
// Ensure we're on a platform where we _can_ build a working runtime.
|
||||
if (target_triple_.isOSWindows()) {
|
||||
result_ =
|
||||
Error("TODO: Windows runtimes are untested and not yet supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
auto build_dir_or_error = runtimes->Build(Component);
|
||||
if (!build_dir_or_error.ok()) {
|
||||
result_ = std::move(build_dir_or_error).error();
|
||||
return;
|
||||
}
|
||||
auto build_dir = *(std::move(build_dir_or_error));
|
||||
CARBON_KIND_SWITCH(std::move(build_dir)) {
|
||||
case CARBON_KIND(std::filesystem::path build_dir_path): {
|
||||
// Found cached build.
|
||||
result_ = std::move(build_dir_path);
|
||||
return;
|
||||
}
|
||||
case CARBON_KIND(Runtimes::Builder builder): {
|
||||
runtimes_builder_ = std::move(builder);
|
||||
// Building the runtimes is handled below.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (Component == Runtimes::LibUnwind) {
|
||||
srcs_path_ = installation().libunwind_path();
|
||||
include_path_ = installation().libunwind_path() / "include";
|
||||
archive_path_ = std::filesystem::path("lib") / "libunwind.a";
|
||||
} else {
|
||||
static_assert(false,
|
||||
"Invalid runtimes component for an archive runtime builder.");
|
||||
}
|
||||
|
||||
archive_.emplace(this, archive_path_, srcs_path_, CollectSrcFiles(),
|
||||
CollectCflags());
|
||||
tasks_.async([this]() mutable { Setup(); });
|
||||
}
|
||||
|
||||
template <Runtimes::Component Component>
|
||||
requires(Component == Runtimes::LibUnwind)
|
||||
auto ClangArchiveRuntimesBuilder<Component>::CollectSrcFiles()
|
||||
-> llvm::SmallVector<llvm::StringRef> {
|
||||
if constexpr (Component == Runtimes::LibUnwind) {
|
||||
return llvm::SmallVector<llvm::StringRef>(llvm::make_filter_range(
|
||||
RuntimeSources::LibunwindSrcs, [](llvm::StringRef src) {
|
||||
return src.ends_with(".c") || src.ends_with(".cpp") ||
|
||||
src.ends_with(".S");
|
||||
}));
|
||||
} else {
|
||||
static_assert(false,
|
||||
"Invalid runtimes component for an archive runtime builder.");
|
||||
}
|
||||
}
|
||||
|
||||
template <Runtimes::Component Component>
|
||||
requires(Component == Runtimes::LibUnwind)
|
||||
auto ClangArchiveRuntimesBuilder<Component>::CollectCflags()
|
||||
-> llvm::SmallVector<llvm::StringRef> {
|
||||
if constexpr (Component == Runtimes::LibUnwind) {
|
||||
return {
|
||||
"-no-canonical-prefixes",
|
||||
"-O3",
|
||||
"-fPIC",
|
||||
"-funwind-tables",
|
||||
"-fno-exceptions",
|
||||
"-fno-rtti",
|
||||
"-nostdinc++",
|
||||
"-I",
|
||||
include_path_.native(),
|
||||
"-D_LIBUNWIND_IS_NATIVE_ONLY",
|
||||
"-w",
|
||||
};
|
||||
} else {
|
||||
static_assert(false,
|
||||
"Invalid runtimes component for an archive runtime builder.");
|
||||
}
|
||||
}
|
||||
|
||||
template <Runtimes::Component Component>
|
||||
requires(Component == Runtimes::LibUnwind)
|
||||
auto ClangArchiveRuntimesBuilder<Component>::Setup() -> void {
|
||||
// Symlink the installation's `include` into the runtime.
|
||||
CARBON_CHECK(include_path_.is_absolute(),
|
||||
"Unexpected relative include path: {0}", include_path_);
|
||||
if (auto result = runtimes_builder_->dir().Symlink("include", include_path_);
|
||||
!result.ok()) {
|
||||
result_ = std::move(result).error();
|
||||
return;
|
||||
}
|
||||
|
||||
// Finish building the runtime once the archive is built.
|
||||
Latch::Handle latch_handle = step_counter_.Init(
|
||||
[this]() mutable { tasks_.async([this]() mutable { Finish(); }); });
|
||||
|
||||
// Start building the archive itself with a handle to detect when complete.
|
||||
archive_->Setup(std::move(latch_handle));
|
||||
}
|
||||
|
||||
template <Runtimes::Component Component>
|
||||
requires(Component == Runtimes::LibUnwind)
|
||||
auto ClangArchiveRuntimesBuilder<Component>::Finish() -> void {
|
||||
CARBON_VLOG("Finished building {0}...\n", archive_path_);
|
||||
if (!archive_->result().ok()) {
|
||||
result_ = std::move(archive_->result()).error();
|
||||
return;
|
||||
}
|
||||
|
||||
result_ = (*std::move(runtimes_builder_)).Commit();
|
||||
}
|
||||
|
||||
template class ClangArchiveRuntimesBuilder<Runtimes::LibUnwind>;
|
||||
|
||||
ClangResourceDirBuilder::ClangResourceDirBuilder(
|
||||
ClangRunner* clang, llvm::ThreadPoolInterface* threads,
|
||||
llvm::Triple target_triple, Runtimes* runtimes)
|
||||
|
||||
@@ -203,6 +203,60 @@ class ClangRuntimesBuilderBase::ArchiveBuilder {
|
||||
ErrorOr<Success> result_ = Error("No archive built!");
|
||||
};
|
||||
|
||||
// A class template to build runtimes consisting of a single archive.
|
||||
//
|
||||
// The template argument comes from the `Runtimes::Component` enum, but is only
|
||||
// intended for Clang-runtimes that consist of a single archive. We use a
|
||||
// requires to enforce that the components used are exactly one of those
|
||||
// supported so we can also move instantiation into the `.cpp` file.
|
||||
template <Runtimes::Component Component>
|
||||
requires(Component == Runtimes::LibUnwind)
|
||||
class ClangArchiveRuntimesBuilder : public ClangRuntimesBuilderBase {
|
||||
public:
|
||||
// Constructing this class will attempt to build the `Component` archive into
|
||||
// `runtimes`.
|
||||
//
|
||||
// If an existing build is found, it will immediately be available.
|
||||
// Otherwise, constructing this class will schedule asynchronous work on
|
||||
// `threads` to build the archive on-demand using `clang`.
|
||||
//
|
||||
// Once constructed, callers may call `Wait` (from the base class) to wait
|
||||
// until the asynchronous work is complete and the runtimes are available. If
|
||||
// they were already available, the call to `Wait` will not block.
|
||||
ClangArchiveRuntimesBuilder(ClangRunner* clang,
|
||||
llvm::ThreadPoolInterface* threads,
|
||||
llvm::Triple target_triple, Runtimes* runtimes);
|
||||
|
||||
private:
|
||||
// Helpers to compute the list of source files and compile flags for a
|
||||
// particular archive. The implementations of these are expected to be
|
||||
// specialized for each different `Component`.
|
||||
auto CollectSrcFiles() -> llvm::SmallVector<llvm::StringRef>;
|
||||
auto CollectCflags() -> llvm::SmallVector<llvm::StringRef>;
|
||||
|
||||
// Helper to encapsulate the initial, but still asynchronous setup work.
|
||||
auto Setup() -> void;
|
||||
|
||||
// Helper to encapsulate the final asynchronous step in building the resource
|
||||
// directory.
|
||||
auto Finish() -> void;
|
||||
|
||||
// The root path used for any of the source files.
|
||||
std::filesystem::path srcs_path_;
|
||||
|
||||
// The (absolute) include path used during the compilation of the source
|
||||
// files.
|
||||
std::filesystem::path include_path_;
|
||||
|
||||
// The relative archive path within the runtimes' build directory.
|
||||
std::filesystem::path archive_path_;
|
||||
|
||||
// The archive builder if it is necessary to build the archive.
|
||||
std::optional<ArchiveBuilder> archive_;
|
||||
};
|
||||
|
||||
extern template class ClangArchiveRuntimesBuilder<Runtimes::LibUnwind>;
|
||||
|
||||
// Builds the target-specific resource directory for Clang.
|
||||
//
|
||||
// There is a resource directory installed along side the Clang binary that
|
||||
|
||||
@@ -46,6 +46,7 @@ class Runtimes {
|
||||
|
||||
enum Component {
|
||||
ClangResourceDir,
|
||||
LibUnwind,
|
||||
|
||||
NumComponents,
|
||||
};
|
||||
@@ -136,6 +137,8 @@ class Runtimes {
|
||||
switch (component) {
|
||||
case ClangResourceDir:
|
||||
return "clang_resource_dir";
|
||||
case LibUnwind:
|
||||
return "libunwind";
|
||||
case NumComponents:
|
||||
CARBON_FATAL("Invalid component");
|
||||
}
|
||||
|
||||
@@ -162,6 +162,14 @@ filegroup(
|
||||
srcs = CRT_FILES.values() + BUILTINS_FILEGROUPS.values(),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "libunwind",
|
||||
srcs = [
|
||||
"@llvm-project//libunwind:libunwind_hdrs",
|
||||
"@llvm-project//libunwind:libunwind_srcs",
|
||||
],
|
||||
)
|
||||
|
||||
# Given a root `prefix_root`, the hierarchy looks like:
|
||||
#
|
||||
# - prefix_root/bin: Binaries intended for direct use.
|
||||
@@ -195,6 +203,7 @@ install_dirs = {
|
||||
is_driver = True,
|
||||
),
|
||||
install_filegroup("core", "//core:prelude"),
|
||||
install_filegroup("libunwind", ":libunwind"),
|
||||
],
|
||||
"lib/carbon/llvm/bin": [install_symlink(
|
||||
name,
|
||||
|
||||
@@ -225,6 +225,11 @@ auto InstallPaths::llvm_runtime_srcs() const -> std::filesystem::path {
|
||||
"/src";
|
||||
}
|
||||
|
||||
auto InstallPaths::libunwind_path() const -> std::filesystem::path {
|
||||
// TODO: Adjust this to work equally well on Windows.
|
||||
return prefix_ / "lib/carbon/libunwind";
|
||||
}
|
||||
|
||||
auto InstallPaths::digest_path() const -> std::filesystem::path {
|
||||
// TODO: Adjust this to work equally well on Windows.
|
||||
return prefix_ / "lib/carbon/install_digest.txt";
|
||||
|
||||
@@ -111,6 +111,9 @@ class InstallPaths {
|
||||
// The path to the root of LLVM runtime sources.
|
||||
auto llvm_runtime_srcs() const -> std::filesystem::path;
|
||||
|
||||
// The path to `libunwind` runtime.
|
||||
auto libunwind_path() const -> std::filesystem::path;
|
||||
|
||||
// The installation digest path.
|
||||
//
|
||||
// This file contains a digest of the installation.
|
||||
|
||||
Reference in New Issue
Block a user