Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
9169785
Add environment variable to skip printing time in bootstrap tracing logs
Kobzol Aug 11, 2026
33271bd
Use `LlvmCiMode` to distinguish whether LLVM should be downloaded fro…
Kobzol Aug 11, 2026
8f2c2bb
Add explicit `LlvmFromCi` step
Kobzol Aug 11, 2026
ab49dc4
Explicitly store in `LlvmOutput` whether we should link to it dynamic…
Kobzol Aug 11, 2026
8ddf956
Reduce dependency on the `Builder::llvm_link_shared` function
Kobzol Aug 11, 2026
79cf1e7
Store the name of the link-type.txt file in a shared constant
Kobzol Aug 11, 2026
adbcc9e
Add `LlvmKind` to distinguish how was LLVM provided
Kobzol Aug 11, 2026
f535c14
Centralize handling of LLVM linkage mode
Kobzol Aug 11, 2026
41f54f7
Only call `maybe_download_ci_llvm` in `try_download_ci_llvm`
Kobzol Aug 11, 2026
da2de27
Stop overriding llvm-config when using download-ci-llvm in config par…
Kobzol Aug 11, 2026
952d4be
Move `llvm_out` from `Build` to `Builder`
Kobzol Aug 11, 2026
e3a4831
Fix downloading LLVM from CI in dry run
Kobzol Aug 11, 2026
b095a44
Remove the `ci_llvm_root` function
Kobzol Aug 11, 2026
653cca2
Rename `prebuilt_llvm_config` to `get_llvm_build_status`
Kobzol Aug 11, 2026
299d6f1
Add `prebuilt_llvm_output` function to check whether prebuilt LLVM is…
Kobzol Aug 11, 2026
f8403e5
Fix tracing compilation errors
Kobzol Aug 11, 2026
0896a61
Fix tests
Kobzol Aug 11, 2026
6b5cad6
Fix checking of compiler-rt sources in dry run
Kobzol Aug 12, 2026
53bd738
Fix Clippy
Kobzol Aug 12, 2026
0a92a1f
Document `BOOTSTRAP_TRACING_SKIP_TIME` in the rustc-dev-guide
Kobzol Aug 15, 2026
6644179
Rename `TracingPrinter` field to avoid double negative
Kobzol Aug 15, 2026
a0b57de
Rename `maybe_download_ci_llvm` to `maybe_download_host_ci_llvm`
Kobzol Aug 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 15 additions & 14 deletions src/bootstrap/src/core/build_steps/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use serde_derive::Deserialize;
use tracing::span;

use crate::core::build_steps::gcc::{Gcc, GccOutput, GccTargetPair};
use crate::core::build_steps::llvm::{LlvmFromCi, prebuilt_llvm_output};
use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts};
use crate::core::build_steps::{dist, llvm};
use crate::core::builder::{
Expand Down Expand Up @@ -505,14 +506,16 @@ pub fn std_crates_for_make_run(run: &RunConfig<'_>) -> Vec<String> {
/// downloaded copy of CI LLVM, then we try to use the `compiler-rt` sources from
/// there instead, which lets us avoid checking out the LLVM submodule.
fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
// Try to use `compiler-rt` sources from downloaded CI LLVM, if possible.
if builder.config.llvm_from_ci {
// CI LLVM might not have been downloaded yet, so try to download it now.
builder.config.maybe_download_ci_llvm();
let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
if ci_llvm_compiler_rt.exists() {
return ci_llvm_compiler_rt;
// Try to use `compiler-rt` sources from downloaded CI LLVM, if available
if let Some(downloaded_llvm) = builder.ensure(LlvmFromCi { target: builder.host_target }) {
let ci_llvm_compiler_rt = downloaded_llvm.output.root_dir().join("compiler-rt");
if !builder.config.dry_run() {
assert!(
ci_llvm_compiler_rt.exists(),
"compiler-rt sources not found in LLVM downloaded from CI at {ci_llvm_compiler_rt:?}"
);
}
return ci_llvm_compiler_rt;
}

// Otherwise, fall back to requiring the LLVM submodule.
Expand Down Expand Up @@ -1387,9 +1390,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
// (i.e. it's already built or is downloadable), we prefer to maintain a
// consistent environment between check and non-check builds.
if builder.config.llvm_enabled(target) {
let building_llvm_is_expensive =
crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
.should_build();
let building_llvm_is_expensive = prebuilt_llvm_output(builder, target).is_none();

let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
if !skip_llvm {
Expand Down Expand Up @@ -1419,13 +1420,13 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
/// Note that this has the side-effect of _building LLVM_, which is sometimes
/// unwanted (e.g. for check builds).
fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
if builder.config.is_rust_llvm(target) {
let llvm_output = builder.ensure(llvm::Llvm { target });
if builder.config.is_rust_llvm(&llvm_output, target) {
cargo.env("LLVM_RUSTLLVM", "1");
}
if builder.config.llvm_enzyme {
cargo.env("LLVM_ENZYME", "1");
}
let llvm_output = builder.ensure(llvm::Llvm { target });
if builder.config.llvm_offload {
builder.ensure(llvm::OmpOffload { target });
cargo.env("LLVM_OFFLOAD", "1");
Expand Down Expand Up @@ -1484,7 +1485,7 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect
);
cargo.env("LLVM_STATIC_STDCPP", file);
}
if builder.llvm_link_shared() {
if llvm_output.link_shared() {
cargo.env("LLVM_LINK_SHARED", "1");
}
if builder.config.llvm_use_libcxx {
Expand Down Expand Up @@ -2185,7 +2186,7 @@ impl CommandLineStep for Assemble {
let src_path = llvm_bin_dir.join(&tool_exe);

// When using `download-ci-llvm`, some of the tools may not exist, so skip trying to copy them.
if !src_path.exists() && builder.config.llvm_from_ci {
if !src_path.exists() && builder.config.llvm_ci_mode.download_from_ci() {
eprintln!("{} does not exist; skipping copy", src_path.display());
continue;
}
Expand Down
53 changes: 38 additions & 15 deletions src/bootstrap/src/core/build_steps/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ use crate::core::build_steps::compile::{
};
use crate::core::build_steps::doc::DocumentationFormat;
use crate::core::build_steps::gcc::GccTargetPair;
use crate::core::build_steps::llvm::{
LLVM_CI_LINK_TYPE_PATH, LlvmBuildStatus, get_llvm_build_status,
};
use crate::core::build_steps::tool::{
self, RustcPrivateCompilers, ToolTargetBuildMode, get_tool_target_compiler,
};
Expand Down Expand Up @@ -2474,6 +2477,7 @@ fn install_llvm_file(
)]
fn maybe_install_llvm(
builder: &Builder<'_>,
llvm: &LlvmBuildStatus,
target: TargetSelection,
dst_libdir: &Path,
install_symlink: bool,
Expand All @@ -2494,7 +2498,14 @@ fn maybe_install_llvm(
//
// If the LLVM is coming from ourselves (just from CI) though, we
// still want to install it, as it otherwise won't be available.
if builder.config.is_system_llvm(target) {

// FIXME: this should be simplified once we stop pre-setting LLVM CI llvm-config during
// config parsing.
let is_system_llvm =
builder.config.target_config.get(&target).and_then(|t| t.llvm_config.as_ref()).is_some()
&& !(builder.config.llvm_ci_mode.download_from_ci()
&& builder.config.is_host_target(target));
if is_system_llvm {
trace!("system LLVM requested, no install");
return false;
}
Expand All @@ -2504,7 +2515,7 @@ fn maybe_install_llvm(
// clear why this is the case, though. llvm-config will emit the versioned
// paths and we don't want those in the sysroot (as we're expecting
// unversioned paths).
if target.contains("apple-darwin") && builder.llvm_link_shared() {
if target.contains("apple-darwin") && llvm.llvm_output().link_shared() {
let src_libdir = builder.llvm_out(target).join("lib");
let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
if llvm_dylib_path.exists() {
Expand Down Expand Up @@ -2532,7 +2543,7 @@ fn maybe_install_llvm(
!builder.config.dry_run()
} else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmOutput {
host_llvm_config, ..
}) = llvm::prebuilt_llvm_config(builder, target, true)
}) = llvm
{
trace!("LLVM already built, installing LLVM files");
let mut cmd = command(host_llvm_config);
Expand Down Expand Up @@ -2565,19 +2576,23 @@ fn maybe_install_llvm(
name = "maybe_install_llvm_target",
skip_all,
fields(
llvm_link_shared = ?builder.llvm_link_shared(),
target = ?target,
sysroot = ?sysroot,
),
),
)]
pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");

// We need to figure out the link mode from a LLVM, if it is provided, but without forcing it
// to be built if it isn't.
let config = get_llvm_build_status(builder, target);

// We do not need to copy LLVM files into the sysroot if it is not
// dynamically linked; it is already included into librustc_llvm
// statically.
if builder.llvm_link_shared() {
maybe_install_llvm(builder, target, &dst_libdir, false);
if config.llvm_output().link_shared() {
maybe_install_llvm(builder, &config, target, &dst_libdir, false);
}
}

Expand All @@ -2589,26 +2604,30 @@ pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection,
name = "maybe_install_llvm_runtime",
skip_all,
fields(
llvm_link_shared = ?builder.llvm_link_shared(),
target = ?target,
sysroot = ?sysroot,
),
),
)]
pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
let dst_libdir = sysroot.join(builder.libdir_relative(Compiler::new(1, target)));

// We need to figure out the link mode from a LLVM, if it is provided, but without forcing it
// to be built if it isn't.
let config = get_llvm_build_status(builder, target);

// We do not need to copy LLVM files into the sysroot if it is not
// dynamically linked; it is already included into librustc_llvm
// statically.
if builder.llvm_link_shared() {
maybe_install_llvm(builder, target, &dst_libdir, false);
if config.llvm_output().link_shared() {
maybe_install_llvm(builder, &config, target, &dst_libdir, false);

// To workaround lack of rpath on Windows, we bundle another copy of
// the LLVM DLL to make rust-lld and llvm-tools work when `sysroot/bin`
// is missing from PATH, i.e. when they not launched by rustc.
if target.triple.contains("windows") {
let dst_libdir = sysroot.join("lib/rustlib").join(target).join("bin");
maybe_install_llvm(builder, target, &dst_libdir, false);
maybe_install_llvm(builder, &config, target, &dst_libdir, false);
}
}
}
Expand Down Expand Up @@ -2670,7 +2689,7 @@ impl CommandLineStep for LlvmTools {

// Run only if a custom llvm-config is not used
if let Some(config) = builder.config.target_config.get(&target)
&& !builder.config.llvm_from_ci
&& !builder.config.llvm_ci_mode.download_from_ci()
&& config.llvm_config.is_some()
{
builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
Expand All @@ -2694,7 +2713,7 @@ impl CommandLineStep for LlvmTools {
for tool in tools_to_install(&builder.paths) {
let exe = src_bindir.join(exe(tool, target));
// When using `download-ci-llvm`, some of the tools may not exist, so skip trying to copy them.
if !exe.exists() && builder.config.llvm_from_ci {
if !exe.exists() && builder.config.llvm_ci_mode.download_from_ci() {
eprintln!("{} does not exist; skipping copy", exe.display());
continue;
}
Expand Down Expand Up @@ -2960,9 +2979,13 @@ impl CommandLineStep for RustDev {
// of `rustc-dev` to support the inherited `-lLLVM` when using the
// compiler libraries.
let dst_libdir = tarball.image_dir().join("lib");
maybe_install_llvm(builder, target, &dst_libdir, true);
let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);

let config = get_llvm_build_status(builder, target);
maybe_install_llvm(builder, &config, target, &dst_libdir, true);

// Store the link type, so that it can be read by bootstrap after the archive is downloaded
let link_type = if llvm_output.link_shared() { "dynamic" } else { "static" };
t!(std::fs::write(tarball.image_dir().join(LLVM_CI_LINK_TYPE_PATH), link_type), dst_libdir);

// Copy the `compiler-rt` source, so that `library/profiler_builtins`
// can potentially use it to build the profiler runtime without needing
Expand Down
Loading
Loading