diff --git a/Cargo.lock b/Cargo.lock index 13a7f2e..5953bcd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -993,7 +993,7 @@ dependencies = [ [[package]] name = "geode" -version = "3.1.1" +version = "3.2.0" dependencies = [ "ansi_term", "cfg-if 1.0.0", diff --git a/Cargo.toml b/Cargo.toml index 3f150bd..0fd2eb4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "geode" -version = "3.1.1" +version = "3.2.0" authors = [ "HJfod ", "Camila314 ", diff --git a/src/cli.rs b/src/cli.rs index 39d2db2..2e2021c 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,3 +1,5 @@ +use crate::mod_file::PlatformName; + /// Command-line interface for Geode #[derive(clap::Parser, Debug)] #[clap(version)] @@ -75,7 +77,7 @@ pub enum GeodeCommands { Build { /// Which platform to cross-compile to, if possible #[clap(long, short)] - platform: Option, + platform: Option, /// Whether to only configure cmake #[clap(long, short, default_value_t = false)] diff --git a/src/package.rs b/src/package.rs index aefd7ff..aac48ce 100644 --- a/src/package.rs +++ b/src/package.rs @@ -483,7 +483,7 @@ pub fn subcommand(config: &mut Config, cmd: Package) { input, output, externals, - } => project::check_dependencies(config, input, output, externals), + } => project::check_dependencies(config, input, output, None, externals), Package::Resources { root_path, diff --git a/src/project.rs b/src/project.rs index d95678b..c7f63c6 100644 --- a/src/project.rs +++ b/src/project.rs @@ -1,4 +1,4 @@ -use crate::mod_file::ToGeodeString; +use crate::mod_file::{PlatformName, ToGeodeString}; use crate::util::mod_file::DependencyImportance; use crate::{done, fail, fatal, index, info, warn, NiceUnwrap}; use crate::{ @@ -40,6 +40,11 @@ pub enum Project { /// is assumed install_dir: Option, + /// The platform checked used for platform-specific dependencies. If + /// not specified, uses current host platform if possible + #[clap(long, short)] + platform: Option, + /// Any external dependencies as a list in the form of `mod.id:version`. /// An external dependency is one that the CLI will not verify exists in /// any way; it will just assume you have it installed through some @@ -235,6 +240,7 @@ pub fn check_dependencies( config: &Config, input: PathBuf, output: PathBuf, + platform: Option, externals: Vec, ) { let mod_info = parse_mod_info(&input); @@ -269,8 +275,16 @@ pub fn check_dependencies( let dep_dir = output.join("geode-deps"); fs::create_dir_all(&dep_dir).nice_unwrap("Unable to create dependency directory"); + let platform = platform + .unwrap_or_else(|| PlatformName::current().nice_unwrap("Unknown platform, please specify one with --platform")); + // check all dependencies for dep in mod_info.dependencies { + // Skip dependencies not on this platform + if !dep.platforms.contains(&platform) { + continue; + } + // is this an external dependency? if let Some(ext) = externals.get(&dep.id) { // did we get a version? @@ -503,11 +517,13 @@ pub fn subcommand(config: &mut Config, cmd: Project) { Project::ClearCache => clear_cache(&std::env::current_dir().unwrap()), Project::Check { install_dir, + platform, externals, } => check_dependencies( config, std::env::current_dir().unwrap(), install_dir.unwrap_or("build".into()), + platform, externals, ), } diff --git a/src/project_build.rs b/src/project_build.rs index 6013b16..818bc57 100644 --- a/src/project_build.rs +++ b/src/project_build.rs @@ -1,9 +1,9 @@ use std::{path::Path, process::Command}; -use crate::{fail, fatal, info, NiceUnwrap}; +use crate::{fail, fatal, info, mod_file::PlatformName, warn, NiceUnwrap}; pub fn build_project( - platform: Option, + platform: Option, configure_only: bool, build_only: bool, ndk_path: Option, @@ -14,33 +14,27 @@ pub fn build_project( fatal!("Could not find CMakeLists.txt. Please run this within a Geode project!"); } - let platform = platform.map(|x| x.to_lowercase()); let platform = platform - .map(|x| match x.as_str() { - "win" | "windows" => String::from("win"), - "mac" | "macos" => String::from("mac"), - s @ ("android32" | "android64") => String::from(s), - s => fatal!("Unknown platform {s}"), - }) - .unwrap_or_else(|| { - if cfg!(target_os = "windows") { - String::from("win") - } else if cfg!(target_os = "android") { - String::from("android64") - } else if cfg!(target_os = "linux") { - String::from("win") - } else if cfg!(target_os = "macos") { - String::from("mac") - } else { - fatal!("Unknown platform, please specify one with --platform"); - } - }); + .unwrap_or_else(|| PlatformName::current().nice_unwrap("Unknown platform, please specify one with --platform")); + + // Make architechture exact + let platform = match platform { + PlatformName::Android => { + warn!("Assuming 64-bit Android, use \"-p android32\" to build for 32-bit Android"); + PlatformName::Android64 + }, + // If Mac cross-building ever becomes possible, make sure to upgrade Mac + // to MacArm or MacIntel here (or hard error if there's no reasonable + // default) + p => p, + }; + let cross_compiling = if cfg!(target_os = "windows") { - platform != "win" + platform != PlatformName::Windows } else if cfg!(target_os = "linux") { true } else if cfg!(target_os = "macos") { - platform != "mac" + platform != PlatformName::MacOS } else { true }; @@ -52,8 +46,8 @@ pub fn build_project( }; let mut conf_args: Vec = Vec::new(); - match platform.as_str() { - "win" => { + match platform { + PlatformName::Windows => { if cross_compiling { let root = crate::config::Config::cross_tools_path(); let splat_path = root.join("splat"); @@ -81,13 +75,13 @@ pub fn build_project( conf_args.extend(["-A", "x64"].map(String::from)); } } - "mac" => { + PlatformName::MacOS | PlatformName::MacArm | PlatformName::MacIntel => { if cross_compiling { fatal!("Sorry! but we do not know of any way to cross-compile to MacOS."); } conf_args.push("-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15".into()) } - "android32" | "android64" => { + PlatformName::Android32 | PlatformName::Android64 | PlatformName::Android => { if !build_only { let ndk_path = ndk_path.unwrap_or_else(|| std::env::var("ANDROID_NDK_ROOT").nice_unwrap( @@ -103,9 +97,10 @@ pub fn build_project( "-DCMAKE_TOOLCHAIN_FILE={}", toolchain_path.to_string_lossy() )); - if platform == "android32" { + if platform == PlatformName::Android32 { conf_args.push("-DANDROID_ABI=armeabi-v7a".into()); - } else { + } + else { conf_args.push("-DANDROID_ABI=arm64-v8a".into()); } // TODO: let the user change this? idk @@ -118,13 +113,13 @@ pub fn build_project( conf_args.push("-DGEODE_DONT_INSTALL_MODS=1".into()); } } - _ => unreachable!("invalid platform"), } let build_type = config_type.unwrap_or_else(|| { - if platform == "win" { + if platform == PlatformName::Windows { "RelWithDebInfo".into() - } else { + } + else { "Debug".into() } }); diff --git a/src/util/mod_file.rs b/src/util/mod_file.rs index 4544260..a3571e9 100644 --- a/src/util/mod_file.rs +++ b/src/util/mod_file.rs @@ -1,8 +1,10 @@ use crate::spritesheet::SpriteSheet; use crate::NiceUnwrap; +use clap::ValueEnum; use semver::{Version, VersionReq}; use serde::{Deserialize, Deserializer}; use std::collections::{HashMap, HashSet}; +use std::fmt::Display; use std::fs; use std::io::Read; use std::path::{Path, PathBuf}; @@ -214,11 +216,13 @@ pub struct ModResources { pub fonts: HashMap, } -#[derive(Deserialize, Hash, PartialEq, Eq)] +#[derive(Debug, Deserialize, Hash, PartialEq, Eq, Clone, Copy, ValueEnum)] #[serde(rename_all = "lowercase")] pub enum PlatformName { #[serde(rename = "win")] + #[value(alias = "win")] Windows, + #[value(alias = "mac")] MacOS, #[serde(rename = "mac-intel")] MacIntel, @@ -229,6 +233,41 @@ pub enum PlatformName { Android64, } +impl PlatformName { + pub fn current() -> Option { + if cfg!(target_os = "windows") { + Some(PlatformName::Windows) + } + else if cfg!(target_os = "android") { + Some(PlatformName::Android64) + } + else if cfg!(target_os = "linux") { + Some(PlatformName::Windows) + } + else if cfg!(target_os = "macos") { + Some(PlatformName::MacOS) + } + else { + None + } + } +} + +impl Display for PlatformName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use PlatformName as P; + f.write_str(match self { + P::Windows => "win", + P::MacOS => "mac", + P::MacIntel => "mac-intel", + P::MacArm => "mac-arm", + P::Android => "android", + P::Android32 => "android32", + P::Android64 => "android64", + }) + } +} + fn all_platforms() -> HashSet { use PlatformName as P; HashSet::from([