Use cargo check -Zbuild-std instead of cargo miri setup

This should be more reliable (not building with `cfg(miri)` and more
accurately knowing whether a target supports std).

Known targets affected by this change:
- cygwin: should now build since it only breaks in `cfg(miri)`
- i686-pc-nto-qnx700: officially doesn't support std

closes #4
This commit is contained in:
nora 2025-07-05 14:21:26 +02:00
parent 0be7b4c981
commit df486c20f8
7 changed files with 85 additions and 68 deletions

View file

@ -0,0 +1,3 @@
UPDATE finished_nightly SET mode = 'std' WHERE mode = 'miri-std';
UPDATE build_info SET mode = 'std' WHERE mode = 'miri-std';

View file

@ -61,7 +61,11 @@ pub async fn background_builder(db: Db) -> Result<()> {
loop { loop {
if let Err(err) = background_builder_inner(&db).await { if let Err(err) = background_builder_inner(&db).await {
error!("error in background builder: {err}"); error!(
?err,
"error in background builder, waiting for an hour before retrying: {err}"
);
tokio::time::sleep(Duration::from_secs(3600)).await;
} }
} }
} }
@ -145,20 +149,7 @@ async fn install_toolchain(toolchain: &Toolchain, mode: BuildMode) -> Result<()>
if !result.status.success() { if !result.status.success() {
bail!("rustup failed: {:?}", String::from_utf8(result.stderr)); bail!("rustup failed: {:?}", String::from_utf8(result.stderr));
} }
if mode == BuildMode::MiriStd {
let result = Command::new("rustup")
.arg("component")
.arg("add")
.arg("miri")
.arg("--toolchain")
.arg(&toolchain.0)
.output()
.await
.wrap_err("failed to spawn rustup")?;
if !result.status.success() {
bail!("rustup failed: {:?}", String::from_utf8(result.stderr));
}
}
Ok(()) Ok(())
} }
@ -289,8 +280,6 @@ async fn build_target(
) -> Result<BuildResult> { ) -> Result<BuildResult> {
let mut rustflags = None; let mut rustflags = None;
let output = match mode {
BuildMode::Core => {
let init = Command::new("cargo") let init = Command::new("cargo")
.args(["init", "--lib", "--name", "target-test"]) .args(["init", "--lib", "--name", "target-test"])
.current_dir(tmpdir) .current_dir(tmpdir)
@ -306,6 +295,9 @@ async fn build_target(
.wrap_err_with(|| format!("writing to {}", librs.display()))?; .wrap_err_with(|| format!("writing to {}", librs.display()))?;
let mut cmd = Command::new("cargo"); let mut cmd = Command::new("cargo");
match mode {
BuildMode::Core => {
cmd.arg(format!("+{toolchain}")) cmd.arg(format!("+{toolchain}"))
.args(["build", "-Zbuild-std=core", "--release"]) .args(["build", "-Zbuild-std=core", "--release"])
.args(["--target", target]); .args(["--target", target]);
@ -319,22 +311,19 @@ async fn build_target(
cmd.env("RUSTFLAGS", &flags); cmd.env("RUSTFLAGS", &flags);
rustflags = Some(flags); rustflags = Some(flags);
} }
cmd.current_dir(tmpdir)
.output()
.await
.wrap_err("spawning cargo build")?
} }
BuildMode::MiriStd => Command::new("cargo") BuildMode::Std => {
.arg(format!("+{toolchain}")) cmd.arg(format!("+{toolchain}"))
.args(["miri", "setup"]) .args(["check", "-Zbuild-std"])
.args(["--target", target]) .args(["--target", target]);
}
};
let output = cmd
.current_dir(tmpdir) .current_dir(tmpdir)
.env("MIRI_SYSROOT", 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 stderr = String::from_utf8(output.stderr).wrap_err("cargo stderr utf8")?;

View file

@ -14,26 +14,25 @@ pub struct Db {
pub static MIGRATOR: Migrator = sqlx::migrate!(); pub static MIGRATOR: Migrator = sqlx::migrate!();
#[derive(Debug, Clone, Copy, sqlx::Type, Serialize, Deserialize, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, sqlx::Type, Serialize, PartialEq, Eq, Hash)]
#[sqlx(rename_all = "kebab-case")] #[sqlx(rename_all = "kebab-case")]
#[serde(rename_all = "kebab-case")]
pub enum BuildMode { pub enum BuildMode {
/// `-Zbuild-std=core` /// `build -Zbuild-std=core`
Core, Core,
/// `cargo miri setup` /// `check -Zbuild-std`
MiriStd, 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::Core => f.write_str("core"),
Self::MiriStd => f.write_str("miri-std"), Self::Std => f.write_str("std"),
} }
} }
} }
#[derive(sqlx::FromRow, Serialize, Deserialize, Clone)] #[derive(sqlx::FromRow, Serialize, Clone)]
pub struct BuildInfo { pub struct BuildInfo {
pub nightly: String, pub nightly: String,
pub target: String, pub target: String,
@ -41,7 +40,7 @@ pub struct BuildInfo {
pub mode: BuildMode, pub mode: BuildMode,
} }
#[derive(Clone, sqlx::FromRow, Serialize, Deserialize)] #[derive(Clone, sqlx::FromRow, Serialize)]
pub struct FullBuildInfo { pub struct FullBuildInfo {
pub nightly: String, pub nightly: String,
pub target: String, pub target: String,

View file

@ -44,7 +44,7 @@ impl Nightlies {
self.all self.all
.iter() .iter()
.flat_map(|nightly| [(nightly, BuildMode::Core), (nightly, BuildMode::MiriStd)]) .flat_map(|nightly| [(nightly, BuildMode::Core), (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(),

View file

@ -34,11 +34,33 @@ pub async fn webserver(db: Db) -> Result<()> {
axum::serve(listener, app).await.wrap_err("failed to serve") axum::serve(listener, app).await.wrap_err("failed to serve")
} }
#[derive(Debug, Clone, Copy)]
pub struct LegacyBuildMode(BuildMode);
impl<'de> serde::Deserialize<'de> for LegacyBuildMode {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
match s.as_str() {
"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(format!(
"invalid build mode, expected 'core', 'std', or 'miri-std'"
))),
}
}
}
#[derive(Deserialize)] #[derive(Deserialize)]
struct BuildQuery { struct BuildQuery {
nightly: String, nightly: String,
target: String, target: String,
mode: Option<BuildMode>, mode: Option<LegacyBuildMode>,
} }
async fn web_build(State(state): State<AppState>, Query(query): Query<BuildQuery>) -> Response { async fn web_build(State(state): State<AppState>, Query(query): Query<BuildQuery>) -> Response {
@ -63,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.unwrap_or(BuildMode::Core), query.mode.map(|mode| mode.0).unwrap_or(BuildMode::Core),
) )
.await .await
{ {
@ -132,8 +154,8 @@ async fn web_target(State(state): State<AppState>, Query(query): Query<TargetQue
.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_core, latest_miri) {
(Some(core), Some(miri)) => { (Some(core), Some(std)) => {
if core.status == Status::Error || miri.status == Status::Error { if core.status == Status::Error || std.status == Status::Error {
Status::Error Status::Error
} else { } else {
Status::Pass Status::Pass
@ -150,7 +172,7 @@ async fn web_target(State(state): State<AppState>, Query(query): Query<TargetQue
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::Core => v.0 = Some(build),
BuildMode::MiriStd => v.1 = Some(build), BuildMode::Std => v.1 = Some(build),
} }
} }
@ -213,7 +235,7 @@ async fn web_nightly(State(state): State<AppState>, Query(query): Query<NightlyQ
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::Core => v.0 = Some(build.clone()),
BuildMode::MiriStd => v.1 = Some(build.clone()), BuildMode::Std => v.1 = Some(build.clone()),
} }
} }
@ -223,7 +245,7 @@ async fn web_nightly(State(state): State<AppState>, Query(query): Query<NightlyQ
if build.status == Status::Error { if build.status == Status::Error {
match build.mode { match build.mode {
BuildMode::Core => core_failures += 1, BuildMode::Core => core_failures += 1,
BuildMode::MiriStd => std_failures += 1, BuildMode::Std => std_failures += 1,
} }
} }
} }
@ -244,7 +266,7 @@ async fn web_nightly(State(state): State<AppState>, Query(query): Query<NightlyQ
.and_then(|info| info.broken_error.clone()); .and_then(|info| info.broken_error.clone());
let std_broken = info let std_broken = info
.iter() .iter()
.find(|info| info.mode == BuildMode::MiriStd && info.is_broken) .find(|info| info.mode == BuildMode::Std && info.is_broken)
.and_then(|info| info.broken_error.clone()); .and_then(|info| info.broken_error.clone());
let page = NightlyPage { let page = NightlyPage {

View file

@ -15,10 +15,12 @@
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 miri setup</code>. If a target does std is being built with <code>cargo check -Zbuild-std</code>. If a target
not support std, the std column represents core/alloc. This checks that does not support std, the std column represents core/alloc. This checks
std builds (on targets that have it) but does not check whether that std checks (on targets that have it) but does not check whether
codegen/linking works. codegen/linking works.
For older builds, <code>cargo miri setup</code> was used instead.
</p> </p>
{% if let Some(core_broken) = core_broken %} {% if let Some(core_broken) = core_broken %}
<p> <p>

View file

@ -23,10 +23,12 @@
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 miri setup</code>. If a target does std is being built with <code>cargo check -Zbuild-std</code>. If a target
not support std, the std column represents core/alloc. This checks that does not support std, the std column represents core/alloc. This checks
std builds (on targets that have it) but does not check whether that std checks (on targets that have it) but does not check whether
codegen/linking works. codegen/linking works.
For older builds, <code>cargo miri setup</code> was used instead.
</p> </p>
{% if showing_failures %} {% if showing_failures %}
<p> <p>