From b1d1728c42d89ae24acb14bcd2c330b948f1cd7a Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Fri, 4 Jul 2025 18:21:52 +0200 Subject: [PATCH] Support using custom rustflags for targets This is necessary for AVR and AMDGPU. We currently just hardcode some flags in the binary, which is good enough. There's a new column which keeps track of the used flags and shows them for a build. A migration makes sure that the older results are properly backfilled with the flags to make them build. --- ...0250704160556_reset-missing-target-cpu.sql | 8 +++ src/build.rs | 49 ++++++++++++++++--- src/db.rs | 6 ++- src/web.rs | 32 ++++++++---- {static => templates}/build.html | 5 ++ 5 files changed, 81 insertions(+), 19 deletions(-) create mode 100644 migrations/20250704160556_reset-missing-target-cpu.sql rename {static => templates}/build.html (93%) diff --git a/migrations/20250704160556_reset-missing-target-cpu.sql b/migrations/20250704160556_reset-missing-target-cpu.sql new file mode 100644 index 0000000..76d96a5 --- /dev/null +++ b/migrations/20250704160556_reset-missing-target-cpu.sql @@ -0,0 +1,8 @@ +-- Add migration script here + +ALTER TABLE build_info + ADD COLUMN rustflags VARCHAR; + +DELETE FROM build_info WHERE target IN ('avr-none', 'amdgcn-amd-amdhsa') AND mode = 'core'; + +DELETE FROM finished_nightly WHERE nightly > '2025-02-11'; diff --git a/src/build.rs b/src/build.rs index 7317e2b..e2d35f2 100644 --- a/src/build.rs +++ b/src/build.rs @@ -18,6 +18,22 @@ use crate::{ nightlies::Nightlies, }; +struct CustomBuildFlags { + target: &'static str, + flags: &'static [&'static str], +} + +const CUSTOM_CORE_FLAGS: &[CustomBuildFlags] = &[ + CustomBuildFlags { + target: "avr-none", + flags: &["-Ctarget-cpu=atmega328p"], + }, + CustomBuildFlags { + target: "amdgcn-amd-amdhsa", + flags: &["-Ctarget-cpu=gfx1100"], + }, +]; + pub struct Toolchain(String); impl Toolchain { pub fn from_nightly(nightly: &str) -> Self { @@ -44,9 +60,7 @@ pub async fn background_builder(db: Db) -> Result<()> { } async fn background_builder_inner(db: &Db) -> Result<()> { - let nightlies = Nightlies::fetch() - .await - .wrap_err("fetching nightlies")?; + let nightlies = Nightlies::fetch().await.wrap_err("fetching nightlies")?; let already_finished = db .finished_nightlies() .await @@ -243,6 +257,7 @@ async fn build_single_target(db: &Db, nightly: &str, target: &str, mode: BuildMo status: result.status, stderr: result.stderr, mode, + rustflags: result.rustflags, }) .await?; @@ -252,6 +267,7 @@ async fn build_single_target(db: &Db, nightly: &str, target: &str, mode: BuildMo struct BuildResult { status: Status, stderr: String, + rustflags: Option, } /// Build a target core in a temporary directory and see whether it passes or not. @@ -261,6 +277,8 @@ async fn build_target( target: &str, mode: BuildMode, ) -> Result { + let mut rustflags = None; + let output = match mode { BuildMode::Core => { let init = Command::new("cargo") @@ -277,11 +295,22 @@ async fn build_target( std::fs::write(&librs, "#![no_std]\n") .wrap_err_with(|| format!("writing to {}", librs.display()))?; - Command::new("cargo") - .arg(format!("+{toolchain}")) + let mut cmd = Command::new("cargo"); + cmd.arg(format!("+{toolchain}")) .args(["build", "-Zbuild-std=core", "--release"]) - .args(["--target", target]) - .current_dir(tmpdir) + .args(["--target", target]); + + 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); + } + + cmd.current_dir(tmpdir) .output() .await .wrap_err("spawning cargo build")? @@ -307,5 +336,9 @@ async fn build_target( info!("Finished build"); - Ok(BuildResult { status, stderr }) + Ok(BuildResult { + status, + stderr, + rustflags, + }) } diff --git a/src/db.rs b/src/db.rs index 42c1811..73aa95f 100644 --- a/src/db.rs +++ b/src/db.rs @@ -48,6 +48,7 @@ pub struct FullBuildInfo { pub status: Status, pub stderr: String, pub mode: BuildMode, + pub rustflags: Option, } #[derive(Debug, PartialEq, Clone, Copy, sqlx::Type, Serialize, Deserialize)] @@ -95,13 +96,14 @@ impl Db { pub async fn insert(&self, info: FullBuildInfo) -> Result<()> { sqlx::query( - "INSERT INTO build_info (nightly, target, status, stderr, mode) VALUES (?, ?, ?, ?, ?);", + "INSERT INTO build_info (nightly, target, status, stderr, mode, rustflags) VALUES (?, ?, ?, ?, ?, ?);", ) .bind(info.nightly) .bind(info.target) .bind(info.status) .bind(info.stderr) .bind(info.mode) + .bind(info.rustflags) .execute(&self.conn) .await .wrap_err("inserting build info into database")?; @@ -173,7 +175,7 @@ impl Db { mode: BuildMode, ) -> Result> { let result = sqlx::query_as::<_, FullBuildInfo>( - "SELECT nightly, target, status, stderr, mode FROM build_info + "SELECT nightly, target, status, stderr, mode, rustflags FROM build_info WHERE nightly = ? AND target = ? AND mode = ?", ) .bind(nightly) diff --git a/src/web.rs b/src/web.rs index 777c5c0..14eee79 100644 --- a/src/web.rs +++ b/src/web.rs @@ -41,6 +41,19 @@ struct BuildQuery { } async fn web_build(State(state): State, Query(query): Query) -> Response { + use askama::Template; + #[derive(askama::Template)] + #[template(path = "build.html")] + struct BuildPage { + nightly: String, + target: String, + stderr: String, + mode: BuildMode, + rustflags: Option, + version: &'static str, + status: Status, + } + match state .db .build_status_full( @@ -51,15 +64,16 @@ async fn web_build(State(state): State, Query(query): Query { - let page = include_str!("../static/build.html") - .replace("{{nightly}}", &query.nightly) - .replace("{{target}}", &query.target) - .replace("{{stderr}}", &build.stderr) - .replace("{{mode}}", &build.mode.to_string()) - .replace("{{version}}", crate::VERSION) - .replace("{{status}}", &build.status.to_string()); - - Html(page).into_response() + let page = BuildPage { + nightly: query.nightly, + target: query.target, + stderr: build.stderr, + mode: build.mode, + rustflags: build.rustflags, + version: crate::VERSION, + status: build.status, + }; + Html(page.render().unwrap()).into_response() } Ok(None) => StatusCode::NOT_FOUND.into_response(), Err(err) => { diff --git a/static/build.html b/templates/build.html similarity index 93% rename from static/build.html rename to templates/build.html index c86505d..4e28ced 100644 --- a/static/build.html +++ b/templates/build.html @@ -17,6 +17,11 @@
{{status}}
+ {% if let Some(rustflags) = rustflags %} +

+ Using rustflags: {{rustflags}} +

+ {% endif %}
 {{stderr}}