Skip to content

Commit

Permalink
feat(cli): check if Rust lib contains required Android and iOS symbols
Browse files Browse the repository at this point in the history
…#10094 (#10483)

* feat(cli): check if Rust lib contains required Android symbols #10094

* check for ios aswell
  • Loading branch information
lucasfernog authored Aug 5, 2024
1 parent ca68689 commit 8e1e153
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 13 deletions.
6 changes: 6 additions & 0 deletions .changes/check-android-lib-symbols.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"tauri-cli": patch:enhance
"@tauri-apps/cli": patch:enhance
---

Check if the Rust library contains the symbols required at runtime for Android and iOS apps.
1 change: 1 addition & 0 deletions core/tauri-macros/src/mobile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub fn entry_point(_attributes: TokenStream, item: TokenStream) -> TokenStream {
stop_unwind(#function_name);
}

// be careful when renaming this, the `start_app` symbol is checked by the CLI
#[cfg(not(target_os = "android"))]
#[no_mangle]
#[inline(never)]
Expand Down
1 change: 1 addition & 0 deletions core/tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ macro_rules! android_binding {
::tauri::tao
);

// be careful when renaming this, the `Java_app_tauri_plugin_PluginManager_handlePluginResponse` symbol is checked by the CLI
::tauri::tao::platform::android::prelude::android_fn!(
app_tauri,
plugin,
Expand Down
7 changes: 7 additions & 0 deletions tooling/cli/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tooling/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ oxc_ast = "0.16"
magic_string = "0.3"
phf = { version = "0.11", features = ["macros"] }
walkdir = "2"
elf = "0.7"

[target."cfg(windows)".dependencies.windows-sys]
version = "0.52"
Expand Down
2 changes: 1 addition & 1 deletion tooling/cli/src/migrate/migrations/v1/frontend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pub fn migrate(app_dir: &Path, tauri_dir: &Path) -> Result<()> {
.current_package_version(pkg, app_dir)
.unwrap_or_default()
.unwrap_or_default();
if version.starts_with("1") {
if version.starts_with('1') {
new_npm_packages.push(format!("{pkg}@^{npm_version}"));
}
}
Expand Down
2 changes: 1 addition & 1 deletion tooling/cli/src/migrate/migrations/v2_rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ fn migrate_npm_dependencies(app_dir: &Path) -> Result<()> {
.current_package_version(pkg, app_dir)
.unwrap_or_default()
.unwrap_or_default();
if version.starts_with("1") {
if version.starts_with('1') {
install_deps.push(format!("{pkg}@^2.0.0-rc.0"));
}
}
Expand Down
62 changes: 52 additions & 10 deletions tooling/cli/src/mobile/android/android_studio_script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ use crate::{
};
use clap::{ArgAction, Parser};

use anyhow::Context;
use cargo_mobile2::{
android::{adb, target::Target},
opts::Profile,
target::{call_for_targets_with_fallback, TargetTrait},
};

use std::path::Path;

#[derive(Debug, Parser)]
pub struct Options {
/// Targets to build.
Expand Down Expand Up @@ -83,22 +86,61 @@ pub fn command(options: Options) -> Result<()> {
}
}

let mut validated_lib = false;

call_for_targets_with_fallback(
options.targets.unwrap_or_default().iter(),
&detect_target_ok,
&env,
|target: &Target| {
target
.build(
&config,
&metadata,
&env,
cli_options.noise_level,
true,
profile,
)
.map_err(Into::into)
target.build(
&config,
&metadata,
&env,
cli_options.noise_level,
true,
profile,
)?;

if !validated_lib {
validated_lib = true;

let lib_path = config
.app()
.target_dir(target.triple, profile)
.join(config.so_name());

validate_lib(&lib_path)?;
}

Ok(())
},
)
.map_err(|e| anyhow::anyhow!(e.to_string()))?
}

fn validate_lib(path: &Path) -> Result<()> {
let so_bytes = std::fs::read(path)?;
let elf = elf::ElfBytes::<elf::endian::AnyEndian>::minimal_parse(&so_bytes)
.context("failed to parse ELF")?;
let (symbol_table, string_table) = elf
.dynamic_symbol_table()
.context("failed to read dynsym section")?
.context("missing dynsym tables")?;

let mut symbols = Vec::new();
for s in symbol_table.iter() {
if let Ok(symbol) = string_table.get(s.st_name as usize) {
symbols.push(symbol);
}
}

if !symbols.contains(&"Java_app_tauri_plugin_PluginManager_handlePluginResponse") {
anyhow::bail!(
"Library from {} does not include required runtime symbols. This means you are likely missing the tauri::mobile_entry_point macro usage, see the documentation for more information: https://v2.tauri.app/start/migrate/from-tauri-1",
path.display()
);
}

Ok(())
}
19 changes: 18 additions & 1 deletion tooling/cli/src/mobile/ios/xcode_script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ use std::{
collections::HashMap,
env::{current_dir, set_current_dir, var_os},
ffi::OsStr,
path::PathBuf,
path::{Path, PathBuf},
process::Command,
};

#[derive(Debug, Parser)]
Expand Down Expand Up @@ -211,6 +212,8 @@ pub fn command(options: Options) -> Result<()> {
return Err(anyhow::anyhow!("Library not found at {}. Make sure your Cargo.toml file has a [lib] block with `crate-type = [\"staticlib\", \"cdylib\", \"lib\"]`", lib_path.display()));
}

validate_lib(&lib_path)?;

let project_dir = config.project_dir();
let externals_lib_dir = project_dir.join(format!("Externals/{arch}/{}", profile.as_str()));
std::fs::create_dir_all(&externals_lib_dir)?;
Expand All @@ -221,3 +224,17 @@ pub fn command(options: Options) -> Result<()> {
}
Ok(())
}

fn validate_lib(path: &Path) -> Result<()> {
// we ignore `nm` errors
if let Ok(output) = Command::new("nm").arg(path).output() {
let symbols = String::from_utf8_lossy(&output.stdout);
if !symbols.contains("start_app") {
anyhow::bail!(
"Library from {} does not include required runtime symbols. This means you are likely missing the tauri::mobile_entry_point macro usage, see the documentation for more information: https://v2.tauri.app/start/migrate/from-tauri-1",
path.display()
);
}
}
Ok(())
}

0 comments on commit 8e1e153

Please sign in to comment.