mirror of
https://github.com/Noratrieb/does-it-build.git
synced 2026-03-16 05:56:07 +01:00
Compare commits
5 commits
df486c20f8
...
8179082517
| Author | SHA1 | Date | |
|---|---|---|---|
| 8179082517 | |||
| c90b94ee69 | |||
| 9f18ad0d06 | |||
| 8e9ff1e9fd | |||
| 4969eaeb36 |
6 changed files with 85 additions and 129 deletions
100
src/build.rs
100
src/build.rs
|
|
@ -2,6 +2,7 @@ use std::{
|
||||||
fmt::{Debug, Display},
|
fmt::{Debug, Display},
|
||||||
num::NonZeroUsize,
|
num::NonZeroUsize,
|
||||||
path::Path,
|
path::Path,
|
||||||
|
process::Output,
|
||||||
time::{Duration, Instant, SystemTime},
|
time::{Duration, Instant, SystemTime},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -233,14 +234,9 @@ async fn build_single_target(db: &Db, nightly: &str, target: &str, mode: BuildMo
|
||||||
|
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
|
|
||||||
let result = build_target(
|
let result = build_target(tmpdir.path(), &Toolchain::from_nightly(nightly), target)
|
||||||
tmpdir.path(),
|
.await
|
||||||
&Toolchain::from_nightly(nightly),
|
.wrap_err("running build")?;
|
||||||
target,
|
|
||||||
mode,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.wrap_err("running build")?;
|
|
||||||
|
|
||||||
db.insert(FullBuildInfo {
|
db.insert(FullBuildInfo {
|
||||||
nightly: nightly.into(),
|
nightly: nightly.into(),
|
||||||
|
|
@ -272,16 +268,19 @@ struct BuildResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build a target core in a temporary directory and see whether it passes or not.
|
/// Build a target core in a temporary directory and see whether it passes or not.
|
||||||
async fn build_target(
|
async fn build_target(tmpdir: &Path, toolchain: &Toolchain, target: &str) -> Result<BuildResult> {
|
||||||
tmpdir: &Path,
|
|
||||||
toolchain: &Toolchain,
|
|
||||||
target: &str,
|
|
||||||
mode: BuildMode,
|
|
||||||
) -> Result<BuildResult> {
|
|
||||||
let mut rustflags = None;
|
let mut rustflags = None;
|
||||||
|
|
||||||
let init = Command::new("cargo")
|
let init = Command::new("cargo")
|
||||||
.args(["init", "--lib", "--name", "target-test"])
|
.arg(format!("+{toolchain}"))
|
||||||
|
.args([
|
||||||
|
"init",
|
||||||
|
"--lib",
|
||||||
|
"--name",
|
||||||
|
"target-test",
|
||||||
|
"--edition",
|
||||||
|
"2015",
|
||||||
|
])
|
||||||
.current_dir(tmpdir)
|
.current_dir(tmpdir)
|
||||||
.output()
|
.output()
|
||||||
.await
|
.await
|
||||||
|
|
@ -294,41 +293,58 @@ async fn build_target(
|
||||||
std::fs::write(&librs, "#![no_std]\n")
|
std::fs::write(&librs, "#![no_std]\n")
|
||||||
.wrap_err_with(|| format!("writing to {}", librs.display()))?;
|
.wrap_err_with(|| format!("writing to {}", librs.display()))?;
|
||||||
|
|
||||||
let mut cmd = Command::new("cargo");
|
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]);
|
||||||
|
|
||||||
match mode {
|
let extra_flags = CUSTOM_CORE_FLAGS
|
||||||
BuildMode::Core => {
|
.iter()
|
||||||
cmd.arg(format!("+{toolchain}"))
|
.find(|flags| flags.target == target);
|
||||||
.args(["build", "-Zbuild-std=core", "--release"])
|
|
||||||
.args(["--target", target]);
|
|
||||||
|
|
||||||
let extra_flags = CUSTOM_CORE_FLAGS
|
if let Some(extra_flags) = extra_flags {
|
||||||
.iter()
|
let flags = extra_flags.flags.join(" ");
|
||||||
.find(|flags| flags.target == target);
|
cmd.env("RUSTFLAGS", &flags);
|
||||||
|
*rustflags = Some(flags);
|
||||||
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]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let output = cmd
|
cmd.current_dir(tmpdir)
|
||||||
.current_dir(tmpdir)
|
.output()
|
||||||
.output()
|
.await
|
||||||
.await
|
.wrap_err("spawning cargo build")
|
||||||
.wrap_err("spawning cargo build")?;
|
}
|
||||||
|
|
||||||
let stderr = String::from_utf8(output.stderr).wrap_err("cargo stderr utf8")?;
|
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 status = if output.status.success() {
|
let status = if output.status.success() {
|
||||||
Status::Pass
|
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 {
|
} else {
|
||||||
Status::Error
|
Status::Error
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,13 @@ pub static MIGRATOR: Migrator = sqlx::migrate!();
|
||||||
#[derive(Debug, Clone, Copy, sqlx::Type, Serialize, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, sqlx::Type, Serialize, PartialEq, Eq, Hash)]
|
||||||
#[sqlx(rename_all = "kebab-case")]
|
#[sqlx(rename_all = "kebab-case")]
|
||||||
pub enum BuildMode {
|
pub enum BuildMode {
|
||||||
/// `build -Zbuild-std=core`
|
/// `build --release -Zbuild-std`
|
||||||
Core,
|
|
||||||
/// `check -Zbuild-std`
|
|
||||||
Std,
|
Std,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for BuildMode {
|
impl Display for BuildMode {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Core => f.write_str("core"),
|
|
||||||
Self::Std => f.write_str("std"),
|
Self::Std => f.write_str("std"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ impl Nightlies {
|
||||||
|
|
||||||
self.all
|
self.all
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|nightly| [(nightly, BuildMode::Core), (nightly, BuildMode::Std)])
|
.flat_map(|nightly| [(nightly, BuildMode::Std)])
|
||||||
.find(|(nightly, mode)| {
|
.find(|(nightly, mode)| {
|
||||||
!already_finished.contains(&FinishedNightly {
|
!already_finished.contains(&FinishedNightly {
|
||||||
nightly: (*nightly).to_owned(),
|
nightly: (*nightly).to_owned(),
|
||||||
|
|
|
||||||
44
src/web.rs
44
src/web.rs
|
|
@ -44,14 +44,14 @@ impl<'de> serde::Deserialize<'de> for LegacyBuildMode {
|
||||||
{
|
{
|
||||||
let s = String::deserialize(deserializer)?;
|
let s = String::deserialize(deserializer)?;
|
||||||
match s.as_str() {
|
match s.as_str() {
|
||||||
"core" => Ok(LegacyBuildMode(BuildMode::Core)),
|
"core" => Ok(LegacyBuildMode(BuildMode::Std)),
|
||||||
"std" => Ok(LegacyBuildMode(BuildMode::Std)),
|
"std" => Ok(LegacyBuildMode(BuildMode::Std)),
|
||||||
// This mode used to be called "miri-std" but it has been renamed to "std" using build-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.
|
// Allow the old value to keep links working but map it to std.
|
||||||
"miri-std" => Ok(LegacyBuildMode(BuildMode::Std)),
|
"miri-std" => Ok(LegacyBuildMode(BuildMode::Std)),
|
||||||
_ => Err(serde::de::Error::custom(format!(
|
_ => Err(serde::de::Error::custom(
|
||||||
"invalid build mode, expected 'core', 'std', or 'miri-std'"
|
"invalid build mode, expected 'core', 'std', or 'miri-std'".to_owned(),
|
||||||
))),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +85,7 @@ async fn web_build(State(state): State<AppState>, Query(query): Query<BuildQuery
|
||||||
.build_status_full(
|
.build_status_full(
|
||||||
&query.nightly,
|
&query.nightly,
|
||||||
&query.target,
|
&query.target,
|
||||||
query.mode.map(|mode| mode.0).unwrap_or(BuildMode::Core),
|
query.mode.map(|mode| mode.0).unwrap_or(BuildMode::Std),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
|
@ -144,26 +144,14 @@ async fn web_target(State(state): State<AppState>, Query(query): Query<TargetQue
|
||||||
|
|
||||||
match state.db.history_for_target(&query.target).await {
|
match state.db.history_for_target(&query.target).await {
|
||||||
Ok(builds) => {
|
Ok(builds) => {
|
||||||
let latest_core = builds
|
let latest_std = builds
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|build| build.mode == BuildMode::Core)
|
.filter(|build| build.mode == BuildMode::Std)
|
||||||
.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());
|
.max_by_key(|elem| elem.nightly.clone());
|
||||||
|
|
||||||
let status = match (latest_core, latest_miri) {
|
let status = match latest_std {
|
||||||
(Some(core), Some(std)) => {
|
Some(one) => one.status.to_string(),
|
||||||
if core.status == Status::Error || std.status == Status::Error {
|
None => "missing".to_owned(),
|
||||||
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 =
|
let mut builds_grouped =
|
||||||
|
|
@ -171,7 +159,6 @@ async fn web_target(State(state): State<AppState>, Query(query): Query<TargetQue
|
||||||
for build in builds {
|
for build in builds {
|
||||||
let v = builds_grouped.entry(build.nightly.clone()).or_default();
|
let v = builds_grouped.entry(build.nightly.clone()).or_default();
|
||||||
match build.mode {
|
match build.mode {
|
||||||
BuildMode::Core => v.0 = Some(build),
|
|
||||||
BuildMode::Std => v.1 = Some(build),
|
BuildMode::Std => v.1 = Some(build),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -217,9 +204,7 @@ async fn web_nightly(State(state): State<AppState>, Query(query): Query<NightlyQ
|
||||||
nightly: String,
|
nightly: String,
|
||||||
version: &'static str,
|
version: &'static str,
|
||||||
builds: Vec<(String, Option<BuildInfo>, Option<BuildInfo>)>,
|
builds: Vec<(String, Option<BuildInfo>, Option<BuildInfo>)>,
|
||||||
core_failures: usize,
|
|
||||||
std_failures: usize,
|
std_failures: usize,
|
||||||
core_broken: Option<String>,
|
|
||||||
std_broken: Option<String>,
|
std_broken: Option<String>,
|
||||||
showing_failures: bool,
|
showing_failures: bool,
|
||||||
}
|
}
|
||||||
|
|
@ -234,17 +219,14 @@ async fn web_nightly(State(state): State<AppState>, Query(query): Query<NightlyQ
|
||||||
for build in &builds {
|
for build in &builds {
|
||||||
let v = builds_grouped.entry(build.target.clone()).or_default();
|
let v = builds_grouped.entry(build.target.clone()).or_default();
|
||||||
match build.mode {
|
match build.mode {
|
||||||
BuildMode::Core => v.0 = Some(build.clone()),
|
|
||||||
BuildMode::Std => v.1 = Some(build.clone()),
|
BuildMode::Std => v.1 = Some(build.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut std_failures = 0;
|
let mut std_failures = 0;
|
||||||
let mut core_failures = 0;
|
|
||||||
for build in builds {
|
for build in builds {
|
||||||
if build.status == Status::Error {
|
if build.status == Status::Error {
|
||||||
match build.mode {
|
match build.mode {
|
||||||
BuildMode::Core => core_failures += 1,
|
|
||||||
BuildMode::Std => std_failures += 1,
|
BuildMode::Std => std_failures += 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -260,10 +242,6 @@ async fn web_nightly(State(state): State<AppState>, Query(query): Query<NightlyQ
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
builds.sort_by_cached_key(|build| build.0.clone());
|
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
|
let std_broken = info
|
||||||
.iter()
|
.iter()
|
||||||
.find(|info| info.mode == BuildMode::Std && info.is_broken)
|
.find(|info| info.mode == BuildMode::Std && info.is_broken)
|
||||||
|
|
@ -274,8 +252,6 @@ async fn web_nightly(State(state): State<AppState>, Query(query): Query<NightlyQ
|
||||||
version: crate::VERSION,
|
version: crate::VERSION,
|
||||||
builds,
|
builds,
|
||||||
std_failures,
|
std_failures,
|
||||||
core_failures,
|
|
||||||
core_broken,
|
|
||||||
std_broken,
|
std_broken,
|
||||||
showing_failures: filter_failures,
|
showing_failures: filter_failures,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,27 +10,13 @@
|
||||||
<h1>Nightly build state for {{nightly}}</h1>
|
<h1>Nightly build state for {{nightly}}</h1>
|
||||||
<a href="/">Home</a>
|
<a href="/">Home</a>
|
||||||
<p>
|
<p>
|
||||||
This contains the status of this nightly. Core is built with
|
The build is performned with <code>cargo build --release -Zbuild-std</code> for a library crate.
|
||||||
<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.
|
|
||||||
|
|
||||||
For older builds, <code>cargo miri setup</code> was used instead.
|
This checks whether everything builds successfully (excluding binary linking, which often requires complex toolchains).
|
||||||
</p>
|
For no-std targets, Cargo's build-std logic is used for figuring out whether to build std or not.
|
||||||
{% if let Some(core_broken) = core_broken %}
|
On older targets (older than November 2024) this does not always work reliably, so some failed std builds there are simply no-std targets.
|
||||||
<p>
|
|
||||||
⚠️ The core build is broken in general for this nightly, so no data is available ⚠️
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
|
||||||
{{core_broken}}
|
|
||||||
</pre>
|
|
||||||
{% endif %}
|
|
||||||
{% if let Some(std_broken) = std_broken %}
|
{% if let Some(std_broken) = std_broken %}
|
||||||
<p>
|
<p>
|
||||||
⚠️ The std build is broken for this nightly, so no data is available ⚠️
|
⚠️ The std build is broken for this nightly, so no data is available ⚠️
|
||||||
|
|
@ -43,8 +29,6 @@
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>core failures</dt>
|
|
||||||
<dd>{{core_failures}}</dd>
|
|
||||||
<dt>std failures</dt>
|
<dt>std failures</dt>
|
||||||
<dd>{{std_failures}}</dd>
|
<dd>{{std_failures}}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
@ -61,21 +45,12 @@
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>nightly</th>
|
<th>nightly</th>
|
||||||
<th>core<br>codegen</th>
|
<th>std<br>build</th>
|
||||||
<th>std<br>check</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% for build in builds %}
|
{% for build in builds %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="/target?target={{build.0}}">{{ build.0 }}</a></td>
|
<td><a href="/target?target={{build.0}}">{{ build.0 }}</a></td>
|
||||||
{% match build.1 %} {% when Some with (build) %}
|
{% match build.2 %} {% 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">
|
<td class="build-cell">
|
||||||
<a class="build-info-a" href="{{ build.link() }}">
|
<a class="build-info-a" href="{{ build.link() }}">
|
||||||
<span> {{ build.status.to_emoji() }} </span>
|
<span> {{ build.status.to_emoji() }} </span>
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,13 @@
|
||||||
codegen/linking of core works, but does not check whether std builds.
|
codegen/linking of core works, but does not check whether std builds.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
std is being built with <code>cargo check -Zbuild-std</code>. If a target
|
The build is performned with
|
||||||
does not support std, the std column represents core/alloc. This checks
|
<code>cargo build --release -Zbuild-std</code> for a library crate. This
|
||||||
that std checks (on targets that have it) but does not check whether
|
checks whether everything builds successfully (excluding binary linking,
|
||||||
codegen/linking works.
|
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
|
||||||
For older builds, <code>cargo miri setup</code> was used instead.
|
older targets (older than November 2024) this does not always work
|
||||||
|
reliably, so some failed std builds there are simply no-std targets.
|
||||||
</p>
|
</p>
|
||||||
{% if showing_failures %}
|
{% if showing_failures %}
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -42,21 +43,12 @@
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>nightly</th>
|
<th>nightly</th>
|
||||||
<th>core<br />codegen</th>
|
<th>std<br />build</th>
|
||||||
<th>std<br />check</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% for build in builds %}
|
{% for build in builds %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="/nightly?nightly={{build.0}}">{{ build.0 }}</a></td>
|
<td><a href="/nightly?nightly={{build.0}}">{{ build.0 }}</a></td>
|
||||||
{% match build.1 %} {% when Some with (build) %}
|
{% match build.2 %} {% 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">
|
<td class="build-cell">
|
||||||
<a class="build-info-a" href="{{ build.link() }}">
|
<a class="build-info-a" href="{{ build.link() }}">
|
||||||
<span> {{ build.status.to_emoji() }} </span>
|
<span> {{ build.status.to_emoji() }} </span>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue