Add nds.toml to configure icon and title

This commit is contained in:
not-jan 2025-02-03 19:44:00 +01:00
parent 2168b4204b
commit a090ea0020
3 changed files with 101 additions and 61 deletions

View File

@ -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<String> {
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<bool> = 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, .. }),
..

32
src/config.rs Normal file
View File

@ -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<String>; 3],
pub icon: Option<String>,
}
impl Config {
pub fn try_load(nds_config: &NDSConfig) -> std::io::Result<Self> {
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)
}
}

View File

@ -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<String>) -> (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<String>) -> 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::<Vec<String>>()
.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))
}
}