From a090ea0020c5a443b4cf175634e3eda59842e7f8 Mon Sep 17 00:00:00 2001 From: not-jan <61017633+not-jan@users.noreply.github.com> Date: Mon, 3 Feb 2025 19:44:00 +0100 Subject: [PATCH] Add nds.toml to configure icon and title --- src/command.rs | 32 ++++++++--------- src/config.rs | 32 +++++++++++++++++ src/lib.rs | 98 +++++++++++++++++++++++++++----------------------- 3 files changed, 101 insertions(+), 61 deletions(-) create mode 100644 src/config.rs diff --git a/src/command.rs b/src/command.rs index 81772de..042400b 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,7 +1,7 @@ -use std::{env, fs}; use std::io::Read; use std::process::Stdio; use std::sync::OnceLock; +use std::{env, fs}; use cargo_metadata::Message; use clap::{Args, Parser, Subcommand}; @@ -171,7 +171,7 @@ impl CargoCmd { /// Returns the additional arguments run by the "official" cargo subcommand. pub fn cargo_args(&self) -> Vec { match self { - CargoCmd::Build(build) =>build.passthrough.cargo_args(), + CargoCmd::Build(build) => build.passthrough.cargo_args(), CargoCmd::Run(run) => run.build_args.passthrough.cargo_args(), CargoCmd::Test(test) => test.cargo_args(), CargoCmd::New(new) => { @@ -180,14 +180,14 @@ impl CargoCmd { cargo_args.push(new.path.clone()); cargo_args - }, + } CargoCmd::Init(init) => { // We push the original path in the init command (we captured it in [`Init`] to learn about the context) let mut cargo_args = init.cargo_args.cargo_args(); cargo_args.push(init.path.clone()); cargo_args - }, + } CargoCmd::Passthrough(other) => other.clone().split_off(1), } } @@ -416,8 +416,12 @@ impl Run { static HAS_RUNNER: OnceLock = OnceLock::new(); let &custom_runner_configured = HAS_RUNNER.get_or_init(|| { - let blocksds = env::var("BLOCKSDS").unwrap_or("/opt/wonderful/thirdparty/blocksds/core".to_owned()); - env::set_var("RUSTFLAGS", format!("-C link-args=-specs={blocksds}/sys/crts/ds_arm9.specs")); + let blocksds = env::var("BLOCKSDS") + .unwrap_or("/opt/wonderful/thirdparty/blocksds/core".to_owned()); + env::set_var( + "RUSTFLAGS", + format!("-C link-args=-specs={blocksds}/sys/crts/ds_arm9.specs"), + ); let mut cmd = cargo(&self.config); cmd.args([ @@ -425,7 +429,7 @@ impl Run { "-Z", "build-std=core,alloc", "--target", - "./armv5te-nintendo-ds.json" + "./armv5te-nintendo-ds.json", ]) .stdout(Stdio::null()) .stderr(Stdio::null()); @@ -590,7 +594,7 @@ extern "C" fn main() -> c_int } "#; -const CUSTOM_CARGO_CONFIG : &str = r#"[profile.release] +const CUSTOM_CARGO_CONFIG: &str = r#"[profile.release] codegen-units = 1 opt-level=3 debug-assertions=false @@ -625,7 +629,7 @@ impl New { let main_rs_path = project_path.join("src/main.rs"); let target_json_path = project_path.join("armv5te-nintendo-ds.json"); let config_path = project_path.join(".cargo/config.toml"); - + // Create the "romfs" directory fs::create_dir(romfs_path).unwrap(); @@ -643,14 +647,12 @@ impl New { // Add the custom changes to the main.rs file fs::write(main_rs_path, CUSTOM_MAIN_RS).unwrap(); - fs::write(target_json_path,TARGET_JSON).unwrap(); + fs::write(target_json_path, TARGET_JSON).unwrap(); fs::create_dir(project_path.join(".cargo")).unwrap(); fs::write(config_path, CUSTOM_CARGO_CONFIG).unwrap(); - } } - impl Init { /// Callback for `cargo nds new`. /// @@ -668,7 +670,7 @@ impl Init { let main_rs_path = project_path.join("src/main.rs"); let target_json_path = project_path.join("armv5te-nintendo-ds.json"); let config_path = project_path.join(".cargo/config.toml"); - + // Create the "romfs" directory fs::create_dir(romfs_path).unwrap(); @@ -686,10 +688,9 @@ impl Init { // Add the custom changes to the main.rs file fs::write(main_rs_path, CUSTOM_MAIN_RS).unwrap(); - fs::write(target_json_path,TARGET_JSON).unwrap(); + fs::write(target_json_path, TARGET_JSON).unwrap(); fs::create_dir(project_path.join(".cargo")).unwrap(); fs::write(config_path, CUSTOM_CARGO_CONFIG).unwrap(); - } } @@ -796,7 +797,6 @@ mod tests { .copied() .collect(); - dbg!(&input); let Cargo::Input(Input { cmd: CargoCmd::Run(Run { build_args, .. }), .. diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..ce3b6b5 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,32 @@ +use std::io::ErrorKind; + +use serde::{Deserialize, Serialize}; + +use crate::NDSConfig; + +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct Config { + pub name: [Option; 3], + pub icon: Option, +} + +impl Config { + pub fn try_load(nds_config: &NDSConfig) -> std::io::Result { + let mut path = nds_config.cargo_manifest_path.clone(); + path.pop(); + path.push("nds.toml"); + + match std::fs::exists(&path) { + Ok(true) => {} + Ok(false) => return Ok(Self::default()), + Err(e) => return Err(e), + } + + let config = std::fs::read_to_string(&path)?; + + let config: Config = toml::from_str(&config) + .map_err(|e| std::io::Error::new(ErrorKind::Other, e.message()))?; + + Ok(config) + } +} diff --git a/src/lib.rs b/src/lib.rs index 821e0e5..d9f3723 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ pub mod command; +mod config; mod graph; use core::fmt; @@ -10,6 +11,7 @@ use std::{env, io, process}; use cargo_metadata::{Message, MetadataCommand}; use command::{Input, Test}; +use config::Config; use rustc_version::Channel; use semver::Version; use tee::TeeReader; @@ -65,7 +67,8 @@ pub fn run_cargo(input: &Input, message_format: Option) -> (ExitStatus, /// For "build" commands (which compile code, such as `cargo nds build` or `cargo nds clippy`), /// if there is no pre-built std detected in the sysroot, `build-std` will be used instead. pub fn make_cargo_command(input: &Input, message_format: &Option) -> Command { - let blocksds = env::var("BLOCKSDS").unwrap_or("/opt/wonderful/thirdparty/blocksds/core".to_owned()); + let blocksds = + env::var("BLOCKSDS").unwrap_or("/opt/wonderful/thirdparty/blocksds/core".to_owned()); let rustflags = format!("-C link-args=-specs={blocksds}/sys/crts/ds_arm9.specs"); let cargo_cmd = &input.cmd; @@ -227,10 +230,7 @@ pub fn get_metadata(messages: &[Message]) -> NDSConfig { let mut icon = String::from("./icon.bmp"); if !Path::new(&icon).exists() { - icon = format!( - "{}/sys/icon.bmp", - env::var("BLOCKSDS").unwrap() - ); + icon = format!("{}/sys/icon.bmp", env::var("BLOCKSDS").unwrap()); } // for now assume a single "kind" since we only support one output artifact @@ -250,13 +250,13 @@ pub fn get_metadata(messages: &[Message]) -> NDSConfig { }; NDSConfig { - name : name, - author : author, + name: name, + author: author, description: package .description .clone() .unwrap_or_else(|| String::from("Homebrew Application")), - icon : icon, + icon: icon, target_path: artifact.executable.unwrap().into(), cargo_manifest_path: package.manifest_path.into(), } @@ -267,7 +267,27 @@ pub fn get_metadata(messages: &[Message]) -> NDSConfig { pub fn build_nds(config: &NDSConfig, verbose: bool) { let mut command = Command::new("ndstool"); let name = get_name(config); - let banner_text = format!("{};{};{}", name.0.file_name().unwrap().to_string_lossy(), &config.description, &config.author); + + let output_config = Config::try_load(config).expect("Failed to load nds.toml"); + + let banner_text = if output_config.name.iter().any(|i| i.is_some()) { + output_config + .name + .into_iter() + .map(|i| i.unwrap_or_default()) + .collect::>() + .join(";") + } else { + format!( + "{};{};{}", + name.0.file_name().unwrap().to_string_lossy(), + &config.description, + &config.author + ) + }; + + let icon = get_icon_path(config); + command .arg("-c") .arg(config.path_nds()) @@ -276,15 +296,14 @@ pub fn build_nds(config: &NDSConfig, verbose: bool) { .arg("-7") .arg(config.path_arm7()) .arg("-b") - .arg(&config.icon) + .arg(&icon) .arg(banner_text); // If romfs directory exists, automatically include it let (romfs_path, is_default_romfs) = get_romfs_path(config); if romfs_path.is_dir() { eprintln!("Adding RomFS from {}", romfs_path.display()); - command.arg("-d") - .arg(&romfs_path); + command.arg("-d").arg(&romfs_path); } else if !is_default_romfs { eprintln!( "Could not find configured RomFS dir: {}", @@ -365,7 +384,6 @@ pub fn get_romfs_path(config: &NDSConfig) -> (PathBuf, bool) { (romfs_path, is_default) } - /// Read the `RomFS` path from the Cargo manifest. If it's unset, use the default. /// The returned boolean is true when the default is used. pub fn get_name(config: &NDSConfig) -> (PathBuf, bool) { @@ -396,38 +414,22 @@ pub fn get_name(config: &NDSConfig) -> (PathBuf, bool) { /// Read the `icon` path from the Cargo manifest. If it's unset, use the default. /// The returned boolean is true when the default is used. -pub fn get_icon_path(config: &NDSConfig) -> (PathBuf, bool) { +pub fn get_icon_path(config: &NDSConfig) -> PathBuf { let manifest_path = &config.cargo_manifest_path; - let manifest_str = std::fs::read_to_string(manifest_path) - .unwrap_or_else(|e| panic!("Could not open {}: {e}", manifest_path.display())); - let manifest_data: toml::Value = - toml::de::from_str(&manifest_str).expect("Could not parse Cargo manifest as TOML"); - // Find the icon setting and compute the path - let mut is_default = false; - - let icon_setting = manifest_data - .as_table() - .and_then(|table| table.get("package")) - .and_then(toml::Value::as_table) - .and_then(|table| table.get("metadata")) - .and_then(toml::Value::as_table) - .and_then(|table| table.get("nds")) - .and_then(toml::Value::as_table) - .and_then(|table| table.get("icon")) - .and_then(toml::Value::as_str) - .unwrap_or_else(|| { - is_default = true; - "/opt/wonderful/thirdparty/blocksds/core/sys/icon.bmp" - }); - let mut icon_path = manifest_path.clone(); - icon_path.pop(); // Pop Cargo.toml - icon_path.push(icon_setting); - - (icon_path, is_default) + let config = Config::try_load(config).expect("Failed to load nds.toml"); + match config.icon { + Some(icon) => { + let mut icon_path = manifest_path.clone(); + icon_path.pop(); // Pop Cargo.toml + icon_path.push(icon); + icon_path + } + None => "/opt/wonderful/thirdparty/blocksds/core/sys/icon.bmp".into(), + } } -#[derive(Default)] +#[derive(Default, Debug)] pub struct NDSConfig { name: String, author: String, @@ -442,15 +444,21 @@ impl NDSConfig { self.target_path.with_extension("").with_extension("nds") } pub fn path_arm9(&self) -> PathBuf { - self.target_path.with_extension("").with_extension("arm9.elf") + self.target_path + .with_extension("") + .with_extension("arm9.elf") } pub fn path_arm7(&self) -> PathBuf { - let arm7 =self.target_path.with_extension("").with_extension("arm7.elf"); + let arm7 = self + .target_path + .with_extension("") + .with_extension("arm7.elf"); if arm7.exists() { return arm7; } - let blocksds= env::var("BLOCKSDS").unwrap_or("/opt/wonderful/thirdparty/blocksds/core".to_owned()); - PathBuf::from(format!("{}/sys/default_arm7/arm7.elf",blocksds)) + let blocksds = + env::var("BLOCKSDS").unwrap_or("/opt/wonderful/thirdparty/blocksds/core".to_owned()); + PathBuf::from(format!("{}/sys/default_arm7/arm7.elf", blocksds)) } }