diff --git a/packages/cli/src/build/request.rs b/packages/cli/src/build/request.rs index 06e6a6311..b9e7d06c8 100644 --- a/packages/cli/src/build/request.rs +++ b/packages/cli/src/build/request.rs @@ -114,10 +114,17 @@ impl BuildRequest { // We don't want to overwrite the user's .cargo/config.toml since that gets committed to git // and we want everyone's install to be the same. if self.build.platform() == Platform::Android { + let linker = self + .krate + .android_linker() + .context("Could not autodetect android linker")?; + + tracing::trace!("Using android linker: {linker:?}"); + cmd.env( LinkAction::ENV_VAR_NAME, LinkAction::LinkAndroid { - linker: "/Users/jonkelley/Library/Android/sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android24-clang".into(), + linker, extra_flags: vec![], } .to_json(), diff --git a/packages/cli/src/build/verify.rs b/packages/cli/src/build/verify.rs index 2c8af9321..3fa876183 100644 --- a/packages/cli/src/build/verify.rs +++ b/packages/cli/src/build/verify.rs @@ -134,6 +134,12 @@ impl BuildRequest { /// will do its best to fill in the missing bits by exploring the sdk structure /// IE will attempt to use the Java installed from android studio if possible. pub(crate) async fn verify_android_tooling(&self, _rustup: RustupShow) -> Result<()> { + if self.krate.android_linker().is_none() { + return Err(anyhow::anyhow!( + "Android linker not found. Please set the ANDROID_NDK_HOME environment variable to the root of your NDK installation." + ).into()); + } + Ok(()) } @@ -142,7 +148,7 @@ impl BuildRequest { /// /// Eventually, we want to check for the prereqs for wry/tao as outlined by tauri: /// https://tauri.app/start/prerequisites/ - pub(crate) async fn verify_linux_tooling(&self, _rustup: crate::RustupShow) -> Result<()> { + pub(crate) async fn verify_linux_tooling(&self, _rustup: RustupShow) -> Result<()> { Ok(()) } } diff --git a/packages/cli/src/dioxus_crate.rs b/packages/cli/src/dioxus_crate.rs index 54dccc40a..a0074f5cc 100644 --- a/packages/cli/src/dioxus_crate.rs +++ b/packages/cli/src/dioxus_crate.rs @@ -2,6 +2,7 @@ use crate::CliSettings; use crate::{config::DioxusConfig, TargetArgs}; use crate::{Platform, Result}; use anyhow::Context; +use itertools::Itertools; use krates::{cm::Target, KrateDetails}; use krates::{cm::TargetKind, Cmd, Krates, NodeId}; use std::path::PathBuf; @@ -555,6 +556,73 @@ impl DioxusCrate { krates } + + fn android_ndk(&self) -> Option { + // "/Users/jonkelley/Library/Android/sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android24-clang" + static PATH: once_cell::sync::Lazy> = once_cell::sync::Lazy::new(|| { + use std::env::var; + use tracing::debug; + + fn var_or_debug(name: &str) -> Option { + var(name) + .inspect_err(|_| debug!("{name} not set")) + .ok() + .map(PathBuf::from) + } + + // attempt to autodetect the ndk path from env vars (usually set by the shell) + let auto_detected_ndk = + var_or_debug("NDK_HOME").or_else(|| var_or_debug("ANDROID_NDK_HOME")); + + if let Some(home) = auto_detected_ndk { + return Some(home); + } + + let sdk = var_or_debug("ANDROID_SDK_ROOT") + .or_else(|| var_or_debug("ANDROID_SDK")) + .or_else(|| var_or_debug("ANDROID_HOME"))?; + + let ndk = sdk.join("ndk"); + + ndk.read_dir() + .ok()? + .flatten() + .map(|dir| (dir.file_name(), dir.path())) + .sorted() + .last() + .map(|(_, path)| path.to_path_buf()) + }); + + PATH.clone() + } + + pub(crate) fn android_linker(&self) -> Option { + // "/Users/jonkelley/Library/Android/sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android24-clang" + self.android_ndk().map(|ndk| { + let toolchain_dir = ndk.join("toolchains").join("llvm").join("prebuilt"); + + if cfg!(target_os = "macos") { + // for whatever reason, even on aarch64 macos, the linker is under darwin-x86_64 + return toolchain_dir + .join("darwin-x86_64") + .join("bin") + .join("clang"); + } + + if cfg!(target_os = "linux") { + return toolchain_dir.join("linux-x86_64").join("bin").join("clang"); + } + + if cfg!(target_os = "windows") { + return toolchain_dir + .join("windows-x86_64") + .join("bin") + .join("clang.exe"); + } + + unimplemented!("Unsupported target os for android toolchain auodetection") + }) + } } impl std::fmt::Debug for DioxusCrate {