Make OSDK scheme inheritance easier to use

This commit is contained in:
Zhang Junyang
2025-06-13 20:16:51 +08:00
committed by Tate, Hongliang Tian
parent f3f0e9a244
commit 6d687fef32
3 changed files with 98 additions and 24 deletions

View File

@ -28,7 +28,7 @@ the available configurations in the manifest.
```toml ```toml
project_type = "kernel" # <1> project_type = "kernel" # <1>
# --------------------------- the default schema settings ------------------------------- # --------------------------- the default scheme settings -------------------------------
supported_archs = ["x86_64", "riscv64"] # <2> supported_archs = ["x86_64", "riscv64"] # <2>
# The common options for all build, run and test subcommands # The common options for all build, run and test subcommands
@ -63,13 +63,13 @@ args = "-machine q35 -m 2G" # <19>
[test.boot] # <8> [test.boot] # <8>
[test.grub] # <13> [test.grub] # <13>
[test.qemu] # <17> [test.qemu] # <17>
# ----------------------- end of the default schema settings ---------------------------- # ----------------------- end of the default scheme settings ----------------------------
# A customized schema settings # A customized scheme settings
[schema."custom"] # <22> [scheme."custom"] # <22>
[schema."custom".build] # <3> [scheme."custom".build] # <3>
[schema."custom".run] # <20> [scheme."custom".run] # <20>
[schema."custom".test] # <21> [scheme."custom".test] # <21>
``` ```
Here are some additional notes for the fields: 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`. 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. A customized scheme has the same fields as the default scheme.
By default, a customized schema will inherit all options from the default schema, By default, a customized scheme will inherit all options from the default scheme,
unless overridden by new options. unless overridden by new options.
### Example ### Example
@ -221,10 +221,20 @@ used to determine the actual set of qemu arguments.
### Scheme ### Scheme
Scheme is an advanced feature to create multiple profiles for Scheme is an advanced feature that allows you to create multiple profiles for
the same actions under different scenarios. Scheme allows any the same action (`build`, `run`, or `test`) under different scenarios (e.g.,
user-defined keys and can be selected by the `--scheme` CLI x86 vs. RISC-V). Schemes support any user-defined keys (see the 22nd
argument. The key `scheme` can be used to create special settings configuration) and can be selected using the `--scheme` CLI argument.
(especially special QEMU configurations). If a scheme action is
matched, unspecified and required arguments will be inherited If a scheme `<s>` is selected for an action (such as `test`), the value of an
from the default scheme. unspecified but required configuration `key` will be determined by the
following rules:
- If the general config (`scheme.<s>.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.

View File

@ -71,8 +71,14 @@ impl TomlManifest {
process::exit(Errno::GetMetadata as _); 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. // All the schemes should inherit from the default scheme.
for scheme in current_manifest.map.values_mut() { for scheme in current_manifest.map.values_mut() {
scheme.run_and_test_inherit_from_global();
scheme.inherit(&current_manifest.default_scheme); scheme.inherit(&current_manifest.default_scheme);
} }
@ -82,13 +88,17 @@ impl TomlManifest {
/// Get the scheme given the scheme from the command line arguments. /// Get the scheme given the scheme from the command line arguments.
pub fn get_scheme(&self, scheme: Option<impl ToString>) -> &Scheme { pub fn get_scheme(&self, scheme: Option<impl ToString>) -> &Scheme {
if let Some(scheme) = scheme { if let Some(scheme) = scheme {
let selected_scheme = self.map.get(&scheme.to_string()); log::info!("Using scheme `{}`", scheme.to_string());
if selected_scheme.is_none() {
let Some(selected_scheme) = self.map.get(&scheme.to_string()) else {
error_msg!("Scheme `{}` not found in `OSDK.toml`", scheme.to_string()); error_msg!("Scheme `{}` not found in `OSDK.toml`", scheme.to_string());
process::exit(Errno::ParseMetadata as _); process::exit(Errno::ParseMetadata as _);
} };
selected_scheme.unwrap()
selected_scheme
} else { } else {
log::info!("Using default scheme");
&self.default_scheme &self.default_scheme
} }
} }

View File

@ -16,17 +16,37 @@ pub use qemu::*;
/// All the configurable fields within a scheme. /// All the configurable fields within a scheme.
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Scheme { pub struct Scheme {
// The user is not allowed to set this field. However, /// The working directory.
// the manifest loader set this and all actions such ///
// as running, testing, and building will use this field. /// 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<PathBuf>, pub work_dir: Option<PathBuf>,
#[serde(default)] #[serde(default)]
pub supported_archs: Vec<Arch>, pub supported_archs: Vec<Arch>,
/// The boot configs.
///
/// Building, running, and testing would consult on these configs.
pub boot: Option<BootScheme>, pub boot: Option<BootScheme>,
/// The GRUB configs.
///
/// Building, running, and testing would consult on these configs.
pub grub: Option<GrubScheme>, pub grub: Option<GrubScheme>,
/// The QEMU configs.
///
/// Building, running, and testing would consult on these configs.
pub qemu: Option<QemuScheme>, pub qemu: Option<QemuScheme>,
/// Other build configs.
///
/// Building, running, and testing would consult on these configs.
pub build: Option<BuildScheme>, pub build: Option<BuildScheme>,
/// Running specific configs.
///
/// These values, if exists, overrides global boot/GRUB/QEMU/build configs.
pub run: Option<ActionScheme>, pub run: Option<ActionScheme>,
/// Testing specific configs.
///
/// These values, if exists, overrides global boot/GRUB/QEMU/build configs.
pub test: Option<ActionScheme>, pub test: Option<ActionScheme>,
} }
@ -82,4 +102,38 @@ impl Scheme {
self.work_dir.clone_from(&from.work_dir); 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(),
});
}
}
} }