From 6d687fef324d083c04b1eff22e65b45494eb28d7 Mon Sep 17 00:00:00 2001 From: Zhang Junyang Date: Fri, 13 Jun 2025 20:16:51 +0800 Subject: [PATCH] Make OSDK scheme inheritance easier to use --- docs/src/osdk/reference/manifest.md | 44 +++++++++++++-------- osdk/src/config/manifest.rs | 18 +++++++-- osdk/src/config/scheme/mod.rs | 60 +++++++++++++++++++++++++++-- 3 files changed, 98 insertions(+), 24 deletions(-) diff --git a/docs/src/osdk/reference/manifest.md b/docs/src/osdk/reference/manifest.md index 0fb5b56c3..5d98bf862 100644 --- a/docs/src/osdk/reference/manifest.md +++ b/docs/src/osdk/reference/manifest.md @@ -28,7 +28,7 @@ the available configurations in the manifest. ```toml project_type = "kernel" # <1> -# --------------------------- the default schema settings ------------------------------- +# --------------------------- the default scheme settings ------------------------------- supported_archs = ["x86_64", "riscv64"] # <2> # The common options for all build, run and test subcommands @@ -63,13 +63,13 @@ args = "-machine q35 -m 2G" # <19> [test.boot] # <8> [test.grub] # <13> [test.qemu] # <17> -# ----------------------- end of the default schema settings ---------------------------- +# ----------------------- end of the default scheme settings ---------------------------- -# A customized schema settings -[schema."custom"] # <22> -[schema."custom".build] # <3> -[schema."custom".run] # <20> -[schema."custom".test] # <21> +# A customized scheme settings +[scheme."custom"] # <22> +[scheme."custom".build] # <3> +[scheme."custom".run] # <20> +[scheme."custom".test] # <21> ``` Here are some additional notes for the fields: @@ -201,10 +201,10 @@ can include any POSIX shell compliant separators. Similar to `20`, but only take effect when running `cargo osdk test`. -22. The definition of customized schema. +22. The definition of customized scheme. - A customized schema has the same fields as the default schema. - By default, a customized schema will inherit all options from the default schema, + A customized scheme has the same fields as the default scheme. + By default, a customized scheme will inherit all options from the default scheme, unless overridden by new options. ### Example @@ -221,10 +221,20 @@ used to determine the actual set of qemu arguments. ### Scheme -Scheme is an advanced feature to create multiple profiles for -the same actions under different scenarios. Scheme allows any -user-defined keys and can be selected by the `--scheme` CLI -argument. The key `scheme` can be used to create special settings -(especially special QEMU configurations). If a scheme action is -matched, unspecified and required arguments will be inherited -from the default scheme. +Scheme is an advanced feature that allows you to create multiple profiles for +the same action (`build`, `run`, or `test`) under different scenarios (e.g., +x86 vs. RISC-V). Schemes support any user-defined keys (see the 22nd +configuration) and can be selected using the `--scheme` CLI argument. + +If a scheme `` is selected for an action (such as `test`), the value of an +unspecified but required configuration `key` will be determined by the +following rules: + - If the general config (`scheme..key`) exists for the selected scheme, use + this value. + - Otherwise, if the default scheme has this configuration for the action + (`test.key`), use this value. + - Otherwise, if the default scheme has this configuration (`key`), use this + value. + +If the value is still not found, either the default value for the key will be +used or an error will be thrown. diff --git a/osdk/src/config/manifest.rs b/osdk/src/config/manifest.rs index 368438289..d1ce313a6 100644 --- a/osdk/src/config/manifest.rs +++ b/osdk/src/config/manifest.rs @@ -71,8 +71,14 @@ impl TomlManifest { process::exit(Errno::GetMetadata as _); }; + // Running and testing configs should inherit from the global configs. + current_manifest + .default_scheme + .run_and_test_inherit_from_global(); + // All the schemes should inherit from the default scheme. for scheme in current_manifest.map.values_mut() { + scheme.run_and_test_inherit_from_global(); scheme.inherit(¤t_manifest.default_scheme); } @@ -82,13 +88,17 @@ impl TomlManifest { /// Get the scheme given the scheme from the command line arguments. pub fn get_scheme(&self, scheme: Option) -> &Scheme { if let Some(scheme) = scheme { - let selected_scheme = self.map.get(&scheme.to_string()); - if selected_scheme.is_none() { + log::info!("Using scheme `{}`", scheme.to_string()); + + let Some(selected_scheme) = self.map.get(&scheme.to_string()) else { error_msg!("Scheme `{}` not found in `OSDK.toml`", scheme.to_string()); process::exit(Errno::ParseMetadata as _); - } - selected_scheme.unwrap() + }; + + selected_scheme } else { + log::info!("Using default scheme"); + &self.default_scheme } } diff --git a/osdk/src/config/scheme/mod.rs b/osdk/src/config/scheme/mod.rs index 23ad57a07..b6ca1fe24 100644 --- a/osdk/src/config/scheme/mod.rs +++ b/osdk/src/config/scheme/mod.rs @@ -16,17 +16,37 @@ pub use qemu::*; /// All the configurable fields within a scheme. #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Scheme { - // The user is not allowed to set this field. However, - // the manifest loader set this and all actions such - // as running, testing, and building will use this field. + /// The working directory. + /// + /// The user is not allowed to set this field. However, + /// the manifest loader set this and all actions such + /// as running, testing, and building will use this field. pub work_dir: Option, #[serde(default)] pub supported_archs: Vec, + /// The boot configs. + /// + /// Building, running, and testing would consult on these configs. pub boot: Option, + /// The GRUB configs. + /// + /// Building, running, and testing would consult on these configs. pub grub: Option, + /// The QEMU configs. + /// + /// Building, running, and testing would consult on these configs. pub qemu: Option, + /// Other build configs. + /// + /// Building, running, and testing would consult on these configs. pub build: Option, + /// Running specific configs. + /// + /// These values, if exists, overrides global boot/GRUB/QEMU/build configs. pub run: Option, + /// Testing specific configs. + /// + /// These values, if exists, overrides global boot/GRUB/QEMU/build configs. pub test: Option, } @@ -82,4 +102,38 @@ impl Scheme { self.work_dir.clone_from(&from.work_dir); } } + + /// Produces a scheme in which `run` and `test` action settings inherit + /// from the default settings in the provided scheme. + pub fn run_and_test_inherit_from_global(&mut self) { + let old_scheme = self.clone(); + + if let Some(run) = &mut self.run { + inherit_optional!(old_scheme, run, .boot); + inherit_optional!(old_scheme, run, .grub); + inherit_optional!(old_scheme, run, .qemu); + inherit_optional!(old_scheme, run, .build); + } else { + self.run = Some(ActionScheme { + boot: self.boot.clone(), + grub: self.grub.clone(), + qemu: self.qemu.clone(), + build: self.build.clone(), + }); + } + + if let Some(test) = &mut self.test { + inherit_optional!(old_scheme, test, .boot); + inherit_optional!(old_scheme, test, .grub); + inherit_optional!(old_scheme, test, .qemu); + inherit_optional!(old_scheme, test, .build); + } else { + self.test = Some(ActionScheme { + boot: self.boot.clone(), + grub: self.grub.clone(), + qemu: self.qemu.clone(), + build: self.build.clone(), + }); + } + } }