use std::{env, path::{Path, PathBuf}};
use self::find_java::find_java_home;
mod find_android_sdk;
mod find_java;
pub const ANDROID_HOME: &str = "ANDROID_HOME";
pub const ANDROID_SDK_ROOT: &str = "ANDROID_SDK_ROOT";
pub const ANDROID_BUILD_TOOLS_VERSION: &str = "ANDROID_BUILD_TOOLS_VERSION";
pub const ANDROID_PLATFORM: &str = "ANDROID_PLATFORM";
pub const ANDROID_SDK_VERSION: &str = "ANDROID_SDK_VERSION";
pub const ANDROID_API_LEVEL: &str = "ANDROID_API_LEVEL";
pub const ANDROID_SDK_EXTENSION: &str = "ANDROID_SDK_EXTENSION";
pub const ANDROID_D8_JAR: &str = "ANDROID_D8_JAR";
pub const ANDROID_JAR: &str = "ANDROID_JAR";
pub const JAVA_HOME: &str = "JAVA_HOME";
pub trait PathExt {
fn path_if_exists(self) -> Option<Self> where Self: Sized;
}
impl<P: AsRef<Path>> PathExt for P {
fn path_if_exists(self) -> Option<P> {
if self.as_ref().as_os_str().is_empty() {
return None;
}
self.as_ref().exists().then_some(self)
}
}
#[doc(alias("ANDROID_HOME", "ANDROID_SDK_ROOT", "home", "sdk", "root"))]
pub fn android_sdk() -> Option<PathBuf> {
env::var(ANDROID_HOME).ok()
.and_then(PathExt::path_if_exists)
.or_else(|| env::var(ANDROID_SDK_ROOT).ok()
.and_then(PathExt::path_if_exists)
)
.map(PathBuf::from)
.or_else(|| find_android_sdk::find_android_sdk().and_then(PathExt::path_if_exists))
}
pub fn android_jar(platform_string: Option<&str>) -> Option<PathBuf> {
env::var(ANDROID_JAR).ok()
.and_then(PathExt::path_if_exists)
.map(PathBuf::from)
.or_else(|| android_sdk()
.and_then(|sdk| sdk
.join("platforms")
.join(platform_string.map(ToString::to_string)
.unwrap_or_else(|| env_android_platform_api_level()
.expect("either ANDROID_JAR or [ANDROID_PLATFORM, ANDROID_API_LEVEL, ANDROID_SDK_VERSION] must be set")
)
)
.join("android.jar")
.path_if_exists()
)
)
}
pub fn android_d8_jar(build_tools_version: Option<&str>) -> Option<PathBuf> {
env::var(ANDROID_D8_JAR).ok()
.and_then(PathExt::path_if_exists)
.map(PathBuf::from)
.or_else(|| android_sdk()
.and_then(|sdk| sdk
.join("build-tools")
.join(build_tools_version.map(ToString::to_string)
.unwrap_or_else(|| env::var(ANDROID_BUILD_TOOLS_VERSION)
.expect("either ANDROID_D8_JAR or ANDROID_BUILD_TOOLS_VERSION must be set")
)
)
.join("lib")
.join("d8.jar")
.path_if_exists()
)
)
}
fn env_android_platform_api_level() -> Option<String> {
let mut base = env::var(ANDROID_PLATFORM).ok()
.or_else(|| env::var(ANDROID_API_LEVEL).ok())
.or_else(|| env::var(ANDROID_SDK_VERSION).ok())?;
if base.is_empty() {
return None;
}
if !base.starts_with("android-") {
base = format!("android-{}", base);
}
if base.contains("-ext") {
return Some(base);
}
if let Some(raw_ext) = env::var(ANDROID_SDK_EXTENSION).ok() {
let ext_num = raw_ext
.trim_start_matches("-")
.trim_start_matches("ext");
if !ext_num.is_empty() {
base = format!("{}-ext{}", base, ext_num);
}
}
Some(base)
}
pub fn java() -> Option<PathBuf> {
java_home().and_then(|jh| jh
.join("bin")
.join("java")
.path_if_exists()
)
}
pub fn javac() -> Option<PathBuf> {
java_home().and_then(|jh| jh
.join("bin")
.join("javac")
.path_if_exists()
)
}
pub fn java_home() -> Option<PathBuf> {
env::var(JAVA_HOME).ok()
.and_then(PathExt::path_if_exists)
.map(PathBuf::from)
.or_else(find_java_home)
}