support building/exporting multiple targets

This commit is contained in:
Michael Angelo Calimlim 2023-10-31 20:06:53 +08:00
parent f637bf73e8
commit 5dbe0c5490
5 changed files with 398 additions and 71 deletions

View file

@ -20,6 +20,7 @@ colored = "2.0.4"
command-macros = "0.2.9"
fs_extra = "1.3.0"
kstring = "2.0.0"
itertools = "0.11.0"
liquid = { version = "0.26.4", default-features = false, features = [ "stdlib" ] }
liquid-core = { version = "0.26.4", default-features = false }
nanoid = "0.4.0"

View file

@ -21,6 +21,7 @@ use regex::Regex;
use std::fs::{create_dir_all, read_dir, write, File, OpenOptions};
use std::io::prelude::*;
use std::path::Path;
use std::{thread, time};
use strum::IntoEnumIterator;
use voca_rs::Voca;
use walkdir::WalkDir;
@ -43,11 +44,11 @@ pub enum FtwCommand {
machine_type: FtwMachineType,
},
Build {
target: FtwTarget,
targets: Vec<FtwTarget>,
build_type: FtwBuildType,
},
Export {
target: FtwTarget,
targets: Vec<FtwTarget>,
build_type: FtwBuildType,
},
Clean,
@ -415,18 +416,23 @@ impl Processor for FtwCommand {
FtwCommand::run_with_godot(machine_type)?;
Ok(FtwSuccess::Run { machine_type })
}
FtwCommand::Build { target, build_type } => {
FtwCommand::Build { targets, build_type } => {
FtwCommand::is_valid_project()?;
FtwCommand::clean()?;
FtwCommand::build_lib(*target, *build_type)?;
Ok(FtwSuccess::Build { target, build_type })
for target in targets {
FtwCommand::build_lib(*target, *build_type)?;
thread::sleep(time::Duration::from_millis(100));
}
Ok(FtwSuccess::Build { targets, build_type })
}
FtwCommand::Export { target, build_type } => {
FtwCommand::Export { targets, build_type } => {
FtwCommand::is_valid_project()?;
FtwCommand::clean()?;
FtwCommand::build_lib(*target, *build_type)?;
FtwCommand::export_game(*target, *build_type)?;
Ok(FtwSuccess::Export { target, build_type })
for target in targets {
FtwCommand::build_lib(*target, *build_type)?;
FtwCommand::export_game(*target, *build_type)?;
}
Ok(FtwSuccess::Export { targets, build_type })
}
FtwCommand::Clean => {
FtwCommand::clean()?;
@ -755,9 +761,10 @@ mod ftw_command_tests {
};
let _ = cmd.process();
let _ = env::set_current_dir(Path::new(&project.get_name()));
let target: FtwTarget = util::get_current_platform().parse().unwrap();
let target = util::get_current_platform().parse().unwrap();
let targets = vec![target];
let cmd = FtwCommand::Build {
target: target.clone(),
targets,
build_type: FtwBuildType::Debug,
};
let _ = cmd.process();
@ -791,9 +798,10 @@ enable-cross-compilation=true
.read(".ftw")
.contains("enable-cross-compilation=true"));
let _ = env::set_current_dir(Path::new(&project.get_name()));
let target: FtwTarget = FtwTarget::LinuxX86_64;
let target = FtwTarget::LinuxX86_64;
let targets = vec![target];
let cmd = FtwCommand::Build {
target: target.clone(),
targets,
build_type: FtwBuildType::Debug,
};
let _ = cmd.process();
@ -812,6 +820,51 @@ enable-cross-compilation=true
)));
}
#[test]
fn test_process_ftw_command_cross_build_multi_target() {
let project = Project::new();
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let contents = r#"[ftw]
enable-cross-compilation=true
"#;
let _ = project.create(".ftw", contents);
assert!(project
.read(".ftw")
.contains("enable-cross-compilation=true"));
let _ = env::set_current_dir(Path::new(&project.get_name()));
let targets = vec![
FtwTarget::AndroidLinuxX86_64,
FtwTarget::MacOsX86_64,
FtwTarget::LinuxX86_64,
FtwTarget::WindowsX86_64Gnu,
];
let cmd = FtwCommand::Build {
targets: targets.clone(),
build_type: FtwBuildType::Debug,
};
let _ = cmd.process();
let cmd = FtwCommand::Clean;
let _ = cmd.process();
let _ = env::set_current_dir(Path::new("../"));
assert!(project
.read("rust/Cargo.toml")
.contains(&project.get_name()));
for target in targets {
let target_cli_arg = target.to_cli_arg();
let target_lib_prefix = target.to_lib_prefix();
let project_name = project.get_name();
let target_lib_ext = target.to_lib_ext();
assert!(project.exists(&format!(
"lib/{target_cli_arg}/{target_lib_prefix}{project_name}.{target_lib_ext}"
)));
}
}
#[test]
fn test_process_ftw_command_cross_build_windows_target() {
let project = Project::new();
@ -829,9 +882,10 @@ enable-cross-compilation=true
.read(".ftw")
.contains("enable-cross-compilation=true"));
let _ = env::set_current_dir(Path::new(&project.get_name()));
let target: FtwTarget = FtwTarget::WindowsX86_64Gnu;
let target = FtwTarget::WindowsX86_64Gnu;
let targets = vec![target];
let cmd = FtwCommand::Build {
target: target.clone(),
targets,
build_type: FtwBuildType::Debug,
};
let _ = cmd.process();
@ -867,9 +921,10 @@ enable-cross-compilation=true
.read(".ftw")
.contains("enable-cross-compilation=true"));
let _ = env::set_current_dir(Path::new(&project.get_name()));
let target: FtwTarget = FtwTarget::MacOsX86_64;
let target = FtwTarget::MacOsX86_64;
let targets = vec![target];
let cmd = FtwCommand::Build {
target: target.clone(),
targets,
build_type: FtwBuildType::Debug,
};
let _ = cmd.process();
@ -905,9 +960,10 @@ enable-cross-compilation=true
.read(".ftw")
.contains("enable-cross-compilation=true"));
let _ = env::set_current_dir(Path::new(&project.get_name()));
let target: FtwTarget = FtwTarget::AndroidLinuxAarch64;
let target = FtwTarget::AndroidLinuxAarch64;
let targets = vec![target];
let cmd = FtwCommand::Build {
target: target.clone(),
targets,
build_type: FtwBuildType::Debug,
};
let _ = cmd.process();
@ -943,9 +999,10 @@ enable-cross-compilation=true
.read(".ftw")
.contains("enable-cross-compilation=true"));
let _ = env::set_current_dir(Path::new(&project.get_name()));
let target: FtwTarget = FtwTarget::IosAarch64;
let target = FtwTarget::IosAarch64;
let targets = vec![target];
let cmd = FtwCommand::Build {
target: target.clone(),
targets,
build_type: FtwBuildType::Debug,
};
let _ = cmd.process();
@ -974,9 +1031,10 @@ enable-cross-compilation=true
};
let _ = cmd.process();
let _ = env::set_current_dir(Path::new(&project.get_name()));
let target: FtwTarget = util::get_current_platform().parse().unwrap();
let target = util::get_current_platform().parse().unwrap();
let targets = vec![target];
let cmd = FtwCommand::Build {
target: target.clone(),
targets,
build_type: FtwBuildType::Debug,
};
let _ = cmd.process();
@ -1004,9 +1062,10 @@ enable-cross-compilation=true
};
let _ = cmd.process();
let _ = env::set_current_dir(Path::new(&project.get_name()));
let target: FtwTarget = util::get_current_platform().parse().unwrap();
let target = util::get_current_platform().parse().unwrap();
let targets = vec![target];
let cmd = FtwCommand::Build {
target: target.clone(),
targets,
build_type: FtwBuildType::Release,
};
let _ = cmd.process();
@ -1033,9 +1092,10 @@ enable-cross-compilation=true
};
let _ = cmd.process();
let _ = env::set_current_dir(Path::new(&project.get_name()));
let target: FtwTarget = util::get_current_platform().parse().unwrap();
let target = util::get_current_platform().parse().unwrap();
let targets = vec![target];
let cmd = FtwCommand::Export {
target: target.clone(),
targets,
build_type: FtwBuildType::Debug,
};
let _ = cmd.process();
@ -1076,9 +1136,10 @@ enable-cross-compilation=true
.read(".ftw")
.contains("enable-cross-compilation=true"));
let _ = env::set_current_dir(Path::new(&project.get_name()));
let target: FtwTarget = FtwTarget::LinuxX86_64;
let target = FtwTarget::LinuxX86_64;
let targets = vec![target];
let cmd = FtwCommand::Export {
target: target.clone(),
targets,
build_type: FtwBuildType::Debug,
};
let _ = cmd.process();
@ -1104,6 +1165,59 @@ enable-cross-compilation=true
)));
}
#[test]
fn test_process_ftw_command_cross_export_multi_target() {
let project = Project::new();
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let contents = r#"[ftw]
enable-cross-compilation=true
"#;
let _ = project.create(".ftw", contents);
assert!(project
.read(".ftw")
.contains("enable-cross-compilation=true"));
let _ = env::set_current_dir(Path::new(&project.get_name()));
let targets = vec![
FtwTarget::LinuxX86_64,
FtwTarget::MacOsX86_64,
FtwTarget::WindowsX86_64Gnu,
];
let cmd = FtwCommand::Export {
targets: targets.clone(),
build_type: FtwBuildType::Debug,
};
let _ = cmd.process();
let cmd = FtwCommand::Clean;
let _ = cmd.process();
let _ = env::set_current_dir(Path::new("../"));
assert!(project
.read("rust/Cargo.toml")
.contains(&project.get_name()));
for target in targets {
let target_cli_arg = target.to_cli_arg();
let target_lib_prefix = target.to_lib_prefix();
let project_name = project.get_name();
let target_lib_ext = target.to_lib_ext();
let target_app_ext = target.to_app_ext();
if target == FtwTarget::LinuxX86_64 {
assert!(project.exists(&format!(
"bin/{target_cli_arg}/{target_lib_prefix}{project_name}.{target_lib_ext}"
)));
assert!(project.exists(&format!(
"bin/{target_cli_arg}/{project_name}.debug.{target_cli_arg}.pck"
)));
}
assert!(project.exists(&format!(
"bin/{target_cli_arg}/{project_name}.debug.{target_cli_arg}{target_app_ext}"
)));
}
}
#[test]
fn test_process_ftw_command_cross_export_macos_target() {
let project = Project::new();
@ -1121,9 +1235,10 @@ enable-cross-compilation=true
.read(".ftw")
.contains("enable-cross-compilation=true"));
let _ = env::set_current_dir(Path::new(&project.get_name()));
let target: FtwTarget = FtwTarget::MacOsX86_64;
let target = FtwTarget::MacOsX86_64;
let targets = vec![target];
let cmd = FtwCommand::Export {
target: target.clone(),
targets,
build_type: FtwBuildType::Debug,
};
let _ = cmd.process();

View file

@ -26,11 +26,11 @@ pub enum FtwSuccess<'a> {
machine_type: &'a FtwMachineType,
},
Build {
target: &'a FtwTarget,
targets: &'a Vec<FtwTarget>,
build_type: &'a FtwBuildType,
},
Export {
target: &'a FtwTarget,
targets: &'a Vec<FtwTarget>,
build_type: &'a FtwBuildType,
},
Clean,
@ -75,18 +75,32 @@ impl ToMessage for FtwSuccess<'_> {
let styled_machine_type = machine_type.to_string().blue().bold().italic();
format!("The game was run as a {styled_machine_type} application")
}
FtwSuccess::Build { target, build_type } => {
let styled_target = target.to_string().blue().bold().italic();
let styled_build_type = build_type.to_string().blue().bold().italic();
format!("A library was created at lib/{styled_target} with a {styled_build_type} profile")
}
FtwSuccess::Export { target, build_type } => {
let styled_target = target.to_string().blue().bold().italic();
FtwSuccess::Build {
targets,
build_type,
} => {
let targets: Vec<String> = targets
.iter()
.map(|target| format!("lib/{target}"))
.collect();
let styled_targets = targets.join(",").blue().bold().italic();
let styled_build_type = build_type.to_string().blue().bold().italic();
format!(
"A game was created at bin/{styled_target} with a {styled_build_type} profile"
"A library was created at {styled_targets} with a {styled_build_type} profile"
)
}
FtwSuccess::Export {
targets,
build_type,
} => {
let targets: Vec<String> = targets
.iter()
.map(|target| format!("bin/{target}"))
.collect();
let styled_target = targets.join(",").blue().bold().italic();
let styled_build_type = build_type.to_string().blue().bold().italic();
format!("A game was created at {styled_target} with a {styled_build_type} profile")
}
FtwSuccess::Clean => "The project is now clean from excess artifacts".to_string(),
};
let thumbs_up = FtwSuccess::THUMBS_UP;
@ -167,48 +181,52 @@ mod ftw_success_tests {
);
//
let target = FtwTarget::LinuxX86_64;
let targets = vec![target];
let debug = FtwBuildType::Debug;
let ftw_success_build_debug_message = FtwSuccess::Build {
target: &target,
targets: &targets,
build_type: &debug,
}
.to_message();
let styled_target = target.to_string().blue().bold().italic();
let styled_target = format!("lib/{target}").blue().bold().italic();
let styled_debug = debug.to_string().blue().bold().italic();
assert_eq!(
format!("{thumbs_up} {styled_success} A library was created at lib/{styled_target} with a {styled_debug} profile"),
format!("{thumbs_up} {styled_success} A library was created at {styled_target} with a {styled_debug} profile"),
format!("{ftw_success_build_debug_message}")
);
//
let release = FtwBuildType::Release;
let ftw_success_build_release_message = FtwSuccess::Build {
target: &target,
targets: &targets,
build_type: &release,
}
.to_message();
let styled_release = release.to_string().blue().bold().italic();
assert_eq!(
format!("{thumbs_up} {styled_success} A library was created at lib/{styled_target} with a {styled_release} profile"),
format!("{thumbs_up} {styled_success} A library was created at {styled_target} with a {styled_release} profile"),
format!("{ftw_success_build_release_message}")
);
//
let target = FtwTarget::LinuxX86_64;
let targets = vec![target];
let ftw_success_export_debug_message = FtwSuccess::Export {
target: &target,
targets: &targets,
build_type: &debug,
}
.to_message();
let styled_target = format!("bin/{target}").blue().bold().italic();
assert_eq!(
format!("{thumbs_up} {styled_success} A game was created at bin/{styled_target} with a {styled_debug} profile"),
format!("{thumbs_up} {styled_success} A game was created at {styled_target} with a {styled_debug} profile"),
format!("{ftw_success_export_debug_message}")
);
//
let ftw_success_export_release_message = FtwSuccess::Export {
target: &target,
targets: &targets,
build_type: &release,
}
.to_message();
assert_eq!(
format!("{thumbs_up} {styled_success} A game was created at bin/{styled_target} with a {styled_release} profile"),
format!("{thumbs_up} {styled_success} A game was created at {styled_target} with a {styled_release} profile"),
format!("{ftw_success_export_release_message}")
);
//

View file

@ -6,7 +6,7 @@ use std::fmt::{Display, Formatter};
use std::str::FromStr;
use strum_macros::EnumIter;
#[derive(Clone, Copy, Default, Debug, EnumIter, Eq, PartialEq)]
#[derive(Clone, Copy, Default, Debug, EnumIter, Eq, Ord, PartialOrd, PartialEq)]
pub enum FtwTarget {
AndroidLinuxAarch64,
AndroidLinuxArmV7,

View file

@ -18,10 +18,10 @@ mod util;
use crate::ftw_command::FtwCommand;
use crate::ftw_tag::FtwTag;
use crate::traits::{Processor, ToMessage};
use clap::{
arg, command, crate_authors, crate_description, crate_name, crate_version, ArgMatches, Command,
};
use itertools::Itertools;
use std::env;
#[cfg(not(tarpaulin_include))]
@ -65,13 +65,13 @@ fn get_clap_command() -> Command {
.subcommand(
Command::new("build")
.about("build the library for a particular platform")
.arg(arg!([target] "target platform to build"))
.arg(arg!([targets] "target platforms to build, separated by ','"))
.arg(arg!([build_type] "either a debug or release")),
)
.subcommand(
Command::new("export")
.about("export the game for a particular platform")
.arg(arg!([target] "target platform to export"))
.arg(arg!([targets] "target platform to export"))
.arg(arg!([build_type] "either a debug or release")),
)
.subcommand(Command::new("clean").about("cleans the project from excess artifacts"))
@ -132,31 +132,43 @@ fn parse_matches(matches: &ArgMatches) -> FtwCommand {
}
Some(("build", args)) => {
let current_platform = util::get_current_platform();
let target = args
.get_one::<String>("target")
let targets = args
.get_one("targets")
.unwrap_or(&current_platform)
.parse()
.unwrap_or_default();
.split(',')
.map(|t| t.parse().unwrap_or_default())
.sorted()
.dedup()
.collect();
let build_type = args
.get_one::<String>("build_type")
.unwrap_or(&String::from("debug"))
.parse()
.unwrap_or_default();
FtwCommand::Build { target, build_type }
FtwCommand::Build {
targets,
build_type,
}
}
Some(("export", args)) => {
let current_platform = util::get_current_platform();
let target = args
.get_one::<String>("target")
let targets = args
.get_one("targets")
.unwrap_or(&current_platform)
.parse()
.unwrap_or_default();
.split(',')
.map(|t| t.parse().unwrap_or_default())
.sorted()
.dedup()
.collect();
let build_type = args
.get_one::<String>("build_type")
.unwrap_or(&String::from("debug"))
.parse()
.unwrap_or_default();
FtwCommand::Export { target, build_type }
FtwCommand::Export {
targets,
build_type,
}
}
Some(("clean", _args)) => FtwCommand::Clean,
_ => unreachable!(),
@ -306,7 +318,98 @@ mod main_tests {
let matches = app.get_matches_from(args);
let command = parse_matches(&matches);
let cmd = FtwCommand::Build {
target: FtwTarget::LinuxX86_64,
targets: vec![FtwTarget::LinuxX86_64],
build_type: FtwBuildType::Debug,
};
assert_eq!(command, cmd);
}
#[test]
fn test_parse_matches_multi_build() {
let app = get_clap_command();
let args = [
crate_name!(),
"build",
"linux-x86_64,windows-x86_64,macos-x86_64,android-x86_64",
"debug",
];
let matches = app.get_matches_from(args);
let command = parse_matches(&matches);
let cmd = FtwCommand::Build {
targets: vec![
FtwTarget::AndroidLinuxX86_64,
FtwTarget::LinuxX86_64,
FtwTarget::MacOsX86_64,
FtwTarget::WindowsX86_64Msvc,
],
build_type: FtwBuildType::Debug,
};
assert_eq!(command, cmd);
}
#[test]
fn test_parse_matches_multi_build_with_blank() {
let app = get_clap_command();
let args = [
crate_name!(),
"build",
",windows-x86_64,macos-x86_64,android-x86_64",
"debug",
];
let matches = app.get_matches_from(args);
let command = parse_matches(&matches);
let cmd = FtwCommand::Build {
targets: vec![
FtwTarget::AndroidLinuxX86_64,
FtwTarget::MacOsX86_64,
FtwTarget::WindowsX86_64Msvc,
],
build_type: FtwBuildType::Debug,
};
assert_eq!(command, cmd);
}
#[test]
fn test_parse_matches_multi_build_with_blankv2() {
let app = get_clap_command();
let args = [
crate_name!(),
"build",
"linux-x86_64,windows-x86_64,macos-x86_64,,android-x86_64",
"debug",
];
let matches = app.get_matches_from(args);
let command = parse_matches(&matches);
let cmd = FtwCommand::Build {
targets: vec![
FtwTarget::AndroidLinuxX86_64,
FtwTarget::LinuxX86_64,
FtwTarget::MacOsX86_64,
FtwTarget::WindowsX86_64Msvc,
],
build_type: FtwBuildType::Debug,
};
assert_eq!(command, cmd);
}
#[test]
fn test_parse_matches_multi_build_with_blankv3() {
let app = get_clap_command();
let args = [
crate_name!(),
"build",
"linux-x86_64,windows-x86_64,macos-x86_64,android-x86_64,",
"debug",
];
let matches = app.get_matches_from(args);
let command = parse_matches(&matches);
let cmd = FtwCommand::Build {
targets: vec![
FtwTarget::AndroidLinuxX86_64,
FtwTarget::LinuxX86_64,
FtwTarget::MacOsX86_64,
FtwTarget::WindowsX86_64Msvc,
],
build_type: FtwBuildType::Debug,
};
assert_eq!(command, cmd);
@ -319,7 +422,7 @@ mod main_tests {
let matches = app.get_matches_from(args);
let command = parse_matches(&matches);
let cmd = FtwCommand::Build {
target: FtwTarget::LinuxX86_64,
targets: vec![FtwTarget::LinuxX86_64],
build_type: FtwBuildType::Debug,
};
assert_eq!(command, cmd);
@ -329,11 +432,10 @@ mod main_tests {
fn test_parse_matches_build_no_target_and_no_build_type() {
let app = get_clap_command();
let args = [crate_name!(), "build"];
let target = util::get_current_platform().parse().unwrap();
let matches = app.get_matches_from(args);
let command = parse_matches(&matches);
let cmd = FtwCommand::Build {
target,
targets: vec![util::get_current_platform().parse().unwrap()],
build_type: FtwBuildType::Debug,
};
assert_eq!(command, cmd);
@ -346,7 +448,98 @@ mod main_tests {
let matches = app.get_matches_from(args);
let command = parse_matches(&matches);
let cmd = FtwCommand::Export {
target: FtwTarget::LinuxX86_64,
targets: vec![FtwTarget::LinuxX86_64],
build_type: FtwBuildType::Debug,
};
assert_eq!(command, cmd);
}
#[test]
fn test_parse_matches_multi_export() {
let app = get_clap_command();
let args = [
crate_name!(),
"export",
"linux-x86_64,windows-x86_64,macos-x86_64,android-x86_64",
"debug",
];
let matches = app.get_matches_from(args);
let command = parse_matches(&matches);
let cmd = FtwCommand::Export {
targets: vec![
FtwTarget::AndroidLinuxX86_64,
FtwTarget::LinuxX86_64,
FtwTarget::MacOsX86_64,
FtwTarget::WindowsX86_64Msvc,
],
build_type: FtwBuildType::Debug,
};
assert_eq!(command, cmd);
}
#[test]
fn test_parse_matches_multi_export_with_blank() {
let app = get_clap_command();
let args = [
crate_name!(),
"export",
",windows-x86_64,macos-x86_64,android-x86_64",
"debug",
];
let matches = app.get_matches_from(args);
let command = parse_matches(&matches);
let cmd = FtwCommand::Export {
targets: vec![
FtwTarget::AndroidLinuxX86_64,
FtwTarget::MacOsX86_64,
FtwTarget::WindowsX86_64Msvc,
],
build_type: FtwBuildType::Debug,
};
assert_eq!(command, cmd);
}
#[test]
fn test_parse_matches_multi_export_with_blankv2() {
let app = get_clap_command();
let args = [
crate_name!(),
"export",
"linux-x86_64,windows-x86_64,macos-x86_64,,android-x86_64",
"debug",
];
let matches = app.get_matches_from(args);
let command = parse_matches(&matches);
let cmd = FtwCommand::Export {
targets: vec![
FtwTarget::AndroidLinuxX86_64,
FtwTarget::LinuxX86_64,
FtwTarget::MacOsX86_64,
FtwTarget::WindowsX86_64Msvc,
],
build_type: FtwBuildType::Debug,
};
assert_eq!(command, cmd);
}
#[test]
fn test_parse_matches_multi_export_with_blankv3() {
let app = get_clap_command();
let args = [
crate_name!(),
"export",
"linux-x86_64,windows-x86_64,macos-x86_64,android-x86_64,",
"debug",
];
let matches = app.get_matches_from(args);
let command = parse_matches(&matches);
let cmd = FtwCommand::Export {
targets: vec![
FtwTarget::AndroidLinuxX86_64,
FtwTarget::LinuxX86_64,
FtwTarget::MacOsX86_64,
FtwTarget::WindowsX86_64Msvc,
],
build_type: FtwBuildType::Debug,
};
assert_eq!(command, cmd);
@ -359,7 +552,7 @@ mod main_tests {
let matches = app.get_matches_from(args);
let command = parse_matches(&matches);
let cmd = FtwCommand::Export {
target: FtwTarget::LinuxX86_64,
targets: vec![FtwTarget::LinuxX86_64],
build_type: FtwBuildType::Debug,
};
assert_eq!(command, cmd);
@ -373,7 +566,7 @@ mod main_tests {
let matches = app.get_matches_from(args);
let command = parse_matches(&matches);
let cmd = FtwCommand::Export {
target,
targets: vec![target],
build_type: FtwBuildType::Debug,
};
assert_eq!(command, cmd);