mirror of
https://github.com/SeleDreams/cargo-nds.git
synced 2025-06-18 11:05:36 -04:00
started work on migrating it to cargo-nds
This commit is contained in:
parent
af2d8bfd79
commit
d991297793
118
Cargo.lock
generated
118
Cargo.lock
generated
@ -66,7 +66,7 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo-3ds"
|
||||
name = "cargo-nds"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"cargo_metadata",
|
||||
@ -91,15 +91,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cargo_metadata"
|
||||
version = "0.14.2"
|
||||
version = "0.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
|
||||
checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"cargo-platform",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -149,6 +150,12 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.8"
|
||||
@ -159,12 +166,28 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.9"
|
||||
@ -184,19 +207,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.70"
|
||||
name = "memchr"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@ -269,6 +298,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.2.0"
|
||||
@ -283,9 +321,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.39"
|
||||
version = "2.0.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
||||
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -309,12 +347,57 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
name = "thiserror"
|
||||
version = "1.0.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||
checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -460,3 +543,12 @@ name = "windows_x86_64_msvc"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14b9415ee827af173ebb3f15f9083df5a122eb93572ec28741fb153356ea2578"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
14
Cargo.toml
14
Cargo.toml
@ -1,22 +1,22 @@
|
||||
[package]
|
||||
name = "cargo-3ds"
|
||||
name = "cargo-nds"
|
||||
version = "0.1.2"
|
||||
authors = ["Rust3DS Org", "Andrea Ciliberti <meziu210@icloud.com>"]
|
||||
description = "Cargo wrapper for developing Nintendo 3DS homebrew apps"
|
||||
repository = "https://github.com/rust3ds/cargo-3ds"
|
||||
keywords = ["3ds", "homebrew"]
|
||||
authors = ["Rustnds Org", "Andrea Ciliberti <meziu210@icloud.com>"]
|
||||
description = "Cargo wrapper for developing Nintendo nds homebrew apps"
|
||||
repository = "https://github.com/rustnds/cargo-nds"
|
||||
keywords = ["nds", "homebrew"]
|
||||
categories = ["command-line-utilities", "development-tools::cargo-plugins"]
|
||||
exclude = [".github"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
cargo_metadata = "0.14.0"
|
||||
cargo_metadata = "0.18.1"
|
||||
rustc_version = "0.4.0"
|
||||
semver = "1.0.10"
|
||||
serde = { version = "1.0.139", features = ["derive"] }
|
||||
tee = "0.1.0"
|
||||
toml = "0.5.6"
|
||||
toml = "0.8.12"
|
||||
clap = { version = "4.0.15", features = ["derive", "wrap_help"] }
|
||||
shlex = "1.1.0"
|
||||
serde_json = "1.0.108"
|
||||
|
145
src/command.rs
145
src/command.rs
@ -1,4 +1,4 @@
|
||||
use std::fs;
|
||||
use std::{env, fs};
|
||||
use std::io::Read;
|
||||
use std::process::Stdio;
|
||||
use std::sync::OnceLock;
|
||||
@ -6,12 +6,12 @@ use std::sync::OnceLock;
|
||||
use cargo_metadata::Message;
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
|
||||
use crate::{build_3dsx, build_smdh, cargo, get_metadata, link, print_command, CTRConfig};
|
||||
use crate::{build_nds, cargo, get_metadata, link, print_command, NDSConfig};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(name = "cargo", bin_name = "cargo")]
|
||||
pub enum Cargo {
|
||||
#[command(name = "3ds")]
|
||||
#[command(name = "nds")]
|
||||
Input(Input),
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ pub struct Input {
|
||||
#[command(subcommand)]
|
||||
pub cmd: CargoCmd,
|
||||
|
||||
/// Print the exact commands `cargo-3ds` is running. Note that this does not
|
||||
/// Print the exact commands `cargo-nds` is running. Note that this does not
|
||||
/// set the verbose flag for cargo itself. To set cargo's verbosity flag, add
|
||||
/// `-- -v` to the end of the command line.
|
||||
#[arg(long, short = 'v', global = true)]
|
||||
@ -34,32 +34,32 @@ pub struct Input {
|
||||
}
|
||||
|
||||
/// Run a cargo command. COMMAND will be forwarded to the real
|
||||
/// `cargo` with the appropriate arguments for the 3DS target.
|
||||
/// `cargo` with the appropriate arguments for the nds target.
|
||||
///
|
||||
/// If an unrecognized COMMAND is used, it will be passed through unmodified
|
||||
/// to `cargo` with the appropriate flags set for the 3DS target.
|
||||
/// to `cargo` with the appropriate flags set for the nds target.
|
||||
#[derive(Subcommand, Debug)]
|
||||
#[command(allow_external_subcommands = true)]
|
||||
pub enum CargoCmd {
|
||||
/// Builds an executable suitable to run on a 3DS (3dsx).
|
||||
/// Builds an executable suitable to run on a DS (nds).
|
||||
Build(Build),
|
||||
|
||||
/// Builds an executable and sends it to a device with `3dslink`.
|
||||
/// Builds an executable and sends it to a device with `dslink`.
|
||||
Run(Run),
|
||||
|
||||
/// Builds a test executable and sends it to a device with `3dslink`.
|
||||
/// Builds a test executable and sends it to a device with `dslink`.
|
||||
///
|
||||
/// This can be used with `--test` for integration tests, or `--lib` for
|
||||
/// unit tests (which require a custom test runner).
|
||||
Test(Test),
|
||||
|
||||
/// Sets up a new cargo project suitable to run on a 3DS.
|
||||
/// Sets up a new cargo project suitable to run on a DS.
|
||||
New(New),
|
||||
|
||||
// NOTE: it seems docstring + name for external subcommands are not rendered
|
||||
// in help, but we might as well set them here in case a future version of clap
|
||||
// does include them in help text.
|
||||
/// Run any other `cargo` command with custom building tailored for the 3DS.
|
||||
/// Run any other `cargo` command with custom building tailored for the nds.
|
||||
#[command(external_subcommand, name = "COMMAND")]
|
||||
Passthrough(Vec<String>),
|
||||
}
|
||||
@ -73,7 +73,7 @@ pub struct RemainingArgs {
|
||||
///
|
||||
/// To pass arguments to an executable being run, a *second* `--` must be
|
||||
/// used to disambiguate cargo arguments from executable arguments.
|
||||
/// For example, `cargo 3ds run -- -- xyz` runs an executable with the argument
|
||||
/// For example, `cargo nds run -- -- xyz` runs an executable with the argument
|
||||
/// `xyz`.
|
||||
#[arg(
|
||||
trailing_var_arg = true,
|
||||
@ -97,23 +97,23 @@ pub struct Build {
|
||||
pub struct Run {
|
||||
/// Specify the IP address of the device to send the executable to.
|
||||
///
|
||||
/// Corresponds to 3dslink's `--address` arg, which defaults to automatically
|
||||
/// Corresponds to ndslink's `--address` arg, which defaults to automatically
|
||||
/// finding the device.
|
||||
#[arg(long, short = 'a')]
|
||||
pub address: Option<std::net::Ipv4Addr>,
|
||||
|
||||
/// Set the 0th argument of the executable when running it. Corresponds to
|
||||
/// 3dslink's `--argv0` argument.
|
||||
/// ndslink's `--argv0` argument.
|
||||
#[arg(long, short = '0')]
|
||||
pub argv0: Option<String>,
|
||||
|
||||
/// Start the 3dslink server after sending the executable. Corresponds to
|
||||
/// 3dslink's `--server` argument.
|
||||
/// Start the ndslink server after sending the executable. Corresponds to
|
||||
/// ndslink's `--server` argument.
|
||||
#[arg(long, short = 's', default_value_t = false)]
|
||||
pub server: bool,
|
||||
|
||||
/// Set the number of tries when connecting to the device to send the executable.
|
||||
/// Corresponds to 3dslink's `--retries` argument.
|
||||
/// Corresponds to ndslink's `--retries` argument.
|
||||
// Can't use `short = 'r'` because that would conflict with cargo's `--release/-r`
|
||||
#[arg(long)]
|
||||
pub retries: Option<usize>,
|
||||
@ -133,7 +133,7 @@ pub struct Test {
|
||||
pub no_run: bool,
|
||||
|
||||
/// If set, documentation tests will be built instead of unit tests.
|
||||
/// This implies `--no-run`, unless Cargo's `target.armv6k-nintendo-3ds.runner`
|
||||
/// This implies `--no-run`, unless Cargo's `target.armv6k-nintendo-nds.runner`
|
||||
/// is configured.
|
||||
#[arg(long)]
|
||||
pub doc: bool,
|
||||
@ -158,7 +158,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) => {
|
||||
@ -172,7 +172,7 @@ impl CargoCmd {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the cargo subcommand run by `cargo-3ds` when handling a [`CargoCmd`].
|
||||
/// Returns the cargo subcommand run by `cargo-nds` when handling a [`CargoCmd`].
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
@ -203,13 +203,13 @@ impl CargoCmd {
|
||||
)
|
||||
}
|
||||
|
||||
/// Whether or not this command should build a 3DSX executable file.
|
||||
pub fn should_build_3dsx(&self) -> bool {
|
||||
/// Whether or not this command should build a ndsX executable file.
|
||||
pub fn should_build_ndsx(&self) -> bool {
|
||||
match self {
|
||||
Self::Build(_) | CargoCmd::Run(_) => true,
|
||||
&Self::Test(Test { doc, .. }) => {
|
||||
if doc {
|
||||
eprintln!("Documentation tests requested, no 3dsx will be built");
|
||||
eprintln!("Documentation tests requested, no ndsx will be built");
|
||||
false
|
||||
} else {
|
||||
true
|
||||
@ -219,8 +219,8 @@ impl CargoCmd {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether or not the resulting executable should be sent to the 3DS with
|
||||
/// `3dslink`.
|
||||
/// Whether or not the resulting executable should be sent to the nds with
|
||||
/// `ndslink`.
|
||||
pub fn should_link_to_device(&self) -> bool {
|
||||
match self {
|
||||
Self::Test(Test { no_run: true, .. }) => false,
|
||||
@ -247,7 +247,7 @@ impl CargoCmd {
|
||||
|
||||
if let Self::Test(Test { doc: true, .. }) = self {
|
||||
// We don't care about JSON output for doctests since we're not
|
||||
// building any 3dsx etc. Just use the default output as it's more
|
||||
// building any ndsx etc. Just use the default output as it's more
|
||||
// readable compared to DEFAULT_MESSAGE_FORMAT
|
||||
Ok(Some(String::from("human")))
|
||||
} else {
|
||||
@ -293,11 +293,11 @@ impl CargoCmd {
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// - `cargo 3ds build` and other "build" commands will use their callbacks to build the final `.3dsx` file and link it.
|
||||
/// - `cargo 3ds new` and other generic commands will use their callbacks to make 3ds-specific changes to the environment.
|
||||
/// - `cargo nds build` and other "build" commands will use their callbacks to build the final `.ndsx` file and link it.
|
||||
/// - `cargo nds new` and other generic commands will use their callbacks to make nds-specific changes to the environment.
|
||||
pub fn run_callback(&self, messages: &[Message]) {
|
||||
// Process the metadata only for commands that have it/use it
|
||||
let config = if self.should_build_3dsx() {
|
||||
let config = if self.should_build_ndsx() {
|
||||
eprintln!("Getting metadata");
|
||||
|
||||
Some(get_metadata(messages))
|
||||
@ -343,78 +343,45 @@ impl RemainingArgs {
|
||||
}
|
||||
|
||||
impl Build {
|
||||
/// Callback for `cargo 3ds build`.
|
||||
/// Callback for `cargo nds build`.
|
||||
///
|
||||
/// This callback handles building the application as a `.3dsx` file.
|
||||
fn callback(&self, config: &Option<CTRConfig>) {
|
||||
/// This callback handles building the application as a `.ndsx` file.
|
||||
fn callback(&self, config: &Option<NDSConfig>) {
|
||||
if let Some(config) = config {
|
||||
eprintln!("Building smdh: {}", config.path_smdh().display());
|
||||
build_smdh(config, self.verbose);
|
||||
|
||||
eprintln!("Building 3dsx: {}", config.path_3dsx().display());
|
||||
build_3dsx(config, self.verbose);
|
||||
eprintln!("Building nds: {}", config.path_nds().display());
|
||||
build_nds(config, self.verbose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Run {
|
||||
/// Get the args to pass to `3dslink` based on these options.
|
||||
pub fn get_3dslink_args(&self) -> Vec<String> {
|
||||
/// Get the args to pass to `ndslink` based on these options.
|
||||
pub fn get_dslink_args(&self) -> Vec<String> {
|
||||
let mut args = Vec::new();
|
||||
|
||||
if let Some(address) = self.address {
|
||||
args.extend(["--address".to_string(), address.to_string()]);
|
||||
}
|
||||
|
||||
if let Some(argv0) = &self.argv0 {
|
||||
args.extend(["--arg0".to_string(), argv0.clone()]);
|
||||
}
|
||||
|
||||
if let Some(retries) = self.retries {
|
||||
args.extend(["--retries".to_string(), retries.to_string()]);
|
||||
}
|
||||
|
||||
if self.server {
|
||||
args.push("--server".to_string());
|
||||
}
|
||||
|
||||
let exe_args = self.build_args.passthrough.exe_args();
|
||||
if !exe_args.is_empty() {
|
||||
// For some reason 3dslink seems to want 2 instances of `--`, one
|
||||
// in front of all of the args like this...
|
||||
args.extend(["--args".to_string(), "--".to_string()]);
|
||||
|
||||
let mut escaped = false;
|
||||
for arg in exe_args.iter().cloned() {
|
||||
if arg.starts_with('-') && !escaped {
|
||||
// And one before the first `-` arg that is passed in.
|
||||
args.extend(["--".to_string(), arg]);
|
||||
escaped = true;
|
||||
} else {
|
||||
args.push(arg);
|
||||
}
|
||||
}
|
||||
args.extend(["-a".to_string(), address.to_string()]);
|
||||
}
|
||||
|
||||
args
|
||||
}
|
||||
|
||||
/// Callback for `cargo 3ds run`.
|
||||
/// Callback for `cargo nds run`.
|
||||
///
|
||||
/// This callback handles launching the application via `3dslink`.
|
||||
fn callback(&self, config: &Option<CTRConfig>) {
|
||||
/// This callback handles launching the application via `dslink`.
|
||||
fn callback(&self, config: &Option<NDSConfig>) {
|
||||
// Run the normal "build" callback
|
||||
self.build_args.callback(config);
|
||||
|
||||
if !self.use_custom_runner() {
|
||||
if let Some(cfg) = config {
|
||||
eprintln!("Running 3dslink");
|
||||
eprintln!("Running dslink");
|
||||
link(cfg, self, self.build_args.verbose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether the cargo environment has `target.armv6k-nintendo-3ds.runner`
|
||||
/// Returns whether the cargo environment has `target.armv6k-nintendo-nds.runner`
|
||||
/// configured. This will only be checked once during the lifetime of the program,
|
||||
/// and takes into account the usual ways Cargo looks for its
|
||||
/// [configuration](https://doc.rust-lang.org/cargo/reference/config.html):
|
||||
@ -426,14 +393,16 @@ 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 mut cmd = cargo(&self.config);
|
||||
cmd.args([
|
||||
// https://github.com/rust-lang/cargo/issues/9301
|
||||
"-Z",
|
||||
"unstable-options",
|
||||
"config",
|
||||
"get",
|
||||
"target.armv6k-nintendo-3ds.runner",
|
||||
"build-std=core,alloc",
|
||||
"--target",
|
||||
"./armv5te-nintendo-ds.json"
|
||||
])
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null());
|
||||
@ -458,10 +427,10 @@ impl Run {
|
||||
}
|
||||
|
||||
impl Test {
|
||||
/// Callback for `cargo 3ds test`.
|
||||
/// Callback for `cargo nds test`.
|
||||
///
|
||||
/// This callback handles launching the application via `3dslink`.
|
||||
fn callback(&self, config: &Option<CTRConfig>) {
|
||||
/// This callback handles launching the application via `ndslink`.
|
||||
fn callback(&self, config: &Option<NDSConfig>) {
|
||||
if self.no_run {
|
||||
// If the tests don't have to run, use the "build" callback
|
||||
self.run_args.build_args.callback(config);
|
||||
@ -479,7 +448,7 @@ impl Test {
|
||||
fn cargo_args(&self) -> Vec<String> {
|
||||
let mut cargo_args = self.run_args.build_args.passthrough.cargo_args();
|
||||
|
||||
// We can't run 3DS executables on the host, but we want to respect
|
||||
// We can't run nds executables on the host, but we want to respect
|
||||
// the user's "runner" configuration if set.
|
||||
//
|
||||
// If doctests were requested, `--no-run` will be rejected on the
|
||||
@ -512,9 +481,9 @@ impl Test {
|
||||
}
|
||||
}
|
||||
|
||||
const TOML_CHANGES: &str = r#"ctru-rs = { git = "https://github.com/rust3ds/ctru-rs" }
|
||||
const TOML_CHANGES: &str = r#"ctru-rs = { git = "https://github.com/rustnds/ctru-rs" }
|
||||
|
||||
[package.metadata.cargo-3ds]
|
||||
[package.metadata.cargo-nds]
|
||||
romfs_dir = "romfs"
|
||||
"#;
|
||||
|
||||
@ -541,9 +510,9 @@ fn main() {
|
||||
"#;
|
||||
|
||||
impl New {
|
||||
/// Callback for `cargo 3ds new`.
|
||||
/// Callback for `cargo nds new`.
|
||||
///
|
||||
/// This callback handles the custom environment modifications when creating a new 3DS project.
|
||||
/// This callback handles the custom environment modifications when creating a new nds project.
|
||||
fn callback(&self) {
|
||||
// Commmit changes to the project only if is meant to be a binary
|
||||
if self.cargo_args.args.contains(&"--lib".to_string()) {
|
||||
@ -672,7 +641,7 @@ mod tests {
|
||||
expected_exe: &["bar"],
|
||||
},
|
||||
] {
|
||||
let input: Vec<&str> = ["cargo", "3ds", "run"]
|
||||
let input: Vec<&str> = ["cargo", "nds", "run"]
|
||||
.iter()
|
||||
.chain(param.input)
|
||||
.copied()
|
||||
|
173
src/lib.rs
173
src/lib.rs
@ -21,7 +21,7 @@ use crate::graph::UnitGraph;
|
||||
/// parsing and returning the messages from the spawned process.
|
||||
///
|
||||
/// For commands that produce an executable output, this function will build the
|
||||
/// `.elf` binary that can be used to create other 3ds files.
|
||||
/// `.elf` binary that can be used to create other nds files.
|
||||
pub fn run_cargo(input: &Input, message_format: Option<String>) -> (ExitStatus, Vec<Message>) {
|
||||
let mut command = make_cargo_command(input, &message_format);
|
||||
|
||||
@ -57,7 +57,7 @@ pub fn run_cargo(input: &Input, message_format: Option<String>) -> (ExitStatus,
|
||||
let buf_reader: &mut dyn BufRead = match (message_format, &input.cmd) {
|
||||
// The user presumably cares about the message format if set, so we should
|
||||
// copy stuff to stdout like they expect. We can still extract the executable
|
||||
// information out of it that we need for 3dsxtool etc.
|
||||
// information out of it that we need for ndstool etc.
|
||||
(Some(_), _) |
|
||||
// Rustdoc unfortunately prints to stdout for compile errors, so
|
||||
// we also use a tee when building doc tests too.
|
||||
@ -104,14 +104,11 @@ fn should_use_ctru_debuginfo(cargo_cmd: &Command, verbose: bool) -> bool {
|
||||
|
||||
/// Create a cargo command based on the context.
|
||||
///
|
||||
/// For "build" commands (which compile code, such as `cargo 3ds build` or `cargo 3ds clippy`),
|
||||
/// 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 devkitpro =
|
||||
env::var("DEVKITPRO").expect("DEVKITPRO is not defined as an environment variable");
|
||||
// TODO: should we actually prepend the user's RUSTFLAGS for linking order? not sure
|
||||
let rustflags =
|
||||
env::var("RUSTFLAGS").unwrap_or_default() + &format!(" -L{devkitpro}/libctru/lib");
|
||||
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;
|
||||
|
||||
@ -125,21 +122,15 @@ pub fn make_cargo_command(input: &Input, message_format: &Option<String>) -> Com
|
||||
if cargo_cmd.should_compile() {
|
||||
command
|
||||
.arg("--target")
|
||||
.arg("armv6k-nintendo-3ds")
|
||||
.arg("armv5te-nintendo-ds.json")
|
||||
.arg("-Z")
|
||||
.arg("build-std=core,alloc")
|
||||
.arg("--message-format")
|
||||
.arg(
|
||||
message_format
|
||||
.as_deref()
|
||||
.unwrap_or(CargoCmd::DEFAULT_MESSAGE_FORMAT),
|
||||
);
|
||||
|
||||
let sysroot = find_sysroot();
|
||||
if !sysroot.join("lib/rustlib/armv6k-nintendo-3ds").exists() {
|
||||
eprintln!("No pre-build std found, using build-std");
|
||||
// Always building the test crate is not ideal, but we don't know if the
|
||||
// crate being built uses #![feature(test)], so we build it just in case.
|
||||
command.arg("-Z").arg("build-std=std,test");
|
||||
}
|
||||
}
|
||||
|
||||
if let CargoCmd::Test(test) = cargo_cmd {
|
||||
@ -212,10 +203,10 @@ pub fn check_rust_version() {
|
||||
let rustc_version = rustc_version::version_meta().unwrap();
|
||||
|
||||
if rustc_version.channel > Channel::Nightly {
|
||||
eprintln!("cargo-3ds requires a nightly rustc version.");
|
||||
eprintln!("cargo-nds requires a nightly rustc version.");
|
||||
eprintln!(
|
||||
"Please run `rustup override set nightly` to use nightly in the \
|
||||
current directory, or use `cargo +nightly 3ds` to use it for a \
|
||||
current directory, or use `cargo +nightly nds` to use it for a \
|
||||
single invocation."
|
||||
);
|
||||
process::exit(1);
|
||||
@ -237,17 +228,17 @@ pub fn check_rust_version() {
|
||||
};
|
||||
|
||||
if old_version || old_commit {
|
||||
eprintln!("cargo-3ds requires rustc nightly version >= {MINIMUM_COMMIT_DATE}");
|
||||
eprintln!("cargo-nds requires rustc nightly version >= {MINIMUM_COMMIT_DATE}");
|
||||
eprintln!("Please run `rustup update nightly` to upgrade your nightly version");
|
||||
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses messages returned by "build" cargo commands (such as `cargo 3ds build` or `cargo 3ds run`).
|
||||
/// Parses messages returned by "build" cargo commands (such as `cargo nds build` or `cargo nds run`).
|
||||
/// The returned [`CTRConfig`] is then used for further building in and execution
|
||||
/// in [`build_smdh`], [`build_3dsx`], and [`link`].
|
||||
pub fn get_metadata(messages: &[Message]) -> CTRConfig {
|
||||
/// in [`build_nds`], and [`link`].
|
||||
pub fn get_metadata(messages: &[Message]) -> NDSConfig {
|
||||
let metadata = MetadataCommand::new()
|
||||
.no_deps()
|
||||
.exec()
|
||||
@ -275,12 +266,12 @@ pub fn get_metadata(messages: &[Message]) -> CTRConfig {
|
||||
|
||||
let (package, artifact) = (package.unwrap(), artifact.unwrap());
|
||||
|
||||
let mut icon = String::from("./icon.png");
|
||||
let mut icon = String::from("./icon.bmp");
|
||||
|
||||
if !Path::new(&icon).exists() {
|
||||
icon = format!(
|
||||
"{}/libctru/default_icon.png",
|
||||
env::var("DEVKITPRO").unwrap()
|
||||
"{}/sys/icon.bmp",
|
||||
env::var("BLOCKSDS").unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
@ -300,63 +291,41 @@ pub fn get_metadata(messages: &[Message]) -> CTRConfig {
|
||||
[] => String::from("Unspecified Author"), // as standard with the devkitPRO toolchain
|
||||
};
|
||||
|
||||
CTRConfig {
|
||||
NDSConfig {
|
||||
name,
|
||||
author,
|
||||
description: package
|
||||
.description
|
||||
.clone()
|
||||
.unwrap_or_else(|| String::from("Homebrew Application")),
|
||||
icon,
|
||||
icon : icon,
|
||||
target_path: artifact.executable.unwrap().into(),
|
||||
cargo_manifest_path: package.manifest_path.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds the smdh using `smdhtool`.
|
||||
/// This will fail if `smdhtool` is not within the running directory or in a directory found in $PATH
|
||||
pub fn build_smdh(config: &CTRConfig, verbose: bool) {
|
||||
let mut command = Command::new("smdhtool");
|
||||
/// Builds the nds using `ndstool`.
|
||||
/// This will fail if `ndstool` is not within the running directory or in a directory found in $PATH
|
||||
pub fn build_nds(config: &NDSConfig, verbose: bool) {
|
||||
let mut command = Command::new("ndstool");
|
||||
let banner_text = format!("\"{};{};{}\"", &config.name, &config.description, &config.author);
|
||||
command
|
||||
.arg("--create")
|
||||
.arg(&config.name)
|
||||
.arg(&config.description)
|
||||
.arg(&config.author)
|
||||
.arg("-c")
|
||||
.arg(config.path_nds())
|
||||
.arg("-9")
|
||||
.arg(config.path_arm9())
|
||||
.arg("-7")
|
||||
.arg(config.path_arm7())
|
||||
.arg("-b")
|
||||
.arg(&config.icon)
|
||||
.arg(config.path_smdh())
|
||||
.stdin(Stdio::inherit())
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit());
|
||||
|
||||
if verbose {
|
||||
print_command(&command);
|
||||
}
|
||||
|
||||
let mut process = command
|
||||
.spawn()
|
||||
.expect("smdhtool command failed, most likely due to 'smdhtool' not being in $PATH");
|
||||
|
||||
let status = process.wait().unwrap();
|
||||
|
||||
if !status.success() {
|
||||
process::exit(status.code().unwrap_or(1));
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds the 3dsx using `3dsxtool`.
|
||||
/// This will fail if `3dsxtool` is not within the running directory or in a directory found in $PATH
|
||||
pub fn build_3dsx(config: &CTRConfig, verbose: bool) {
|
||||
let mut command = Command::new("3dsxtool");
|
||||
command
|
||||
.arg(&config.target_path)
|
||||
.arg(config.path_3dsx())
|
||||
.arg(format!("--smdh={}", config.path_smdh().to_string_lossy()));
|
||||
.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(format!("--romfs={}", romfs_path.to_string_lossy()));
|
||||
command.arg("-d")
|
||||
.arg(&romfs_path);
|
||||
} else if !is_default_romfs {
|
||||
eprintln!(
|
||||
"Could not find configured RomFS dir: {}",
|
||||
@ -374,7 +343,7 @@ pub fn build_3dsx(config: &CTRConfig, verbose: bool) {
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.spawn()
|
||||
.expect("3dsxtool command failed, most likely due to '3dsxtool' not being in $PATH");
|
||||
.expect("ndstool command failed, most likely due to 'ndstool' not being in $PATH");
|
||||
|
||||
let status = process.wait().unwrap();
|
||||
|
||||
@ -383,13 +352,13 @@ pub fn build_3dsx(config: &CTRConfig, verbose: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Link the generated 3dsx to a 3ds to execute and test using `3dslink`.
|
||||
/// This will fail if `3dslink` is not within the running directory or in a directory found in $PATH
|
||||
pub fn link(config: &CTRConfig, run_args: &Run, verbose: bool) {
|
||||
let mut command = Command::new("3dslink");
|
||||
/// Link the generated nds to a ds to execute and test using `dslink`.
|
||||
/// This will fail if `dslink` is not within the running directory or in a directory found in $PATH
|
||||
pub fn link(config: &NDSConfig, run_args: &Run, verbose: bool) {
|
||||
let mut command = Command::new("dslink");
|
||||
command
|
||||
.arg(config.path_3dsx())
|
||||
.args(run_args.get_3dslink_args())
|
||||
.args(run_args.get_dslink_args())
|
||||
.arg(config.path_nds())
|
||||
.stdin(Stdio::inherit())
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit());
|
||||
@ -407,7 +376,7 @@ pub fn link(config: &CTRConfig, run_args: &Run, verbose: bool) {
|
||||
|
||||
/// 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_romfs_path(config: &CTRConfig) -> (PathBuf, bool) {
|
||||
pub fn get_romfs_path(config: &NDSConfig) -> (PathBuf, bool) {
|
||||
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()));
|
||||
@ -422,9 +391,9 @@ pub fn get_romfs_path(config: &CTRConfig) -> (PathBuf, bool) {
|
||||
.and_then(toml::Value::as_table)
|
||||
.and_then(|table| table.get("metadata"))
|
||||
.and_then(toml::Value::as_table)
|
||||
.and_then(|table| table.get("cargo-3ds"))
|
||||
.and_then(|table| table.get("nds"))
|
||||
.and_then(toml::Value::as_table)
|
||||
.and_then(|table| table.get("romfs_dir"))
|
||||
.and_then(|table| table.get("romfs"))
|
||||
.and_then(toml::Value::as_str)
|
||||
.unwrap_or_else(|| {
|
||||
is_default = true;
|
||||
@ -437,8 +406,41 @@ pub fn get_romfs_path(config: &CTRConfig) -> (PathBuf, bool) {
|
||||
(romfs_path, is_default)
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
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)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CTRConfig {
|
||||
pub struct NDSConfig {
|
||||
name: String,
|
||||
author: String,
|
||||
description: String,
|
||||
@ -447,13 +449,20 @@ pub struct CTRConfig {
|
||||
cargo_manifest_path: PathBuf,
|
||||
}
|
||||
|
||||
impl CTRConfig {
|
||||
pub fn path_3dsx(&self) -> PathBuf {
|
||||
self.target_path.with_extension("3dsx")
|
||||
impl NDSConfig {
|
||||
pub fn path_nds(&self) -> PathBuf {
|
||||
self.target_path.with_extension("nds")
|
||||
}
|
||||
|
||||
pub fn path_smdh(&self) -> PathBuf {
|
||||
self.target_path.with_extension("smdh")
|
||||
pub fn path_arm9(&self) -> PathBuf {
|
||||
self.target_path.with_extension("arm9.elf")
|
||||
}
|
||||
pub fn path_arm7(&self) -> PathBuf {
|
||||
let arm7 =self.target_path.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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
use std::process;
|
||||
use std::{env, process};
|
||||
|
||||
use cargo_3ds::command::Cargo;
|
||||
use cargo_3ds::{check_rust_version, run_cargo};
|
||||
use cargo_nds::command::Cargo;
|
||||
use cargo_nds::{check_rust_version, run_cargo};
|
||||
use clap::Parser;
|
||||
|
||||
fn main() {
|
||||
check_rust_version();
|
||||
|
||||
let Cargo::Input(mut input) = Cargo::parse();
|
||||
|
||||
let message_format = match input.cmd.extract_message_format() {
|
||||
|
Loading…
Reference in New Issue
Block a user