Compare commits

..

No commits in common. "81790825173d87f89656f66f12a123bc99e2f6f1" and "df486c20f87e0d06e933f448a82b3dfecef4b1cf" have entirely different histories.

6 changed files with 129 additions and 85 deletions

View file

@ -2,7 +2,6 @@ use std::{
fmt::{Debug, Display},
num::NonZeroUsize,
path::Path,
process::Output,
time::{Duration, Instant, SystemTime},
};
@ -234,9 +233,14 @@ async fn build_single_target(db: &Db, nightly: &str, target: &str, mode: BuildMo
let start_time = Instant::now();
let result = build_target(tmpdir.path(), &Toolchain::from_nightly(nightly), target)
.await
.wrap_err("running build")?;
let result = build_target(
tmpdir.path(),
&Toolchain::from_nightly(nightly),
target,
mode,
)
.await
.wrap_err("running build")?;
db.insert(FullBuildInfo {
nightly: nightly.into(),
@ -268,19 +272,16 @@ struct BuildResult {
}
/// Build a target core in a temporary directory and see whether it passes or not.
async fn build_target(tmpdir: &Path, toolchain: &Toolchain, target: &str) -> Result<BuildResult> {
async fn build_target(
tmpdir: &Path,
toolchain: &Toolchain,
target: &str,
mode: BuildMode,
) -> Result<BuildResult> {
let mut rustflags = None;
let init = Command::new("cargo")
.arg(format!("+{toolchain}"))
.args([
"init",
"--lib",
"--name",
"target-test",
"--edition",
"2015",
])
.args(["init", "--lib", "--name", "target-test"])
.current_dir(tmpdir)
.output()
.await
@ -293,58 +294,41 @@ async fn build_target(tmpdir: &Path, toolchain: &Toolchain, target: &str) -> Res
std::fs::write(&librs, "#![no_std]\n")
.wrap_err_with(|| format!("writing to {}", librs.display()))?;
async fn run(
toolchain: &Toolchain,
target: &str,
rustflags: &mut Option<String>,
tmpdir: &Path,
build_std: &str,
) -> Result<Output> {
let mut cmd = Command::new("cargo");
cmd.arg(format!("+{toolchain}"))
.args(["build", "--release", "-j1"])
.arg(build_std)
.args(["--target", target]);
let mut cmd = Command::new("cargo");
let extra_flags = CUSTOM_CORE_FLAGS
.iter()
.find(|flags| flags.target == target);
match mode {
BuildMode::Core => {
cmd.arg(format!("+{toolchain}"))
.args(["build", "-Zbuild-std=core", "--release"])
.args(["--target", target]);
if let Some(extra_flags) = extra_flags {
let flags = extra_flags.flags.join(" ");
cmd.env("RUSTFLAGS", &flags);
*rustflags = Some(flags);
let extra_flags = CUSTOM_CORE_FLAGS
.iter()
.find(|flags| flags.target == target);
if let Some(extra_flags) = extra_flags {
let flags = extra_flags.flags.join(" ");
cmd.env("RUSTFLAGS", &flags);
rustflags = Some(flags);
}
}
BuildMode::Std => {
cmd.arg(format!("+{toolchain}"))
.args(["check", "-Zbuild-std"])
.args(["--target", target]);
}
};
cmd.current_dir(tmpdir)
.output()
.await
.wrap_err("spawning cargo build")
}
let output = cmd
.current_dir(tmpdir)
.output()
.await
.wrap_err("spawning cargo build")?;
let mut output = run(toolchain, target, &mut rustflags, tmpdir, "-Zbuild-std").await?;
let mut stderr = String::from_utf8(output.stderr).wrap_err("cargo stderr utf8")?;
let stderr = String::from_utf8(output.stderr).wrap_err("cargo stderr utf8")?;
let status = if output.status.success() {
Status::Pass
// older cargo (before 2024-12-15) is clueless about std support
} else if stderr.contains("building std is not supported") {
info!("Retrying build because std is not supported");
output = run(
toolchain,
target,
&mut rustflags,
tmpdir,
"-Zbuild-std=core",
)
.await?;
stderr = String::from_utf8(output.stderr).wrap_err("cargo stderr utf8")?;
if output.status.success() {
Status::Pass
} else {
Status::Error
}
} else {
Status::Error
};

View file

@ -17,13 +17,16 @@ pub static MIGRATOR: Migrator = sqlx::migrate!();
#[derive(Debug, Clone, Copy, sqlx::Type, Serialize, PartialEq, Eq, Hash)]
#[sqlx(rename_all = "kebab-case")]
pub enum BuildMode {
/// `build --release -Zbuild-std`
/// `build -Zbuild-std=core`
Core,
/// `check -Zbuild-std`
Std,
}
impl Display for BuildMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Core => f.write_str("core"),
Self::Std => f.write_str("std"),
}
}

View file

@ -44,7 +44,7 @@ impl Nightlies {
self.all
.iter()
.flat_map(|nightly| [(nightly, BuildMode::Std)])
.flat_map(|nightly| [(nightly, BuildMode::Core), (nightly, BuildMode::Std)])
.find(|(nightly, mode)| {
!already_finished.contains(&FinishedNightly {
nightly: (*nightly).to_owned(),

View file

@ -44,14 +44,14 @@ impl<'de> serde::Deserialize<'de> for LegacyBuildMode {
{
let s = String::deserialize(deserializer)?;
match s.as_str() {
"core" => Ok(LegacyBuildMode(BuildMode::Std)),
"core" => Ok(LegacyBuildMode(BuildMode::Core)),
"std" => Ok(LegacyBuildMode(BuildMode::Std)),
// This mode used to be called "miri-std" but it has been renamed to "std" using build-std.
// Allow the old value to keep links working but map it to std.
"miri-std" => Ok(LegacyBuildMode(BuildMode::Std)),
_ => Err(serde::de::Error::custom(
"invalid build mode, expected 'core', 'std', or 'miri-std'".to_owned(),
)),
_ => Err(serde::de::Error::custom(format!(
"invalid build mode, expected 'core', 'std', or 'miri-std'"
))),
}
}
}
@ -85,7 +85,7 @@ async fn web_build(State(state): State<AppState>, Query(query): Query<BuildQuery
.build_status_full(
&query.nightly,
&query.target,
query.mode.map(|mode| mode.0).unwrap_or(BuildMode::Std),
query.mode.map(|mode| mode.0).unwrap_or(BuildMode::Core),
)
.await
{
@ -144,14 +144,26 @@ async fn web_target(State(state): State<AppState>, Query(query): Query<TargetQue
match state.db.history_for_target(&query.target).await {
Ok(builds) => {
let latest_std = builds
let latest_core = builds
.iter()
.filter(|build| build.mode == BuildMode::Std)
.filter(|build| build.mode == BuildMode::Core)
.max_by_key(|elem| elem.nightly.clone());
let latest_miri = builds
.iter()
.filter(|build| build.mode == BuildMode::Core)
.max_by_key(|elem| elem.nightly.clone());
let status = match latest_std {
Some(one) => one.status.to_string(),
None => "missing".to_owned(),
let status = match (latest_core, latest_miri) {
(Some(core), Some(std)) => {
if core.status == Status::Error || std.status == Status::Error {
Status::Error
} else {
Status::Pass
}
.to_string()
}
(Some(one), None) | (None, Some(one)) => one.status.to_string(),
(None, None) => "missing".to_owned(),
};
let mut builds_grouped =
@ -159,6 +171,7 @@ async fn web_target(State(state): State<AppState>, Query(query): Query<TargetQue
for build in builds {
let v = builds_grouped.entry(build.nightly.clone()).or_default();
match build.mode {
BuildMode::Core => v.0 = Some(build),
BuildMode::Std => v.1 = Some(build),
}
}
@ -204,7 +217,9 @@ async fn web_nightly(State(state): State<AppState>, Query(query): Query<NightlyQ
nightly: String,
version: &'static str,
builds: Vec<(String, Option<BuildInfo>, Option<BuildInfo>)>,
core_failures: usize,
std_failures: usize,
core_broken: Option<String>,
std_broken: Option<String>,
showing_failures: bool,
}
@ -219,14 +234,17 @@ async fn web_nightly(State(state): State<AppState>, Query(query): Query<NightlyQ
for build in &builds {
let v = builds_grouped.entry(build.target.clone()).or_default();
match build.mode {
BuildMode::Core => v.0 = Some(build.clone()),
BuildMode::Std => v.1 = Some(build.clone()),
}
}
let mut std_failures = 0;
let mut core_failures = 0;
for build in builds {
if build.status == Status::Error {
match build.mode {
BuildMode::Core => core_failures += 1,
BuildMode::Std => std_failures += 1,
}
}
@ -242,6 +260,10 @@ async fn web_nightly(State(state): State<AppState>, Query(query): Query<NightlyQ
.collect::<Vec<_>>();
builds.sort_by_cached_key(|build| build.0.clone());
let core_broken = info
.iter()
.find(|info| info.mode == BuildMode::Core && info.is_broken)
.and_then(|info| info.broken_error.clone());
let std_broken = info
.iter()
.find(|info| info.mode == BuildMode::Std && info.is_broken)
@ -252,6 +274,8 @@ async fn web_nightly(State(state): State<AppState>, Query(query): Query<NightlyQ
version: crate::VERSION,
builds,
std_failures,
core_failures,
core_broken,
std_broken,
showing_failures: filter_failures,
};

View file

@ -10,13 +10,27 @@
<h1>Nightly build state for {{nightly}}</h1>
<a href="/">Home</a>
<p>
The build is performned with <code>cargo build --release -Zbuild-std</code> for a library crate.
This contains the status of this nightly. Core is built with
<code>cargo build --release -Zbuild-std=core</code>. This checks that
codegen/linking of core works, but does not check whether std builds.
</p>
<p>
std is being built with <code>cargo check -Zbuild-std</code>. If a target
does not support std, the std column represents core/alloc. This checks
that std checks (on targets that have it) but does not check whether
codegen/linking works.
This checks whether everything builds successfully (excluding binary linking, which often requires complex toolchains).
For no-std targets, Cargo's build-std logic is used for figuring out whether to build std or not.
On older targets (older than November 2024) this does not always work reliably, so some failed std builds there are simply no-std targets.
For older builds, <code>cargo miri setup</code> was used instead.
</p>
{% if let Some(core_broken) = core_broken %}
<p>
⚠️ The core build is broken in general for this nightly, so no data is available ⚠️
</p>
<pre>
{{core_broken}}
</pre>
{% endif %}
{% if let Some(std_broken) = std_broken %}
<p>
⚠️ The std build is broken for this nightly, so no data is available ⚠️
@ -29,6 +43,8 @@
<p>
<dl>
<dt>core failures</dt>
<dd>{{core_failures}}</dd>
<dt>std failures</dt>
<dd>{{std_failures}}</dd>
</dl>
@ -45,12 +61,21 @@
<table>
<tr>
<th>nightly</th>
<th>std<br>build</th>
<th>core<br>codegen</th>
<th>std<br>check</th>
</tr>
{% for build in builds %}
<tr>
<td><a href="/target?target={{build.0}}">{{ build.0 }}</a></td>
{% match build.2 %} {% when Some with (build) %}
{% match build.1 %} {% when Some with (build) %}
<td class="build-cell">
<a class="build-info-a" href="{{ build.link() }}">
{{ build.status.to_emoji() }}
</a>
</td>
{% when None %}
<td class="missing"></td>
{% endmatch %} {% match build.2 %} {% when Some with (build) %}
<td class="build-cell">
<a class="build-info-a" href="{{ build.link() }}">
<span> {{ build.status.to_emoji() }} </span>

View file

@ -23,13 +23,12 @@
codegen/linking of core works, but does not check whether std builds.
</p>
<p>
The build is performned with
<code>cargo build --release -Zbuild-std</code> for a library crate. This
checks whether everything builds successfully (excluding binary linking,
which often requires complex toolchains). For no-std targets, Cargo's
build-std logic is used for figuring out whether to build std or not. On
older targets (older than November 2024) this does not always work
reliably, so some failed std builds there are simply no-std targets.
std is being built with <code>cargo check -Zbuild-std</code>. If a target
does not support std, the std column represents core/alloc. This checks
that std checks (on targets that have it) but does not check whether
codegen/linking works.
For older builds, <code>cargo miri setup</code> was used instead.
</p>
{% if showing_failures %}
<p>
@ -43,12 +42,21 @@
<table>
<tr>
<th>nightly</th>
<th>std<br />build</th>
<th>core<br />codegen</th>
<th>std<br />check</th>
</tr>
{% for build in builds %}
<tr>
<td><a href="/nightly?nightly={{build.0}}">{{ build.0 }}</a></td>
{% match build.2 %} {% when Some with (build) %}
{% match build.1 %} {% when Some with (build) %}
<td class="build-cell">
<a class="build-info-a" href="{{ build.link() }}">
{{ build.status.to_emoji() }}
</a>
</td>
{% when None %}
<td class="missing"></td>
{% endmatch %} {% match build.2 %} {% when Some with (build) %}
<td class="build-cell">
<a class="build-info-a" href="{{ build.link() }}">
<span> {{ build.status.to_emoji() }} </span>