mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 22:02:52 +01:00
Previously, the Clang runtimes building only considered building the target resource directory, and was only _internally_ asynchronous. Because the asynchrony was only internal, it could use the function frame as a context object throughout the build of the resource dir. This is simple but doesn't generalize well to more runtimes: if we want to add 2 or 3 more runtimes, we want them to _all_ build asynchronously. That means using some asynchronous builder that maintains the context and allows them to proceed concurrently with other work. This also factors all the runtimes building code into a separate set of files. These aren't separate libraries at this point due to the `ClangRunner` in some cases wanting to build runtimes on-demand, but it at least lets us organize the code more cleanly. Because this splits code between `clang_runner.*` and `clang_runtimes.*`, it also works to update the `#include`s for both to be roughly accurate. I used ClangD's include cleaner for this and it probably also did some latent cleaning as it went, but that's the reason for the churn of `#include` lines. The archive building is also factored out into a re-usable helper. This is a bit "over factored" in this PR, but supports the next PR that uses the same code to build archives for other runtimes. This also overhauls the synchronization used -- it uses a simple `Latch` construct introduced in a previous PR to coordinate between the steps of building the runtimes. Last but not least, it factors the "enable leaking" state out of a boolean in the runner to a parameter. This is important in the face of concurrent calls as otherwise toggling this boolean can create a race. The next PR will layer building more runtimes on top of this new factoring. --------- Co-authored-by: David Blaikie <dblaikie@gmail.com>
104 lines
3.5 KiB
C++
104 lines
3.5 KiB
C++
// 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
|
|
|
|
#include "toolchain/driver/build_runtimes_subcommand.h"
|
|
|
|
#include "llvm/TargetParser/Triple.h"
|
|
#include "toolchain/driver/clang_runner.h"
|
|
#include "toolchain/driver/clang_runtimes.h"
|
|
|
|
namespace Carbon {
|
|
|
|
auto BuildRuntimesOptions::Build(CommandLine::CommandBuilder& b) -> void {
|
|
b.AddStringOption(
|
|
{
|
|
.name = "output-directory",
|
|
.value_name = "DIR",
|
|
.help = R"""(
|
|
The directory to populate with runtime libraries suitable for the selected code
|
|
generation options.
|
|
)""",
|
|
},
|
|
[&](auto& arg_b) { arg_b.Set(&directory); });
|
|
|
|
codegen_options.Build(b);
|
|
}
|
|
|
|
static constexpr CommandLine::CommandInfo SubcommandInfo = {
|
|
.name = "build-runtimes",
|
|
.help = R"""(
|
|
Build Carbon's runtime libraries.
|
|
|
|
This subcommand builds Carbon's runtime libraries for a particular code
|
|
generation target, either in their default location or a specified one.
|
|
|
|
Running this command directly is not necessary as Carbon will build and cache
|
|
runtimes as needed when linking, but building them directly can aid in
|
|
debugging issues or allow them to be prebuilt, possibly with customized code
|
|
generation flags, and used explicitly when linking.
|
|
)""",
|
|
};
|
|
|
|
BuildRuntimesSubcommand::BuildRuntimesSubcommand()
|
|
: DriverSubcommand(SubcommandInfo) {}
|
|
|
|
auto BuildRuntimesSubcommand::Run(DriverEnv& driver_env) -> DriverResult {
|
|
// Don't run Clang when fuzzing, it is known to not be reliable under fuzzing
|
|
// due to many unfixed issues.
|
|
if (TestAndDiagnoseIfFuzzingExternalLibraries(driver_env, "clang")) {
|
|
return {.success = false};
|
|
}
|
|
|
|
// For diagnosing filesystem or other errors when building runtimes.
|
|
CARBON_DIAGNOSTIC(FailureBuildingRuntimes, Error,
|
|
"failure building runtimes: {0}", std::string);
|
|
|
|
auto run_result = RunInternal(driver_env);
|
|
if (!run_result.ok()) {
|
|
driver_env.emitter.Emit(FailureBuildingRuntimes,
|
|
run_result.error().message());
|
|
return {.success = false};
|
|
}
|
|
|
|
llvm::outs() << "Built runtimes: " << *run_result << "\n";
|
|
return {.success = true};
|
|
}
|
|
|
|
auto BuildRuntimesSubcommand::RunInternal(DriverEnv& driver_env)
|
|
-> ErrorOr<std::filesystem::path> {
|
|
ClangRunner runner(driver_env.installation, driver_env.fs,
|
|
driver_env.vlog_stream);
|
|
|
|
Runtimes::Cache::Features features = {
|
|
.target = options_.codegen_options.target.str()};
|
|
|
|
bool is_cache = options_.directory.empty();
|
|
std::filesystem::path explicit_output_path = options_.directory.str();
|
|
if (!is_cache) {
|
|
auto access_result = Filesystem::Cwd().Access(explicit_output_path);
|
|
if (access_result.ok()) {
|
|
return Error("output directory already exists");
|
|
}
|
|
if (!access_result.error().no_entity()) {
|
|
return std::move(access_result).error();
|
|
}
|
|
}
|
|
|
|
CARBON_ASSIGN_OR_RETURN(
|
|
auto runtimes,
|
|
is_cache ? driver_env.runtimes_cache.Lookup(features)
|
|
: Runtimes::Make(explicit_output_path, driver_env.vlog_stream));
|
|
CARBON_ASSIGN_OR_RETURN(auto tmp_dir, Filesystem::MakeTmpDir());
|
|
|
|
ClangResourceDirBuilder resource_dir_builder(&runner, driver_env.thread_pool,
|
|
llvm::Triple(features.target),
|
|
&runtimes);
|
|
|
|
CARBON_RETURN_IF_ERROR(std::move(resource_dir_builder).Wait());
|
|
|
|
return runtimes.base_path();
|
|
}
|
|
|
|
} // namespace Carbon
|