Skip to content

Commit 1b8dee1

Browse files
committed
Fix issue #110087
Three tasks have been implemented here. Add a new `download-ci-llvm = if-unchange` option and enable if by default for `profile = codegen`. Include all build artifacts by traversing the llvm-project build output, Keep the downloadable llvm the same state as if you have just run a full source build. After selecting the codegen profile during ./x.py setup, the submodule will be automatically downloaded.
1 parent 4e0fb98 commit 1b8dee1

File tree

7 files changed

+120
-32
lines changed

7 files changed

+120
-32
lines changed

config.example.toml

+7-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#
3131
# If `change-id` does not match the version that is currently running,
3232
# `x.py` will prompt you to update it and check the related PR for more details.
33-
change-id = 117435
33+
change-id = 116881
3434

3535
# =============================================================================
3636
# Tweaking how LLVM is compiled
@@ -42,11 +42,15 @@ change-id = 117435
4242
# Unless you're developing for a target where Rust CI doesn't build a compiler
4343
# toolchain or changing LLVM locally, you probably want to leave this enabled.
4444
#
45-
# All tier 1 targets are currently supported; set this to `"if-available"` if
46-
# you are not sure whether you're on a tier 1 target.
45+
# Set this to `"if-available"` if you are not sure whether you're on a tier 1
46+
# target. All tier 1 targets are currently supported;
4747
#
4848
# We also currently only support this when building LLVM for the build triple.
4949
#
50+
# Set this to `"if-unchanged"` to only download if the llvm-project have not
51+
# been modified. (If there are no changes or if built from tarball source,
52+
# the logic is the same as "if-available")
53+
#
5054
# Note that many of the LLVM options are not currently supported for
5155
# downloading. Currently only the "assertions" option can be toggled.
5256
#download-ci-llvm = if rust.channel == "dev" { "if-available" } else { false }

src/bootstrap/defaults/config.codegen.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ assertions = true
1010
# enable warnings during the llvm compilation
1111
enable-warnings = true
1212
# build llvm from source
13-
download-ci-llvm = false
13+
download-ci-llvm = "if-unchanged"
1414

1515
[rust]
1616
# This enables `RUSTC_LOG=debug`, avoiding confusing situations

src/bootstrap/download-ci-llvm-stamp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
Change this file to make users of the `download-ci-llvm` configuration download
22
a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
33

4-
Last change is for: https://github.com/rust-lang/rust/pull/113996
4+
Last change is for: https://github.com/rust-lang/rust/pull/116881

src/bootstrap/src/core/build_steps/dist.rs

+11-15
Original file line numberDiff line numberDiff line change
@@ -2219,23 +2219,19 @@ impl Step for RustDev {
22192219
builder.ensure(crate::core::build_steps::llvm::Lld { target });
22202220

22212221
let src_bindir = builder.llvm_out(target).join("bin");
2222-
// If updating this list, you likely want to change
2222+
// If updating this, you likely want to change
22232223
// src/bootstrap/download-ci-llvm-stamp as well, otherwise local users
22242224
// will not pick up the extra file until LLVM gets bumped.
2225-
for bin in &[
2226-
"llvm-config",
2227-
"llvm-ar",
2228-
"llvm-objdump",
2229-
"llvm-profdata",
2230-
"llvm-bcanalyzer",
2231-
"llvm-cov",
2232-
"llvm-dwp",
2233-
"llvm-nm",
2234-
"llvm-dwarfdump",
2235-
"llvm-dis",
2236-
"llvm-tblgen",
2237-
] {
2238-
tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755);
2225+
// We should include all the build artifacts obtained from a source build,
2226+
// so that you can use the downloadable LLVM as if you’ve just run a full source build.
2227+
if src_bindir.exists() {
2228+
for entry in walkdir::WalkDir::new(&src_bindir) {
2229+
let entry = t!(entry);
2230+
if entry.file_type().is_file() && !entry.path_is_symlink() {
2231+
let name = entry.file_name().to_str().unwrap();
2232+
tarball.add_file(src_bindir.join(name), "bin", 0o755);
2233+
}
2234+
}
22392235
}
22402236

22412237
// We don't build LLD on some platforms, so only add it if it exists

src/bootstrap/src/core/build_steps/setup.rs

+9
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,15 @@ impl Step for Profile {
147147
}
148148

149149
fn run(self, builder: &Builder<'_>) {
150+
// During ./x.py setup once you select the codegen profile.
151+
// The submodule will be downloaded. It does not work in the
152+
// tarball case since they don't include Git and submodules
153+
// are already included.
154+
if !builder.rust_info().is_from_tarball() {
155+
if self == Profile::Codegen {
156+
builder.update_submodule(&Path::new("src/llvm-project"));
157+
}
158+
}
150159
setup(&builder.build.config, self)
151160
}
152161
}

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

+90-11
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use std::process::Command;
1919
use std::str::FromStr;
2020

2121
use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX;
22+
use crate::core::build_steps::llvm;
2223
use crate::core::config::flags::{Color, Flags, Warnings};
2324
use crate::utils::cache::{Interned, INTERNER};
2425
use crate::utils::channel::{self, GitInfo};
@@ -1530,17 +1531,7 @@ impl Config {
15301531
config.llvm_build_config = llvm.build_config.clone().unwrap_or(Default::default());
15311532

15321533
let asserts = llvm_assertions.unwrap_or(false);
1533-
config.llvm_from_ci = match llvm.download_ci_llvm {
1534-
Some(StringOrBool::String(s)) => {
1535-
assert_eq!(s, "if-available", "unknown option `{s}` for download-ci-llvm");
1536-
crate::core::build_steps::llvm::is_ci_llvm_available(&config, asserts)
1537-
}
1538-
Some(StringOrBool::Bool(b)) => b,
1539-
None => {
1540-
config.channel == "dev"
1541-
&& crate::core::build_steps::llvm::is_ci_llvm_available(&config, asserts)
1542-
}
1543-
};
1534+
config.llvm_from_ci = config.parse_download_ci_llvm(llvm.download_ci_llvm, asserts);
15441535

15451536
if config.llvm_from_ci {
15461537
// None of the LLVM options, except assertions, are supported
@@ -2104,6 +2095,94 @@ impl Config {
21042095

21052096
Some(commit.to_string())
21062097
}
2098+
2099+
fn parse_download_ci_llvm(
2100+
&self,
2101+
download_ci_llvm: Option<StringOrBool>,
2102+
asserts: bool,
2103+
) -> bool {
2104+
match download_ci_llvm {
2105+
None => self.channel == "dev" && llvm::is_ci_llvm_available(&self, asserts),
2106+
Some(StringOrBool::Bool(b)) => b,
2107+
Some(StringOrBool::String(s)) if s == "if-available" => {
2108+
llvm::is_ci_llvm_available(&self, asserts)
2109+
}
2110+
Some(StringOrBool::String(s)) if s == "if-unchanged" => {
2111+
// Git is needed to track modifications here, but tarball source is not available.
2112+
// If not modified here or built through tarball source, we maintain consistency
2113+
// with '"if available"'.
2114+
if !self.rust_info.is_from_tarball()
2115+
&& self
2116+
.last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true)
2117+
.is_none()
2118+
{
2119+
// there are some untracked changes in the the given paths.
2120+
false
2121+
} else {
2122+
llvm::is_ci_llvm_available(&self, asserts)
2123+
}
2124+
}
2125+
Some(StringOrBool::String(other)) => {
2126+
panic!("unrecognized option for download-ci-llvm: {:?}", other)
2127+
}
2128+
}
2129+
}
2130+
2131+
/// Returns the last commit in which any of `modified_paths` were changed,
2132+
/// or `None` if there are untracked changes in the working directory and `if_unchanged` is true.
2133+
pub fn last_modified_commit(
2134+
&self,
2135+
modified_paths: &[&str],
2136+
option_name: &str,
2137+
if_unchanged: bool,
2138+
) -> Option<String> {
2139+
// Handle running from a directory other than the top level
2140+
let top_level = output(self.git().args(&["rev-parse", "--show-toplevel"]));
2141+
let top_level = top_level.trim_end();
2142+
2143+
// Look for a version to compare to based on the current commit.
2144+
// Only commits merged by bors will have CI artifacts.
2145+
let merge_base = output(
2146+
self.git()
2147+
.arg("rev-list")
2148+
.arg(format!("--author={}", self.stage0_metadata.config.git_merge_commit_email))
2149+
.args(&["-n1", "--first-parent", "HEAD"]),
2150+
);
2151+
let commit = merge_base.trim_end();
2152+
if commit.is_empty() {
2153+
println!("error: could not find commit hash for downloading components from CI");
2154+
println!("help: maybe your repository history is too shallow?");
2155+
println!("help: consider disabling `{option_name}`");
2156+
println!("help: or fetch enough history to include one upstream commit");
2157+
crate::exit!(1);
2158+
}
2159+
2160+
// Warn if there were changes to the compiler or standard library since the ancestor commit.
2161+
let mut git = self.git();
2162+
git.args(&["diff-index", "--quiet", &commit, "--"]);
2163+
2164+
for path in modified_paths {
2165+
git.arg(format!("{top_level}/{path}"));
2166+
}
2167+
2168+
let has_changes = !t!(git.status()).success();
2169+
if has_changes {
2170+
if if_unchanged {
2171+
if self.verbose > 0 {
2172+
println!(
2173+
"warning: saw changes to one of {modified_paths:?} since {commit}; \
2174+
ignoring `{option_name}`"
2175+
);
2176+
}
2177+
return None;
2178+
}
2179+
println!(
2180+
"warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}"
2181+
);
2182+
}
2183+
2184+
Some(commit.to_string())
2185+
}
21072186
}
21082187

21092188
fn set<T>(field: &mut T, val: Option<T>) {

src/bootstrap/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"];
7777
///
7878
/// If you make any major changes (such as adding new values or changing default values), please
7979
/// ensure that the associated PR ID is added to the end of this list.
80-
pub const CONFIG_CHANGE_HISTORY: &[usize] = &[115898, 116998, 117435];
80+
pub const CONFIG_CHANGE_HISTORY: &[usize] = &[115898, 116998, 117435, 116881];
8181

8282
/// Extra --check-cfg to add when building
8383
/// (Mode restriction, config name, config values (if any))

0 commit comments

Comments
 (0)