From 93c315e8b2cba2428bda70933e43586be20dc3ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E7=9D=BF?= Date: Thu, 21 May 2026 16:47:42 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=A6=81?= =?UTF-8?q?=E7=94=A8=20someboot=20=E8=87=AA=E5=8A=A8=E6=B3=A8=E5=85=A5=20C?= =?UTF-8?q?argo=20=E5=8F=82=E6=95=B0=E7=9A=84=E9=85=8D=E7=BD=AE=E9=80=89?= =?UTF-8?q?=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.en.md | 3 + README.md | 3 + ostool/src/bin/cargo-osrun.rs | 1 + ostool/src/board/config.rs | 1 + ostool/src/build/cargo_builder.rs | 63 ++++++++++++++++++++- ostool/src/build/config.rs | 70 +++++++++++++++++++++++ ostool/src/run/qemu.rs | 3 + ostool/src/run/uboot.rs | 2 + ostool/src/tool.rs | 84 +++++++++++++++++++++++++++- ostool/tests/ui/pass_tool_configs.rs | 8 ++- 10 files changed, 234 insertions(+), 4 deletions(-) diff --git a/README.en.md b/README.en.md index ced6fe1..69df043 100644 --- a/README.en.md +++ b/README.en.md @@ -189,6 +189,9 @@ env = { "RUSTFLAGS" = "-C link-arg=-Tlinker.ld" } # while other builds/runs use Release. profile = "Release" +# To disable automatic Cargo argument injection from someboot build-info.toml, set this to true. +# disable_someboot_build_config = true + # Additional cargo arguments args = [] diff --git a/README.md b/README.md index 41c5a5d..88d0789 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,9 @@ env = { "RUSTFLAGS" = "-C link-arg=-Tlinker.ld" } # 省略时保持兼容行为:QEMU --debug 使用 Debug,其它构建/运行使用 Release。 profile = "Release" +# 如需禁用从 someboot build-info.toml 自动注入 Cargo 参数,可显式设置为 true。 +# disable_someboot_build_config = true + # 额外的 cargo 参数 args = [] diff --git a/ostool/src/bin/cargo-osrun.rs b/ostool/src/bin/cargo-osrun.rs index 1f584d9..5b22310 100644 --- a/ostool/src/bin/cargo-osrun.rs +++ b/ostool/src/bin/cargo-osrun.rs @@ -130,6 +130,7 @@ async fn try_main() -> anyhow::Result<()> { build_dir, bin_dir, debug: args.debug, + disable_someboot_build_config: false, })?; tool.prepare_elf_artifact(args.elf, args.to_bin).await?; diff --git a/ostool/src/board/config.rs b/ostool/src/board/config.rs index dcabb8f..f3142dc 100644 --- a/ostool/src/board/config.rs +++ b/ostool/src/board/config.rs @@ -390,6 +390,7 @@ dtb_file = "${package}/board.dtb" log: None, extra_config: None, profile: None, + disable_someboot_build_config: false, args: vec![], pre_build_cmds: vec![], post_build_cmds: vec![], diff --git a/ostool/src/build/cargo_builder.rs b/ostool/src/build/cargo_builder.rs index 7039dd4..75315da 100644 --- a/ostool/src/build/cargo_builder.rs +++ b/ostool/src/build/cargo_builder.rs @@ -256,7 +256,7 @@ impl<'a> CargoBuilder<'a> { // Auto-detected args from someboot/build-info.toml let workspace_manifest = self.tool.workspace_dir().join("Cargo.toml"); - if workspace_manifest.exists() { + if self.tool.someboot_build_config_enabled(self.config) && workspace_manifest.exists() { let detected_args = someboot::detect_build_config_for_package( &workspace_manifest, &self.config.package, @@ -594,6 +594,33 @@ mod tests { select_executable_artifact(artifacts, explicit_bin, default_run, package) } + fn write_someboot_workspace(root: &Path) { + fs::write( + root.join("Cargo.toml"), + "[workspace]\nmembers = [\"app\", \"someboot\"]\nresolver = \"3\"\n", + ) + .unwrap(); + fs::create_dir_all(root.join("app/src")).unwrap(); + fs::write( + root.join("app/Cargo.toml"), + "[package]\nname = \"app\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\nsomeboot = { path = \"../someboot\" }\n", + ) + .unwrap(); + fs::write(root.join("app/src/main.rs"), "fn main() {}\n").unwrap(); + fs::create_dir_all(root.join("someboot/src")).unwrap(); + fs::write( + root.join("someboot/Cargo.toml"), + "[package]\nname = \"someboot\"\nversion = \"0.1.0\"\nedition = \"2024\"\n", + ) + .unwrap(); + fs::write(root.join("someboot/src/lib.rs"), "pub fn marker() {}\n").unwrap(); + fs::write( + root.join("someboot/build-info.toml"), + "[x86_64-unknown-none]\ncargoargs = [\"--someboot-cargoarg\"]\nrustflags = [\"-Cdebuginfo=2\"]\n", + ) + .unwrap(); + } + #[test] fn select_executable_artifact_uses_explicit_bin_first() { let artifacts = vec![ @@ -685,6 +712,39 @@ mod tests { assert!(rendered.contains("kernel-uboot")); } + #[tokio::test] + async fn build_cargo_command_skips_someboot_args_when_cargo_config_disables_them() { + let temp = tempfile::tempdir().unwrap(); + write_someboot_workspace(temp.path()); + + let config = Cargo { + package: "app".into(), + target: "x86_64-unknown-none".into(), + disable_someboot_build_config: true, + profile: Some(CargoBuildProfile::Debug), + ..Default::default() + }; + + let mut tool = Tool::new(ToolConfig { + manifest: Some(temp.path().to_path_buf()), + ..Default::default() + }) + .unwrap(); + let mut builder = CargoBuilder::build(&mut tool, &config, None).skip_objcopy(true); + let cmd = builder.build_cargo_command().await.unwrap(); + let args: Vec = cmd + .get_args() + .map(|arg| arg.to_string_lossy().into_owned()) + .collect(); + + assert!(!args.iter().any(|arg| arg == "--someboot-cargoarg")); + assert!( + !args + .iter() + .any(|arg| arg.contains("target.x86_64-unknown-none.rustflags")) + ); + } + /// Verifies resolved Cargo artifacts are recorded into runtime state. /// /// This covers post-resolution Tool state, not serde/config loading. @@ -713,6 +773,7 @@ mod tests { log: None, extra_config: None, profile: Some(CargoBuildProfile::Debug), + disable_someboot_build_config: false, args: vec![], pre_build_cmds: vec![], post_build_cmds: vec![], diff --git a/ostool/src/build/config.rs b/ostool/src/build/config.rs index bf5f104..d24bb92 100644 --- a/ostool/src/build/config.rs +++ b/ostool/src/build/config.rs @@ -21,6 +21,10 @@ use std::collections::HashMap; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +fn is_false(value: &bool) -> bool { + !*value +} + /// Root build configuration structure. /// /// This is the top-level configuration that specifies which build system @@ -96,6 +100,9 @@ pub struct Cargo { /// Cargo's dev profile, and normal builds/runs use Cargo's release profile. #[serde(default)] pub profile: Option, + /// Disable automatic Cargo argument injection from someboot build metadata. + #[serde(default, skip_serializing_if = "is_false")] + pub disable_someboot_build_config: bool, /// Additional Cargo command-line arguments. pub args: Vec, /// Shell commands to run before the build. @@ -143,3 +150,66 @@ pub enum LogLevel { /// Error level logging. Error, } + +#[cfg(test)] +mod tests { + use super::Cargo; + + #[test] + fn cargo_config_defaults_someboot_injection_to_enabled_when_field_is_absent() { + let cargo: Cargo = toml::from_str( + r#" +env = {} +target = "x86_64-unknown-none" +package = "kernel" +features = [] +args = [] +pre_build_cmds = [] +post_build_cmds = [] +to_bin = false +"#, + ) + .unwrap(); + + assert!(!cargo.disable_someboot_build_config); + } + + #[test] + fn cargo_config_omits_someboot_disable_field_when_false() { + let cargo = Cargo { + env: Default::default(), + target: "x86_64-unknown-none".into(), + package: "kernel".into(), + features: Vec::new(), + args: Vec::new(), + pre_build_cmds: Vec::new(), + post_build_cmds: Vec::new(), + to_bin: false, + ..Cargo::default() + }; + + let rendered = toml::to_string(&cargo).unwrap(); + + assert!(!rendered.contains("disable_someboot_build_config")); + } + + #[test] + fn cargo_config_serializes_someboot_disable_field_when_true() { + let cargo = Cargo { + env: Default::default(), + target: "x86_64-unknown-none".into(), + package: "kernel".into(), + features: Vec::new(), + disable_someboot_build_config: true, + args: Vec::new(), + pre_build_cmds: Vec::new(), + post_build_cmds: Vec::new(), + to_bin: false, + ..Cargo::default() + }; + + let rendered = toml::to_string(&cargo).unwrap(); + + assert!(rendered.contains("disable_someboot_build_config = true")); + } +} diff --git a/ostool/src/run/qemu.rs b/ostool/src/run/qemu.rs index 15a3e77..c5d425d 100644 --- a/ostool/src/run/qemu.rs +++ b/ostool/src/run/qemu.rs @@ -927,6 +927,7 @@ fail_regex = [] log: None, extra_config: None, profile: None, + disable_someboot_build_config: false, args: vec![], pre_build_cmds: vec![], post_build_cmds: vec![], @@ -950,6 +951,7 @@ fail_regex = [] log: None, extra_config: None, profile: None, + disable_someboot_build_config: false, args: vec![], pre_build_cmds: vec![], post_build_cmds: vec![], @@ -1113,6 +1115,7 @@ timeout = 0 log: None, extra_config: None, profile: None, + disable_someboot_build_config: false, args: vec![], pre_build_cmds: vec![], post_build_cmds: vec![], diff --git a/ostool/src/run/uboot.rs b/ostool/src/run/uboot.rs index f92d78a..9a52d45 100644 --- a/ostool/src/run/uboot.rs +++ b/ostool/src/run/uboot.rs @@ -1633,6 +1633,7 @@ timeout = 0 log: None, extra_config: None, profile: None, + disable_someboot_build_config: false, args: vec![], pre_build_cmds: vec![], post_build_cmds: vec![], @@ -1822,6 +1823,7 @@ baud_rate = "115200" log: None, extra_config: None, profile: None, + disable_someboot_build_config: false, args: vec![], pre_build_cmds: vec![], post_build_cmds: vec![], diff --git a/ostool/src/tool.rs b/ostool/src/tool.rs index 3f43371..b622b96 100644 --- a/ostool/src/tool.rs +++ b/ostool/src/tool.rs @@ -38,6 +38,8 @@ pub struct ToolConfig { pub bin_dir: Option, /// Whether debug mode is enabled. pub debug: bool, + /// Disable automatic Cargo argument injection from someboot build metadata. + pub disable_someboot_build_config: bool, } /// Main library object orchestrating build and run operations. @@ -84,6 +86,15 @@ impl Tool { self.ctx.build_config_path = path; } + /// Enables or disables automatic Cargo argument injection from someboot build metadata. + pub fn set_someboot_build_config_enabled(&mut self, enabled: bool) { + self.config.disable_someboot_build_config = !enabled; + } + + pub(crate) fn someboot_build_config_enabled(&self, cargo: &Cargo) -> bool { + !self.config.disable_someboot_build_config && !cargo.disable_someboot_build_config + } + pub fn into_context(self) -> AppContext { self.ctx } @@ -376,7 +387,9 @@ impl Tool { bail!("No build configuration obtained"); }; - if let BuildSystem::Cargo(cargo) = &mut c.system { + if let BuildSystem::Cargo(cargo) = &mut c.system + && self.someboot_build_config_enabled(cargo) + { let iter = self.someboot_cargo_args(cargo)?.into_iter(); cargo.args.extend(iter); } @@ -1039,6 +1052,74 @@ mod tests { assert_eq!(resolved, kernel_dir.join(".qemu-aarch64.toml")); } + #[tokio::test] + async fn prepare_build_config_skips_someboot_args_when_cargo_config_disables_them() { + let temp = tempfile::tempdir().unwrap(); + fs::write( + temp.path().join("Cargo.toml"), + "[workspace]\nmembers = [\"app\", \"someboot\"]\nresolver = \"3\"\n", + ) + .unwrap(); + fs::write( + temp.path().join(".build.toml"), + r#" +[system.Cargo] +package = "app" +target = "x86_64-unknown-none" +disable_someboot_build_config = true +env = {} +features = [] +args = [] +pre_build_cmds = [] +post_build_cmds = [] +to_bin = false +"#, + ) + .unwrap(); + let app_dir = temp.path().join("app"); + fs::create_dir_all(app_dir.join("src")).unwrap(); + fs::write( + app_dir.join("Cargo.toml"), + "[package]\nname = \"app\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\nsomeboot = { path = \"../someboot\" }\n", + ) + .unwrap(); + fs::write(app_dir.join("src/main.rs"), "fn main() {}\n").unwrap(); + let someboot_dir = temp.path().join("someboot"); + fs::create_dir_all(someboot_dir.join("src")).unwrap(); + fs::write( + someboot_dir.join("Cargo.toml"), + "[package]\nname = \"someboot\"\nversion = \"0.1.0\"\nedition = \"2024\"\n", + ) + .unwrap(); + fs::write(someboot_dir.join("src/lib.rs"), "pub fn marker() {}\n").unwrap(); + fs::write( + someboot_dir.join("build-info.toml"), + "[x86_64-unknown-none]\ncargoargs = [\"--someboot-cargoarg\"]\nrustflags = [\"-Cdebuginfo=2\"]\n", + ) + .unwrap(); + + let mut tool = Tool::new(ToolConfig { + manifest: Some(temp.path().to_path_buf()), + ..Default::default() + }) + .unwrap(); + let config = tool + .load_build_config_from_path(&temp.path().join(".build.toml"), false) + .await + .unwrap(); + + let BuildSystem::Cargo(cargo) = config.system else { + panic!("expected Cargo build config"); + }; + assert!(!cargo.args.iter().any(|arg| arg == "--someboot-cargoarg")); + assert!( + !cargo + .args + .iter() + .any(|arg| arg.contains("target.x86_64-unknown-none.rustflags")) + ); + } + #[test] fn replace_string_uses_workspace_and_legacy_workspacefolder() { let temp = tempfile::tempdir().unwrap(); @@ -1149,6 +1230,7 @@ mod tests { log: None, extra_config: None, profile: None, + disable_someboot_build_config: false, args: vec![], pre_build_cmds: vec![], post_build_cmds: vec![], diff --git a/ostool/tests/ui/pass_tool_configs.rs b/ostool/tests/ui/pass_tool_configs.rs index fbe98c0..45139c7 100644 --- a/ostool/tests/ui/pass_tool_configs.rs +++ b/ostool/tests/ui/pass_tool_configs.rs @@ -8,9 +8,13 @@ use ostool::{ }; fn main() { - let tool = Tool::new(ToolConfig::default()).unwrap(); + let mut tool = Tool::new(ToolConfig::default()).unwrap(); + tool.set_someboot_build_config_enabled(false); let _: BuildConfig = tool.default_build_config(); - let cargo = Cargo::default(); + let cargo = Cargo { + disable_someboot_build_config: true, + ..Cargo::default() + }; let qemu: QemuConfig = tool.default_qemu_config_for_cargo(&cargo); let _ = tool.default_qemu_config(); let uboot: UbootConfig = tool.default_uboot_config(); From 582602aed6b75eadaf6337f1c1e24c895ed09331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E7=9D=BF?= Date: Thu, 21 May 2026 17:09:39 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E7=A7=BB=E9=99=A4=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=A4=B1=E8=B4=A5=E6=A8=A1=E5=BC=8F=EF=BC=8C=E7=A1=AE?= =?UTF-8?q?=E4=BF=9D=E7=BC=96=E8=AF=91=E6=AD=A3=E5=88=99=E8=A1=A8=E8=BE=BE?= =?UTF-8?q?=E5=BC=8F=E6=97=B6=E4=BF=9D=E6=8C=81=E7=A9=BA=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ostool/src/run/output_matcher.rs | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/ostool/src/run/output_matcher.rs b/ostool/src/run/output_matcher.rs index 77b607c..578497f 100644 --- a/ostool/src/run/output_matcher.rs +++ b/ostool/src/run/output_matcher.rs @@ -6,7 +6,6 @@ use regex::Regex; pub(crate) const MATCH_DRAIN_DURATION: Duration = Duration::from_millis(500); const MAX_MATCH_WINDOW_BYTES: usize = 2048; -const DEFAULT_FAIL_PATTERNS: &[&str] = &[r"(?i)\bpanic(?:ked)?\b", r"(?i)kernel panic"]; const MATCH_EXCERPT_CONTEXT_CHARS: usize = 120; const MATCH_EXCERPT_MAX_CHARS: usize = 240; @@ -46,17 +45,7 @@ pub(crate) fn compile_regexes( .map(|p| Regex::new(p).map_err(|e| anyhow!("success regex error: {e}"))) .collect::, _>>()?; - let mut merged_fail_patterns = fail_patterns.to_vec(); - for pattern in DEFAULT_FAIL_PATTERNS { - if !merged_fail_patterns - .iter() - .any(|existing| existing == pattern) - { - merged_fail_patterns.push((*pattern).to_string()); - } - } - - let fail_regex = merged_fail_patterns + let fail_regex = fail_patterns .iter() .map(|p| Regex::new(p).map_err(|e| anyhow!("fail regex error: {e}"))) .collect::, _>>()?; @@ -295,17 +284,10 @@ mod tests { } #[test] - fn compile_regexes_appends_builtin_panic_patterns() { + fn compile_regexes_keeps_empty_fail_patterns_empty() { let (_success, fail) = compile_regexes(&[], &[]).unwrap(); - assert!( - fail.iter() - .any(|regex| regex.as_str() == r"(?i)\bpanic(?:ked)?\b") - ); - assert!( - fail.iter() - .any(|regex| regex.as_str() == r"(?i)kernel panic") - ); + assert!(fail.is_empty()); } #[test]