Răsfoiți Sursa

fix: autodetect android install (#3200)

* fix: autodetect android install

* use clang
Jonathan Kelley 7 luni în urmă
părinte
comite
c1f3a6868e

+ 8 - 1
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(),

+ 7 - 1
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(())
     }
 }

+ 68 - 0
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<PathBuf> {
+        // "/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<Option<PathBuf>> = once_cell::sync::Lazy::new(|| {
+            use std::env::var;
+            use tracing::debug;
+
+            fn var_or_debug(name: &str) -> Option<PathBuf> {
+                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<PathBuf> {
+        // "/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 {