Skip to content

Commit 398f406

Browse files
committed
Auto merge of #122709 - onur-ozkan:use-precompiled-rustc-by-default, r=<try>
use precompiled rustc for non-dist builders Makes non-dist builders to use precompiled CI rustc by default if they are available for the target triple. As we are going to make `rust.download-rustc=if-unchanged` default option with #119899, we need to make sure `if-unchanged` logic never breaks and works as expected. As an addition, this will significantly improve the build times on CI when there's no change on the compiler. blocker for #119899 try-job: x86_64-gnu-nopt
2 parents 2e367d9 + 57274bd commit 398f406

File tree

12 files changed

+178
-15
lines changed

12 files changed

+178
-15
lines changed

src/bootstrap/src/core/builder.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,15 @@ impl StepDescription {
418418
.map(|desc| (desc.should_run)(ShouldRun::new(builder, desc.kind)))
419419
.collect::<Vec<_>>();
420420

421+
if builder.download_rustc() && (builder.kind == Kind::Dist || builder.kind == Kind::Install)
422+
{
423+
eprintln!(
424+
"ERROR: '{}' subcommand is incompatible with `rust.download-rustc`.",
425+
builder.kind.as_str()
426+
);
427+
crate::exit!(1);
428+
}
429+
421430
// sanity checks on rules
422431
for (desc, should_run) in v.iter().zip(&should_runs) {
423432
assert!(

src/bootstrap/src/core/builder/tests.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use std::thread;
22

3+
use build_helper::git::get_closest_merge_commit;
4+
35
use super::*;
46
use crate::core::build_steps::doc::DocumentationFormat;
57
use crate::core::config::Config;
@@ -212,6 +214,52 @@ fn alias_and_path_for_library() {
212214
assert_eq!(first(cache.all::<doc::Std>()), &[doc_std!(A => A, stage = 0)]);
213215
}
214216

217+
#[test]
218+
fn ci_rustc_if_unchanged_logic() {
219+
let config = Config::parse_inner(
220+
Flags::parse(&[
221+
"build".to_owned(),
222+
"--dry-run".to_owned(),
223+
"--set=rust.download-rustc='if-unchanged'".to_owned(),
224+
]),
225+
|&_| Ok(Default::default()),
226+
);
227+
228+
if config.rust_info.is_from_tarball() {
229+
return;
230+
}
231+
232+
let build = Build::new(config.clone());
233+
let builder = Builder::new(&build);
234+
235+
if config.out.exists() {
236+
fs::remove_dir_all(&config.out).unwrap();
237+
}
238+
239+
builder.run_step_descriptions(&Builder::get_step_descriptions(config.cmd.kind()), &[]);
240+
241+
let compiler_path = build.src.join("compiler");
242+
let library_path = build.src.join("compiler");
243+
244+
let commit = get_closest_merge_commit(
245+
Some(&builder.config.src),
246+
&builder.config.git_config(),
247+
&[compiler_path.clone(), library_path.clone()],
248+
)
249+
.unwrap();
250+
251+
let has_changes = !helpers::git(Some(&builder.src))
252+
.args(["diff-index", "--quiet", &commit])
253+
.arg("--")
254+
.args([compiler_path, library_path])
255+
.as_command_mut()
256+
.status()
257+
.unwrap()
258+
.success();
259+
260+
assert!(has_changes == config.download_rustc_commit.is_none());
261+
}
262+
215263
mod defaults {
216264
use pretty_assertions::assert_eq;
217265

src/bootstrap/src/core/config/config.rs

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::str::FromStr;
1313
use std::sync::OnceLock;
1414
use std::{cmp, env, fs};
1515

16+
use build_helper::ci::CiEnv;
1617
use build_helper::exit;
1718
use build_helper::git::{get_closest_merge_commit, output_result, GitConfig};
1819
use serde::{Deserialize, Deserializer};
@@ -22,6 +23,7 @@ use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX;
2223
use crate::core::build_steps::llvm;
2324
pub use crate::core::config::flags::Subcommand;
2425
use crate::core::config::flags::{Color, Flags, Warnings};
26+
use crate::core::download::is_download_ci_available;
2527
use crate::utils::cache::{Interned, INTERNER};
2628
use crate::utils::channel::{self, GitInfo};
2729
use crate::utils::helpers::{self, exe, output, t};
@@ -1616,9 +1618,11 @@ impl Config {
16161618
config.mandir = mandir.map(PathBuf::from);
16171619
}
16181620

1621+
config.llvm_assertions =
1622+
toml.llvm.as_ref().map_or(false, |llvm| llvm.assertions.unwrap_or(false));
1623+
16191624
// Store off these values as options because if they're not provided
16201625
// we'll infer default values for them later
1621-
let mut llvm_assertions = None;
16221626
let mut llvm_tests = None;
16231627
let mut llvm_enzyme = None;
16241628
let mut llvm_plugins = None;
@@ -1699,7 +1703,8 @@ impl Config {
16991703
is_user_configured_rust_channel = channel.is_some();
17001704
set(&mut config.channel, channel.clone());
17011705

1702-
config.download_rustc_commit = config.download_ci_rustc_commit(download_rustc);
1706+
config.download_rustc_commit =
1707+
config.download_ci_rustc_commit(download_rustc, config.llvm_assertions);
17031708

17041709
debug = debug_toml;
17051710
debug_assertions = debug_assertions_toml;
@@ -1824,7 +1829,7 @@ impl Config {
18241829
optimize: optimize_toml,
18251830
thin_lto,
18261831
release_debuginfo,
1827-
assertions,
1832+
assertions: _,
18281833
tests,
18291834
enzyme,
18301835
plugins,
@@ -1858,7 +1863,6 @@ impl Config {
18581863
Some(StringOrBool::Bool(false)) | None => {}
18591864
}
18601865
set(&mut config.ninja_in_file, ninja);
1861-
llvm_assertions = assertions;
18621866
llvm_tests = tests;
18631867
llvm_enzyme = enzyme;
18641868
llvm_plugins = plugins;
@@ -1887,8 +1891,8 @@ impl Config {
18871891
config.llvm_enable_warnings = enable_warnings.unwrap_or(false);
18881892
config.llvm_build_config = build_config.clone().unwrap_or(Default::default());
18891893

1890-
let asserts = llvm_assertions.unwrap_or(false);
1891-
config.llvm_from_ci = config.parse_download_ci_llvm(download_ci_llvm, asserts);
1894+
config.llvm_from_ci =
1895+
config.parse_download_ci_llvm(download_ci_llvm, config.llvm_assertions);
18921896

18931897
if config.llvm_from_ci {
18941898
let warn = |option: &str| {
@@ -2056,7 +2060,6 @@ impl Config {
20562060
// Now that we've reached the end of our configuration, infer the
20572061
// default values for all options that we haven't otherwise stored yet.
20582062

2059-
config.llvm_assertions = llvm_assertions.unwrap_or(false);
20602063
config.llvm_tests = llvm_tests.unwrap_or(false);
20612064
config.llvm_enzyme = llvm_enzyme.unwrap_or(false);
20622065
config.llvm_plugins = llvm_plugins.unwrap_or(false);
@@ -2392,8 +2395,9 @@ impl Config {
23922395
ci_config_toml,
23932396
);
23942397

2395-
let disable_ci_rustc_if_incompatible =
2396-
env::var_os("DISABLE_CI_RUSTC_IF_INCOMPATIBLE")
2398+
// Primarily used by CI runners to avoid handling download-rustc incompatible
2399+
// options one by one on shell scripts.
2400+
let disable_ci_rustc_if_incompatible = env::var_os("DISABLE_CI_RUSTC_IF_INCOMPATIBLE")
23972401
.is_some_and(|s| s == "1" || s == "true");
23982402

23992403
if disable_ci_rustc_if_incompatible && res.is_err() {
@@ -2684,7 +2688,15 @@ impl Config {
26842688
}
26852689

26862690
/// Returns the commit to download, or `None` if we shouldn't download CI artifacts.
2687-
fn download_ci_rustc_commit(&self, download_rustc: Option<StringOrBool>) -> Option<String> {
2691+
fn download_ci_rustc_commit(
2692+
&self,
2693+
download_rustc: Option<StringOrBool>,
2694+
llvm_assertions: bool,
2695+
) -> Option<String> {
2696+
if !is_download_ci_available(&self.build.triple, llvm_assertions) {
2697+
return None;
2698+
}
2699+
26882700
// If `download-rustc` is not set, default to rebuilding.
26892701
let if_unchanged = match download_rustc {
26902702
None | Some(StringOrBool::Bool(false)) => return None,
@@ -2697,7 +2709,12 @@ impl Config {
26972709

26982710
// Look for a version to compare to based on the current commit.
26992711
// Only commits merged by bors will have CI artifacts.
2700-
let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap();
2712+
let commit = get_closest_merge_commit(
2713+
Some(&self.src),
2714+
&self.git_config(),
2715+
&[self.src.join("compiler"), self.src.join("library")],
2716+
)
2717+
.unwrap();
27012718
if commit.is_empty() {
27022719
println!("ERROR: could not find commit hash for downloading rustc");
27032720
println!("HELP: maybe your repository history is too shallow?");
@@ -2706,6 +2723,19 @@ impl Config {
27062723
crate::exit!(1);
27072724
}
27082725

2726+
if CiEnv::is_ci() && {
2727+
let head_sha =
2728+
output(helpers::git(Some(&self.src)).arg("rev-parse").arg("HEAD").as_command_mut());
2729+
let head_sha = head_sha.trim();
2730+
commit == head_sha
2731+
} {
2732+
eprintln!("CI rustc commit matches with HEAD and we are in CI.");
2733+
eprintln!(
2734+
"`rustc.download-ci` functionality will be skipped as artifacts are not available."
2735+
);
2736+
return None;
2737+
}
2738+
27092739
// Warn if there were changes to the compiler or standard library since the ancestor commit.
27102740
let has_changes = !t!(helpers::git(Some(&self.src))
27112741
.args(["diff-index", "--quiet", &commit])

src/bootstrap/src/core/config/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use super::{ChangeIdWrapper, Config};
1111
use crate::core::build_steps::clippy::get_clippy_rules_in_order;
1212
use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig};
1313

14-
fn parse(config: &str) -> Config {
14+
pub(crate) fn parse(config: &str) -> Config {
1515
Config::parse_inner(
1616
Flags::parse(&["check".to_string(), "--config=/does/not/exist".to_string()]),
1717
|&_| toml::from_str(&config),

src/bootstrap/src/core/download.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,3 +832,43 @@ fn path_is_dylib(path: &Path) -> bool {
832832
// The .so is not necessarily the extension, it might be libLLVM.so.18.1
833833
path.to_str().map_or(false, |path| path.contains(".so"))
834834
}
835+
836+
/// Checks whether the CI rustc is available for the given target triple.
837+
pub(crate) fn is_download_ci_available(target_triple: &str, llvm_assertions: bool) -> bool {
838+
// All tier 1 targets and tier 2 targets with host tools.
839+
const SUPPORTED_PLATFORMS: &[&str] = &[
840+
"aarch64-apple-darwin",
841+
"aarch64-pc-windows-msvc",
842+
"aarch64-unknown-linux-gnu",
843+
"aarch64-unknown-linux-musl",
844+
"arm-unknown-linux-gnueabi",
845+
"arm-unknown-linux-gnueabihf",
846+
"armv7-unknown-linux-gnueabihf",
847+
"i686-pc-windows-gnu",
848+
"i686-pc-windows-msvc",
849+
"i686-unknown-linux-gnu",
850+
"loongarch64-unknown-linux-gnu",
851+
"powerpc-unknown-linux-gnu",
852+
"powerpc64-unknown-linux-gnu",
853+
"powerpc64le-unknown-linux-gnu",
854+
"riscv64gc-unknown-linux-gnu",
855+
"s390x-unknown-linux-gnu",
856+
"x86_64-apple-darwin",
857+
"x86_64-pc-windows-gnu",
858+
"x86_64-pc-windows-msvc",
859+
"x86_64-unknown-freebsd",
860+
"x86_64-unknown-illumos",
861+
"x86_64-unknown-linux-gnu",
862+
"x86_64-unknown-linux-musl",
863+
"x86_64-unknown-netbsd",
864+
];
865+
866+
const SUPPORTED_PLATFORMS_WITH_ASSERTIONS: &[&str] =
867+
&["x86_64-unknown-linux-gnu", "x86_64-pc-windows-msvc"];
868+
869+
if llvm_assertions {
870+
SUPPORTED_PLATFORMS_WITH_ASSERTIONS.contains(&target_triple)
871+
} else {
872+
SUPPORTED_PLATFORMS.contains(&target_triple)
873+
}
874+
}

src/ci/docker/host-x86_64/mingw-check/Dockerfile

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,20 @@ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
4646
# Check library crates on all tier 1 targets.
4747
# We disable optimized compiler built-ins because that requires a C toolchain for the target.
4848
# We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs.
49-
ENV SCRIPT python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \
49+
ENV SCRIPT \
50+
# `core::builder::tests::ci_rustc_if_unchanged_logic` bootstrap test covers the `rust.download-rustc=if-unchanged` logic.
51+
# Here we are adding a dummy commit on compiler and running that test to ensure when there is a change on the compiler,
52+
# we never download ci rustc with `rust.download-rustc=if-unchanged` option.
53+
echo \"\" >> ../compiler/rustc/src/main.rs && \
54+
git config --global user.email \"dummy@dummy.com\" && \
55+
git config --global user.name \"dummy\" && \
56+
git add ../compiler/rustc/src/main.rs && \
57+
git commit -m \"test commit for rust.download-rustc=if-unchanged logic\" && \
58+
DISABLE_CI_RUSTC_IF_INCOMPATIBLE=0 python3 ../x.py test bootstrap -- core::builder::tests::ci_rustc_if_unchanged_logic && \
59+
# Revert the dummy commit
60+
git reset --hard HEAD~1 && \
61+
62+
python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \
5063
/scripts/check-default-config-profiles.sh && \
5164
python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
5265
python3 ../x.py clippy bootstrap -Dwarnings && \

src/ci/docker/host-x86_64/x86_64-fuchsia/Dockerfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ RUN mkdir -p $RUST_INSTALL_DIR/etc
5858
# Fuchsia only supports LLVM.
5959
ENV CODEGEN_BACKENDS llvm
6060

61+
# download-rustc is not allowed for `x install`
62+
ENV NO_DOWNLOAD_CI_RUSTC 1
63+
6164
ENV RUST_CONFIGURE_ARGS \
6265
--prefix=$RUST_INSTALL_DIR \
6366
--sysconfdir=etc \
@@ -70,6 +73,7 @@ ENV RUST_CONFIGURE_ARGS \
7073
--set target.x86_64-unknown-fuchsia.ar=/usr/local/bin/llvm-ar \
7174
--set target.x86_64-unknown-fuchsia.ranlib=/usr/local/bin/llvm-ranlib \
7275
--set target.x86_64-unknown-fuchsia.linker=/usr/local/bin/ld.lld
76+
7377
ENV SCRIPT \
7478
python3 ../x.py install --target $TARGETS compiler/rustc library/std clippy && \
7579
bash ../src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh

src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,4 @@ RUN echo "optimize = false" >> /config/nopt-std-config.toml
2929
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu \
3030
--disable-optimize-tests \
3131
--set rust.test-compare-mode
32-
ENV SCRIPT python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std \
33-
&& python3 ../x.py --stage 2 test
32+
ENV SCRIPT python3 ../x.py test --stage 2 tests/ui/allocator/no_std-alloc-error-handler-custom.rs -- --force-rerun

src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ ENV RUST_CONFIGURE_ARGS \
8484
--enable-new-symbol-mangling
8585

8686
ENV HOST_TARGET x86_64-unknown-linux-gnu
87+
ENV FORCE_CI_RUSTC 1
8788

8889
COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/
8990
COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/

src/ci/docker/run.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ docker \
343343
--env PR_CI_JOB \
344344
--env OBJDIR_ON_HOST="$objdir" \
345345
--env CODEGEN_BACKENDS \
346+
--env DISABLE_CI_RUSTC_IF_INCOMPATIBLE="$DISABLE_CI_RUSTC_IF_INCOMPATIBLE" \
346347
--init \
347348
--rm \
348349
rust-ci \

src/ci/github-actions/jobs.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ envs:
8585
# it in each job definition.
8686
pr:
8787
- image: mingw-check
88+
env:
89+
# We are adding (temporarily) a dummy commit on the compiler
90+
READ_ONLY_SRC: "0"
8891
<<: *job-linux-4c
8992
- image: mingw-check-tidy
9093
continue_on_error: true
@@ -207,6 +210,8 @@ auto:
207210
<<: *job-linux-8c
208211

209212
- image: mingw-check
213+
env:
214+
READ_ONLY_SRC: 0
210215
<<: *job-linux-4c
211216

212217
- image: test-various

src/ci/run.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ if [ "$CI" != "" ]; then
5252
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set change-id=99999999"
5353
fi
5454

55+
# If runner uses an incompatible option and `FORCE_CI_RUSTC` is not defined,
56+
# switch to in-tree rustc.
57+
if [ "$FORCE_CI_RUSTC" == "" ]; then
58+
echo "debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured."
59+
DISABLE_CI_RUSTC_IF_INCOMPATIBLE=1
60+
fi
61+
5562
if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf || \
5663
isCiBranch automation/bors/try; then
5764
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
@@ -169,10 +176,16 @@ else
169176
if [ "$NO_DOWNLOAD_CI_LLVM" = "" ]; then
170177
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.download-ci-llvm=if-unchanged"
171178
else
179+
# CI rustc requires CI LLVM to be enabled (see https://github.com/rust-lang/rust/issues/123586).
180+
NO_DOWNLOAD_CI_RUSTC=1
172181
# When building for CI we want to use the static C++ Standard library
173182
# included with LLVM, since a dynamic libstdcpp may not be available.
174183
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.static-libstdcpp"
175184
fi
185+
186+
if [ "$NO_DOWNLOAD_CI_RUSTC" = "" ]; then
187+
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.download-rustc=if-unchanged"
188+
fi
176189
fi
177190

178191
if [ "$ENABLE_GCC_CODEGEN" = "1" ]; then

0 commit comments

Comments
 (0)