Browse Source

Support building examples, and misc improvements

* Now supports building examples with `--example <name>`.
* Now prints out each stage as it executes.
* Now uses the target dir found by `cargo metadata`, since it may not be
  in the current directory (ex. workspaces).
pull/5/head
AzureMarker 3 years ago
parent
commit
74cd2bc1f3
No known key found for this signature in database
GPG Key ID: 47A133F3BF9D03D3
  1. 102
      src/main.rs

102
src/main.rs

@ -1,4 +1,4 @@
use cargo_metadata::MetadataCommand; use cargo_metadata::{MetadataCommand, Package};
use rustc_version::{Channel, Version}; use rustc_version::{Channel, Version};
use std::path::Path; use std::path::Path;
use std::{ use std::{
@ -12,6 +12,7 @@ struct CTRConfig {
author: String, author: String,
description: String, description: String,
icon: String, icon: String,
target_path: String,
} }
#[derive(Ord, PartialOrd, PartialEq, Eq, Debug)] #[derive(Ord, PartialOrd, PartialEq, Eq, Debug)]
@ -57,7 +58,11 @@ fn main() {
// Skip `cargo 3ds` // Skip `cargo 3ds`
let mut args = env::args().skip(2); let mut args = env::args().skip(2);
// Get the command and collect the remaining arguments
let command = args.next(); let command = args.next();
let args: Vec<String> = args.collect();
let args: Vec<&str> = args.iter().map(String::as_str).collect();
let must_link = match command { let must_link = match command {
None => panic!("No command specified, try with \"build\" or \"link\""), None => panic!("No command specified, try with \"build\" or \"link\""),
Some(s) => match s.as_str() { Some(s) => match s.as_str() {
@ -67,13 +72,21 @@ fn main() {
}, },
}; };
build_elf(args); eprintln!("Building ELF");
build_elf(&args);
eprintln!("Getting metadata");
let app_conf = get_metadata(&args, &optimization_level);
let app_conf = get_metadata(); eprintln!("Building smdh");
build_3dsx(&app_conf, &optimization_level); build_smdh(&app_conf);
eprintln!("Building 3dsx");
build_3dsx(&app_conf);
if must_link { if must_link {
link(&app_conf.name, &optimization_level); eprintln!("Running 3dslink");
link(&app_conf);
} }
} }
@ -110,7 +123,7 @@ fn check_rust_version() {
} }
} }
fn build_elf(args: std::iter::Skip<env::Args>) { fn build_elf(args: &[&str]) {
let rustflags = format!("-L{}/libctru/lib -lctru ", env::var("DEVKITPRO").unwrap()); let rustflags = format!("-L{}/libctru/lib -lctru ", env::var("DEVKITPRO").unwrap());
let mut process = Command::new("cargo") let mut process = Command::new("cargo")
@ -134,12 +147,45 @@ fn build_elf(args: std::iter::Skip<env::Args>) {
} }
} }
fn get_metadata() -> CTRConfig { fn get_metadata(args: &[&str], opt_level: &str) -> CTRConfig {
let metadata = MetadataCommand::new() let metadata = MetadataCommand::new()
.exec() .exec()
.expect("Failed to get cargo metadata"); .expect("Failed to get cargo metadata");
let target_dir = &metadata.target_directory;
let root_crate = metadata.root_package().expect("No root crate found");
let package: &Package;
let binary_name: String;
let target_path: String;
// Check if we compiled the crate or an example
if let Some(example_pos) = args.iter().position(|arg| *arg == "--example") {
let example_name = *args.get(example_pos + 1).expect("No example given");
// Find the example's package
package = metadata
.packages
.iter()
.find(|pkg| {
pkg.targets.iter().any(|target| {
target.name == example_name && target.kind.iter().any(|kind| kind == "example")
})
})
.expect("Could not find package for example");
binary_name = format!("{} - {} example", example_name, package.name);
target_path = format!(
"{}/armv6k-nintendo-3ds/{}/examples/{}",
target_dir, opt_level, example_name
);
} else {
// Otherwise get the current/root crate
package = metadata.root_package().expect("No root crate found");
binary_name = package.name.clone();
target_path = format!(
"{}/armv6k-nintendo-3ds/{}/{}",
target_dir, opt_level, package.name
);
}
let mut icon = String::from("./icon.png"); let mut icon = String::from("./icon.png");
@ -151,27 +197,25 @@ fn get_metadata() -> CTRConfig {
} }
CTRConfig { CTRConfig {
name: root_crate.name.clone(), name: binary_name,
author: root_crate.authors[0].clone(), author: package.authors[0].clone(),
description: root_crate description: package
.description .description
.clone() .clone()
.unwrap_or_else(|| String::from("Homebrew Application")), .unwrap_or_else(|| String::from("Homebrew Application")),
icon, icon,
target_path,
} }
} }
fn build_3dsx(config: &CTRConfig, opt_lvl: &str) { fn build_smdh(config: &CTRConfig) {
let mut process = Command::new("smdhtool") let mut process = Command::new("smdhtool")
.arg("--create") .arg("--create")
.arg(&config.name) .arg(&config.name)
.arg(&config.description) .arg(&config.description)
.arg(&config.author) .arg(&config.author)
.arg(&config.icon) .arg(&config.icon)
.arg(format!( .arg(format!("{}.smdh", config.target_path))
"./target/armv6k-nintendo-3ds/{}/{}.smdh",
opt_lvl, config.name
))
.stdin(Stdio::inherit()) .stdin(Stdio::inherit())
.stdout(Stdio::inherit()) .stdout(Stdio::inherit())
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
@ -183,21 +227,14 @@ fn build_3dsx(config: &CTRConfig, opt_lvl: &str) {
if !status.success() { if !status.success() {
process::exit(status.code().unwrap_or(1)); process::exit(status.code().unwrap_or(1));
} }
}
fn build_3dsx(config: &CTRConfig) {
let mut command = Command::new("3dsxtool"); let mut command = Command::new("3dsxtool");
let mut process = command let mut process = command
.arg(format!( .arg(format!("{}.elf", config.target_path))
"./target/armv6k-nintendo-3ds/{}/{}.elf", .arg(format!("{}.3dsx", config.target_path))
opt_lvl, config.name .arg(format!("--smdh={}.smdh", config.target_path));
))
.arg(format!(
"./target/armv6k-nintendo-3ds/{}/{}.3dsx",
opt_lvl, config.name
))
.arg(format!(
"--smdh=./target/armv6k-nintendo-3ds/{}/{}.smdh",
opt_lvl, config.name
));
// If romfs directory exists, automatically include it // If romfs directory exists, automatically include it
if Path::new("./romfs").is_dir() { if Path::new("./romfs").is_dir() {
@ -218,12 +255,9 @@ fn build_3dsx(config: &CTRConfig, opt_lvl: &str) {
} }
} }
fn link(name: &str, opt_lvl: &str) { fn link(config: &CTRConfig) {
let mut process = Command::new("3dslink") let mut process = Command::new("3dslink")
.arg(format!( .arg(format!("{}.3dsx", config.target_path))
"./target/armv6k-nintendo-3ds/{}/{}.3dsx",
opt_lvl, name
))
.stdin(Stdio::inherit()) .stdin(Stdio::inherit())
.stdout(Stdio::inherit()) .stdout(Stdio::inherit())
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())

Loading…
Cancel
Save