diff --git a/migrations/20240908082826_add_miri_std.sql b/migrations/20240908082826_add_miri_std.sql
new file mode 100644
index 0000000..46076e9
--- /dev/null
+++ b/migrations/20240908082826_add_miri_std.sql
@@ -0,0 +1,43 @@
+PRAGMA foreign_keys=OFF;
+
+-- Migrate build_info
+
+CREATE TABLE new_build_info (
+ "nightly" VARCHAR NOT NULL,
+ "target" VARCHAR NOT NULL,
+ "status" VARCHAR NOT NULL,
+ "stderr" VARCHAR NOT NULL,
+ "mode" VARCHAR NOT NULL,
+
+ PRIMARY KEY ("nightly", "target", "mode")
+);
+
+INSERT INTO new_build_info (nightly, target, status, stderr, mode)
+SELECT nightly, target, status, stderr, 'core' FROM build_info;
+
+DROP TABLE build_info;
+
+ALTER TABLE new_build_info RENAME TO build_info;
+
+
+-- Migrate finished_nightly
+
+CREATE TABLE new_finished_nightly (
+ "nightly" VARCHAR NOT NULL,
+ "mode" VARCHAR NOT NULL,
+
+ PRIMARY KEY ("nightly", "mode")
+);
+
+INSERT INTO new_finished_nightly (nightly, mode)
+SELECT nightly, 'core' FROM finished_nightly;
+
+DROP TABLE finished_nightly;
+
+ALTER TABLE new_finished_nightly RENAME TO finished_nightly;
+
+-- Finish
+
+PRAGMA foreign_keys=ON;
+
+
diff --git a/src/build.rs b/src/build.rs
index 8806e63..159bd7f 100644
--- a/src/build.rs
+++ b/src/build.rs
@@ -14,7 +14,7 @@ use tokio::process::Command;
use tracing::{debug, info};
use crate::{
- db::{Db, FullBuildInfo, Status},
+ db::{BuildMode, Db, FullBuildInfo, Status},
nightlies::Nightlies,
};
@@ -45,9 +45,9 @@ pub async fn background_builder(db: Db) -> Result<()> {
let next = nightlies.select_latest_to_build(&already_finished);
match next {
- Some(nightly) => {
- info!(%nightly, "Building next nightly");
- build_every_target_for_toolchain(&db, &nightly)
+ Some((nightly, mode)) => {
+ info!(%nightly, %mode, "Building next nightly");
+ build_every_target_for_toolchain(&db, &nightly, mode)
.await
.wrap_err_with(|| format!("building targets for toolchain {nightly}"))?;
}
@@ -82,7 +82,7 @@ async fn targets_for_toolchain(toolchain: &Toolchain) -> Result> {
}
#[tracing::instrument]
-async fn install_toolchain(toolchain: &Toolchain) -> Result<()> {
+async fn install_toolchain(toolchain: &Toolchain, mode: BuildMode) -> Result<()> {
info!(%toolchain, "Installing toolchain");
let result = Command::new("rustup")
@@ -109,6 +109,20 @@ async fn install_toolchain(toolchain: &Toolchain) -> Result<()> {
if !result.status.success() {
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(())
}
@@ -132,14 +146,18 @@ async fn uninstall_toolchain(toolchain: &Toolchain) -> Result<()> {
Ok(())
}
-pub async fn build_every_target_for_toolchain(db: &Db, nightly: &str) -> Result<()> {
- if db.is_nightly_finished(nightly).await? {
+pub async fn build_every_target_for_toolchain(
+ db: &Db,
+ nightly: &str,
+ mode: BuildMode,
+) -> Result<()> {
+ if db.is_nightly_finished(nightly, mode).await? {
debug!("Nightly is already finished, not trying again");
return Ok(());
}
let toolchain = Toolchain::from_nightly(nightly);
- install_toolchain(&toolchain).await?;
+ install_toolchain(&toolchain, mode).await?;
let targets = targets_for_toolchain(&toolchain)
.await
@@ -153,7 +171,7 @@ pub async fn build_every_target_for_toolchain(db: &Db, nightly: &str) -> Result<
let results = futures::stream::iter(
targets
.iter()
- .map(|target| build_single_target(&db, nightly, target)),
+ .map(|target| build_single_target(&db, nightly, target, mode)),
)
.buffer_unordered(concurrent)
.collect::>>()
@@ -163,13 +181,13 @@ pub async fn build_every_target_for_toolchain(db: &Db, nightly: &str) -> Result<
}
for target in targets {
- build_single_target(db, nightly, &target)
+ build_single_target(db, nightly, &target, mode)
.await
.wrap_err_with(|| format!("building target {target} for toolchain {toolchain}"))?;
}
// Mark it as finished, so we never have to build it again.
- db.finish_nightly(nightly).await?;
+ db.finish_nightly(nightly, mode).await?;
uninstall_toolchain(&toolchain).await?;
@@ -177,9 +195,9 @@ pub async fn build_every_target_for_toolchain(db: &Db, nightly: &str) -> Result<
}
#[tracing::instrument(skip(db))]
-async fn build_single_target(db: &Db, nightly: &str, target: &str) -> Result<()> {
+async fn build_single_target(db: &Db, nightly: &str, target: &str, mode: BuildMode) -> Result<()> {
let existing = db
- .build_status_full(nightly, target)
+ .build_status_full(nightly, target, mode)
.await
.wrap_err("getting existing build")?;
if existing.is_some() {
@@ -191,15 +209,21 @@ async fn build_single_target(db: &Db, nightly: &str, target: &str) -> Result<()>
let tmpdir = tempfile::tempdir().wrap_err("creating temporary directory")?;
- 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(),
target: target.into(),
status: result.status,
stderr: result.stderr,
+ mode,
})
.await?;
@@ -212,31 +236,47 @@ 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 {
- std::fs::create_dir_all(&tmpdir).wrap_err("creating target src dir")?;
+async fn build_target(
+ tmpdir: &Path,
+ toolchain: &Toolchain,
+ target: &str,
+ mode: BuildMode,
+) -> Result {
+ let output = match mode {
+ BuildMode::Core => {
+ let init = Command::new("cargo")
+ .args(["init", "--lib", "--name", "target-test"])
+ .current_dir(&tmpdir)
+ .output()
+ .await
+ .wrap_err("spawning cargo init")?;
+ if !init.status.success() {
+ bail!("init failed: {}", String::from_utf8(init.stderr)?);
+ }
- let init = Command::new("cargo")
- .args(["init", "--lib", "--name", "target-test"])
- .current_dir(&tmpdir)
- .output()
- .await
- .wrap_err("spawning cargo init")?;
- if !init.status.success() {
- bail!("init failed: {}", String::from_utf8(init.stderr)?);
- }
+ let librs = tmpdir.join("src").join("lib.rs");
+ std::fs::write(&librs, "#![no_std]\n")
+ .wrap_err_with(|| format!("writing to {}", librs.display()))?;
- let librs = tmpdir.join("src").join("lib.rs");
- std::fs::write(&librs, "#![no_std]\n")
- .wrap_err_with(|| format!("writing to {}", librs.display()))?;
-
- let output = Command::new("cargo")
- .arg(format!("+{toolchain}"))
- .args(["build", "-Zbuild-std=core", "--release"])
- .args(["--target", target])
- .current_dir(&tmpdir)
- .output()
- .await
- .wrap_err("spawning cargo build")?;
+ Command::new("cargo")
+ .arg(format!("+{toolchain}"))
+ .args(["build", "-Zbuild-std=core", "--release"])
+ .args(["--target", target])
+ .current_dir(&tmpdir)
+ .output()
+ .await
+ .wrap_err("spawning cargo build")?
+ }
+ BuildMode::MiriStd => Command::new("cargo")
+ .arg(format!("+{toolchain}"))
+ .args(["miri", "setup"])
+ .args(["--target", target])
+ .current_dir(&tmpdir)
+ .env("MIRI_SYSROOT", tmpdir)
+ .output()
+ .await
+ .wrap_err("spawning cargo build")?,
+ };
let stderr = String::from_utf8(output.stderr).wrap_err("cargo stderr utf8")?;
diff --git a/src/db.rs b/src/db.rs
index 8ed5319..f88244a 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -1,6 +1,9 @@
use std::{fmt::Display, str::FromStr};
-use color_eyre::{eyre::Context, Result};
+use color_eyre::{
+ eyre::{bail, Context},
+ Result,
+};
use serde::{Deserialize, Serialize};
use sqlx::{migrate::Migrator, sqlite::SqliteConnectOptions, Pool, Sqlite};
@@ -11,11 +14,31 @@ pub struct Db {
pub static MIGRATOR: Migrator = sqlx::migrate!();
+#[derive(Debug, Clone, Copy, sqlx::Type, Serialize, Deserialize, PartialEq, Eq, Hash)]
+#[sqlx(rename_all = "kebab-case")]
+#[serde(rename_all = "kebab-case")]
+pub enum BuildMode {
+ /// `-Zbuild-std=core`
+ Core,
+ /// `cargo miri setup`
+ MiriStd,
+}
+
+impl Display for BuildMode {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Self::Core => f.write_str("core"),
+ Self::MiriStd => f.write_str("miri-std"),
+ }
+ }
+}
+
#[derive(sqlx::FromRow, Serialize, Deserialize)]
pub struct BuildInfo {
pub nightly: String,
pub target: String,
pub status: Status,
+ pub mode: BuildMode,
}
#[derive(Clone, sqlx::FromRow, Serialize, Deserialize)]
@@ -24,6 +47,7 @@ pub struct FullBuildInfo {
pub target: String,
pub status: Status,
pub stderr: String,
+ pub mode: BuildMode,
}
#[derive(Debug, PartialEq, Clone, Copy, sqlx::Type, Serialize, Deserialize)]
@@ -43,9 +67,10 @@ impl Display for Status {
}
}
-#[derive(sqlx::FromRow)]
-struct FinishedNightly {
- nightly: String,
+#[derive(sqlx::FromRow, Debug, PartialEq, Eq, Hash)]
+pub struct FinishedNightly {
+ pub nightly: String,
+ pub mode: BuildMode,
}
impl Db {
@@ -62,12 +87,13 @@ impl Db {
pub async fn insert(&self, info: FullBuildInfo) -> Result<()> {
sqlx::query(
- "INSERT INTO build_info (nightly, target, status, stderr) VALUES (?, ?, ?, ?);",
+ "INSERT INTO build_info (nightly, target, status, stderr, mode) VALUES (?, ?, ?, ?, ?);",
)
.bind(info.nightly)
.bind(info.target)
.bind(info.status)
.bind(info.stderr)
+ .bind(info.mode)
.execute(&self.conn)
.await
.wrap_err("inserting build info into database")?;
@@ -75,7 +101,7 @@ impl Db {
}
pub async fn build_status(&self) -> Result> {
- sqlx::query_as::<_, BuildInfo>("SELECT nightly, target, status FROM build_info")
+ sqlx::query_as::<_, BuildInfo>("SELECT nightly, target, status, mode FROM build_info")
.fetch_all(&self.conn)
.await
.wrap_err("getting build status from DB")
@@ -85,43 +111,52 @@ impl Db {
&self,
nightly: &str,
target: &str,
+ mode: BuildMode,
) -> Result
- Does therefore currently not check for the std build status.
-
+ This checks that codegen/linking of core works, but does not check whether std builds.
@@ -27,6 +23,23 @@
loading... |
+
+
+ Miri Std Build
+ Builds every target with:
+
cargo miri setup
+ This checks that std builds (on targets that have it) but does not check whether codegen/linking works.
+
+
+
+
+
+
+
-