use std::path::Path;
use crate::{
Tool,
build::{
cargo_builder::CargoBuilder,
config::{Cargo, Custom},
},
run::{
qemu::{QemuConfig, RunQemuOptions},
uboot::{RunUbootOptions, UbootConfig},
},
};
mod cargo_builder;
pub mod config;
pub mod someboot;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct CargoQemuRunnerArgs {
pub qemu: Option<QemuConfig>,
pub debug: bool,
pub dtb_dump: bool,
pub show_output: bool,
}
#[derive(Debug, Clone, Default)]
pub struct CargoUbootRunnerArgs {
pub uboot: Option<UbootConfig>,
pub show_output: bool,
}
pub enum CargoRunnerKind {
Qemu(Box<CargoQemuRunnerArgs>),
Uboot(Box<CargoUbootRunnerArgs>),
}
impl CargoRunnerKind {
pub fn new_qemu(args: CargoQemuRunnerArgs) -> Self {
Self::Qemu(Box::new(args))
}
pub fn new_uboot(args: CargoUbootRunnerArgs) -> Self {
Self::Uboot(Box::new(args))
}
}
impl Tool {
pub fn default_build_config(&self) -> config::BuildConfig {
config::BuildConfig::default()
}
pub async fn load_build_config_from_dir(
&mut self,
dir: &Path,
menu: bool,
) -> anyhow::Result<config::BuildConfig> {
self.prepare_build_config(Some(dir.join(".build.toml")), menu)
.await
}
pub async fn load_build_config_from_path(
&mut self,
path: &Path,
menu: bool,
) -> anyhow::Result<config::BuildConfig> {
self.prepare_build_config(Some(path.to_path_buf()), menu)
.await
}
pub async fn build_with_config(&mut self, config: &config::BuildConfig) -> anyhow::Result<()> {
match &config.system {
config::BuildSystem::Custom(custom) => self.build_custom(custom)?,
config::BuildSystem::Cargo(cargo) => {
self.cargo_build(cargo).await?;
}
}
Ok(())
}
pub(crate) fn build_custom(&mut self, config: &Custom) -> anyhow::Result<()> {
self.shell_run_cmd(&config.build_cmd)?;
Ok(())
}
pub async fn cargo_build(&mut self, config: &Cargo) -> anyhow::Result<()> {
self.sync_cargo_context(config);
cargo_builder::CargoBuilder::build_auto(self, config)
.execute()
.await
}
pub(crate) async fn prepare_runtime_artifacts(
&mut self,
config: &config::BuildConfig,
debug: bool,
) -> anyhow::Result<()> {
match &config.system {
config::BuildSystem::Custom(custom) => {
self.prepare_custom_runtime_artifacts(custom).await
}
config::BuildSystem::Cargo(cargo) => {
self.prepare_cargo_runtime_artifacts(cargo, debug).await
}
}
}
async fn prepare_custom_runtime_artifacts(&mut self, config: &Custom) -> anyhow::Result<()> {
self.build_custom(config)?;
self.prepare_elf_artifact(config.elf_path.clone().into(), config.to_bin)
.await
}
async fn prepare_cargo_runtime_artifacts(
&mut self,
config: &Cargo,
debug: bool,
) -> anyhow::Result<()> {
let build_config_path = self.ctx.build_config_path.clone();
CargoBuilder::build(self, config, build_config_path)
.debug(debug)
.skip_objcopy(true)
.resolve_artifact_from_json(true)
.execute()
.await
}
pub async fn cargo_run(
&mut self,
config: &Cargo,
runner: &CargoRunnerKind,
) -> anyhow::Result<()> {
self.sync_cargo_context(config);
let build_config_path = self.ctx.build_config_path.clone();
let debug = matches!(runner, CargoRunnerKind::Qemu(args) if args.debug);
CargoBuilder::build(self, config, build_config_path)
.debug(debug)
.skip_objcopy(true)
.resolve_artifact_from_json(true)
.execute()
.await?;
match runner {
CargoRunnerKind::Qemu(args) => {
let qemu = match &args.qemu {
Some(config) => config.clone(),
None => self.ensure_qemu_config_for_cargo(config).await?,
};
self.run_qemu(
&qemu,
RunQemuOptions {
dtb_dump: args.dtb_dump,
show_output: args.show_output,
},
)
.await?;
}
CargoRunnerKind::Uboot(args) => {
let uboot = match &args.uboot {
Some(config) => config.clone(),
None => self.ensure_uboot_config_for_cargo(config).await?,
};
self.run_uboot(
&uboot,
RunUbootOptions {
show_output: args.show_output,
},
)
.await?;
}
}
Ok(())
}
}