From 59db76af4c88645ee03b9f87c0f787fbc0040905 Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Tue, 16 May 2023 06:22:46 -0700 Subject: [PATCH] refactor(android): fix race conditions processing Android plugin project as dependency (#6968) --- core/tauri-build/src/lib.rs | 48 +------- core/tauri-build/src/mobile.rs | 104 ++++++++++-------- core/tauri/build.rs | 1 + .../src-tauri/tauri-plugin-sample/Cargo.toml | 1 + tooling/cli/src/mobile/android/build.rs | 15 +-- tooling/cli/src/mobile/mod.rs | 9 +- .../buildSrc/src/main/kotlin/BuildTask.kt | 2 +- .../cli/templates/plugin/Cargo.crate-manifest | 1 + 8 files changed, 71 insertions(+), 110 deletions(-) diff --git a/core/tauri-build/src/lib.rs b/core/tauri-build/src/lib.rs index 8da6a0a2f..31f94be6e 100644 --- a/core/tauri-build/src/lib.rs +++ b/core/tauri-build/src/lib.rs @@ -15,9 +15,7 @@ use tauri_utils::{ }; use std::{ - collections::HashMap, env::var_os, - fs::{read_to_string, write}, path::{Path, PathBuf}, }; @@ -270,51 +268,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> { println!("cargo:rustc-env=TAURI_ANDROID_PACKAGE_PREFIX={android_package_prefix}"); if let Some(project_dir) = var_os("TAURI_ANDROID_PROJECT_PATH").map(PathBuf::from) { - let gradle_settings_path = project_dir.join("tauri.settings.gradle"); - let app_build_gradle_path = project_dir.join("app").join("tauri.build.gradle.kts"); - - let mut gradle_settings = - "// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n".to_string(); - let mut app_build_gradle = "// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -val implementation by configurations -dependencies {" - .to_string(); - - let plugins_json_path = project_dir.join(".tauri").join("plugins.json"); - let mut plugins: HashMap = if plugins_json_path.exists() { - let s = read_to_string(&plugins_json_path)?; - println!("cargo:rerun-if-changed={}", plugins_json_path.display()); - serde_json::from_str(&s)? - } else { - Default::default() - }; - - plugins.insert( - "tauri-android".into(), - mobile::PluginMetadata { - path: var_os("DEP_TAURI_ANDROID_LIBRARY_PATH").map(PathBuf::from).expect("missing `DEP_TAURI_ANDROID_LIBRARY_PATH` environment variable; did you add `tauri` as a dependency to this crate?"), - }, - ); - - for (plugin_name, plugin) in plugins { - gradle_settings.push_str(&format!("include ':{plugin_name}'")); - gradle_settings.push('\n'); - gradle_settings.push_str(&format!( - "project(':{plugin_name}').projectDir = new File({:?})", - tauri_utils::display_path(plugin.path) - )); - gradle_settings.push('\n'); - - app_build_gradle.push('\n'); - app_build_gradle.push_str(&format!(r#" implementation(project(":{plugin_name}"))"#)); - } - app_build_gradle.push_str("\n}"); - - write(&gradle_settings_path, gradle_settings) - .context("failed to write tauri.settings.gradle")?; - - write(&app_build_gradle_path, app_build_gradle) - .context("failed to write tauri.build.gradle.kts")?; + mobile::generate_gradle_files(project_dir)?; } cfg_alias("dev", !has_feature("custom-protocol")); diff --git a/core/tauri-build/src/mobile.rs b/core/tauri-build/src/mobile.rs index c9a5d92df..9b4e0b87e 100644 --- a/core/tauri-build/src/mobile.rs +++ b/core/tauri-build/src/mobile.rs @@ -3,19 +3,15 @@ // SPDX-License-Identifier: MIT use std::{ - collections::HashMap, env::{var, var_os}, - fs::{copy, create_dir, create_dir_all, read_to_string, remove_dir_all, File}, - io::Write, + fs::{copy, create_dir, create_dir_all, remove_dir_all, write}, path::{Path, PathBuf}, - thread::sleep, - time::{Duration, SystemTime}, }; use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize, Serialize, Eq, PartialEq)] +#[derive(Debug, Default, Deserialize, Serialize, Eq, PartialEq)] pub(crate) struct PluginMetadata { pub path: PathBuf, } @@ -69,48 +65,7 @@ impl PluginBuilder { ) .context("failed to copy tauri-api to the plugin project")?; - if let Some(project_dir) = var_os("TAURI_ANDROID_PROJECT_PATH").map(PathBuf::from) { - let pkg_name = var("CARGO_PKG_NAME").unwrap(); - println!("cargo:rerun-if-env-changed=TAURI_ANDROID_PROJECT_PATH"); - - let plugins_json_path = project_dir.join(".tauri").join("plugins.json"); - let mut plugins: HashMap = if plugins_json_path.exists() { - let s = read_to_string(&plugins_json_path)?; - serde_json::from_str(&s)? - } else { - Default::default() - }; - - let metadata = PluginMetadata { path: source }; - let already_set = plugins - .get(&pkg_name) - .map(|m| m == &metadata) - .unwrap_or(false); - if !already_set { - plugins.insert(pkg_name, metadata); - let mut file = File::create(&plugins_json_path)?; - file.write_all(serde_json::to_string(&plugins)?.as_bytes())?; - file.flush()?; - - // wait for the file to be written before moving to the app build script - let now = SystemTime::now() - .checked_sub(Duration::from_millis(10)) - .unwrap(); - let mut attempts = 0; - while !plugins_json_path - .metadata() - .map(|m| m.modified().unwrap() >= now) - .unwrap_or(false) - { - attempts += 1; - if attempts == 10 { - anyhow::bail!("Could not determine whether the plugins.json file has been modified or not, please rerun the build."); - } - sleep(Duration::from_millis(100)); - } - } - println!("cargo:rerun-if-changed={}", plugins_json_path.display()); - } + println!("cargo:android_library_path={}", source.display()); } } #[cfg(target_os = "macos")] @@ -190,3 +145,56 @@ fn copy_folder(source: &Path, target: &Path, ignore_paths: &[&str]) -> Result<() Ok(()) } + +pub(crate) fn generate_gradle_files(project_dir: PathBuf) -> Result<()> { + let gradle_settings_path = project_dir.join("tauri.settings.gradle"); + let app_build_gradle_path = project_dir.join("app").join("tauri.build.gradle.kts"); + + let mut gradle_settings = + "// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n".to_string(); + let mut app_build_gradle = "// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +val implementation by configurations +dependencies {" + .to_string(); + + for (env, value) in std::env::vars_os() { + let env = env.to_string_lossy(); + if env.starts_with("DEP_") && env.ends_with("_ANDROID_LIBRARY_PATH") { + let name_len = env.len() - "DEP_".len() - "_ANDROID_LIBRARY_PATH".len(); + let mut plugin_name = env + .chars() + .skip("DEP_".len()) + .take(name_len) + .collect::() + .to_lowercase() + .replace('_', "-"); + if plugin_name == "tauri" { + plugin_name = "tauri-android".into(); + } + let plugin_path = PathBuf::from(value); + + gradle_settings.push_str(&format!("include ':{plugin_name}'")); + gradle_settings.push('\n'); + gradle_settings.push_str(&format!( + "project(':{plugin_name}').projectDir = new File({:?})", + tauri_utils::display_path(plugin_path) + )); + gradle_settings.push('\n'); + + app_build_gradle.push('\n'); + app_build_gradle.push_str(&format!(r#" implementation(project(":{plugin_name}"))"#)); + } + } + + app_build_gradle.push_str("\n}"); + + write(&gradle_settings_path, gradle_settings).context("failed to write tauri.settings.gradle")?; + + write(&app_build_gradle_path, app_build_gradle) + .context("failed to write tauri.build.gradle.kts")?; + + println!("cargo:rerun-if-changed={}", gradle_settings_path.display()); + println!("cargo:rerun-if-changed={}", app_build_gradle_path.display()); + + Ok(()) +} diff --git a/core/tauri/build.rs b/core/tauri/build.rs index 863c9c264..ffb958f8d 100644 --- a/core/tauri/build.rs +++ b/core/tauri/build.rs @@ -116,6 +116,7 @@ fn main() { ) .expect("failed to write proguard-tauri.pro"); } + let lib_path = PathBuf::from(std::env::var_os("CARGO_MANIFEST_DIR").unwrap()).join("mobile/android"); println!("cargo:android_library_path={}", lib_path.display()); diff --git a/examples/api/src-tauri/tauri-plugin-sample/Cargo.toml b/examples/api/src-tauri/tauri-plugin-sample/Cargo.toml index 30252fcc7..41c002a1a 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/Cargo.toml +++ b/examples/api/src-tauri/tauri-plugin-sample/Cargo.toml @@ -2,6 +2,7 @@ name = "tauri-plugin-sample" version = "0.1.0" edition = "2021" +links = "tauri-plugin-sample" [dependencies] tauri = { path = "../../../../core/tauri" } diff --git a/tooling/cli/src/mobile/android/build.rs b/tooling/cli/src/mobile/android/build.rs index d8816accc..6761e3422 100644 --- a/tooling/cli/src/mobile/android/build.rs +++ b/tooling/cli/src/mobile/android/build.rs @@ -81,6 +81,12 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> { set_var("WRY_RUSTWEBVIEWCLIENT_CLASS_EXTENSION", ""); set_var("WRY_RUSTWEBVIEW_CLASS_INIT", ""); + let profile = if options.debug { + Profile::Debug + } else { + Profile::Release + }; + ensure_init(config.project_dir(), MobileTarget::Android)?; let mut env = env()?; @@ -101,7 +107,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> { )?; let open = options.open; - run_build(options, config, &mut env, noise_level)?; + run_build(options, profile, config, &mut env, noise_level)?; if open { open_and_wait(config, &env); @@ -115,16 +121,11 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> { fn run_build( mut options: Options, + profile: Profile, config: &AndroidConfig, env: &mut Env, noise_level: NoiseLevel, ) -> Result<()> { - let profile = if options.debug { - Profile::Debug - } else { - Profile::Release - }; - if !(options.apk || options.aab) { // if the user didn't specify the format to build, we'll do both options.apk = true; diff --git a/tooling/cli/src/mobile/mod.rs b/tooling/cli/src/mobile/mod.rs index f3e0364f5..defa590b0 100644 --- a/tooling/cli/src/mobile/mod.rs +++ b/tooling/cli/src/mobile/mod.rs @@ -24,7 +24,7 @@ use std::{ env::{set_var, temp_dir}, ffi::OsString, fmt::Write, - fs::{create_dir_all, read_to_string, remove_file, write}, + fs::{read_to_string, write}, net::SocketAddr, path::PathBuf, process::{exit, ExitStatus}, @@ -315,13 +315,8 @@ fn ensure_init(project_dir: PathBuf, target: Target) -> Result<()> { project_dir.display(), target.command_name(), ) - } else { - if target == Target::Android { - create_dir_all(project_dir.join(".tauri"))?; - let _ = remove_file(project_dir.join(".tauri").join("plugins.json")); - } - Ok(()) } + Ok(()) } fn log_finished(outputs: Vec, kind: &str) { diff --git a/tooling/cli/templates/mobile/android/buildSrc/src/main/kotlin/BuildTask.kt b/tooling/cli/templates/mobile/android/buildSrc/src/main/kotlin/BuildTask.kt index 8a0f065b7..8bbef994a 100644 --- a/tooling/cli/templates/mobile/android/buildSrc/src/main/kotlin/BuildTask.kt +++ b/tooling/cli/templates/mobile/android/buildSrc/src/main/kotlin/BuildTask.kt @@ -15,7 +15,7 @@ open class BuildTask : DefaultTask() { var release: Boolean? = null @TaskAction - fun build() { + fun assemble() { val executable = """{{tauri-binary}}"""; try { runTauriCli(executable) diff --git a/tooling/cli/templates/plugin/Cargo.crate-manifest b/tooling/cli/templates/plugin/Cargo.crate-manifest index 56fed2117..388143d9a 100644 --- a/tooling/cli/templates/plugin/Cargo.crate-manifest +++ b/tooling/cli/templates/plugin/Cargo.crate-manifest @@ -6,6 +6,7 @@ description = "" edition = "2021" rust-version = "1.65" exclude = ["/examples", "/webview-dist", "/webview-src", "/node_modules"] +links = "tauri-plugin-{{ plugin_name }}" [dependencies] tauri = {{ tauri_dep }}