2024-03-01 11:29:01 +00:00
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
2023-02-19 14:21:50 +00:00
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
2023-05-26 16:45:20 +00:00
use super ::{ detect_target_ok , ensure_init , env , get_app , get_config , read_options , MobileTarget } ;
2024-02-03 00:43:33 +00:00
use crate ::{
helpers ::config ::get as get_tauri_config ,
interface ::{ AppInterface , Interface } ,
Result ,
} ;
2022-10-31 12:49:22 +00:00
use clap ::{ ArgAction , Parser } ;
2022-08-23 00:59:17 +00:00
2024-08-05 12:46:28 +00:00
use anyhow ::Context ;
2023-10-05 19:30:56 +00:00
use cargo_mobile2 ::{
2024-08-03 13:04:26 +00:00
android ::{ adb , target ::Target } ,
2022-08-26 12:24:23 +00:00
opts ::Profile ,
2022-08-23 00:59:17 +00:00
target ::{ call_for_targets_with_fallback , TargetTrait } ,
} ;
2024-08-05 12:46:28 +00:00
use std ::path ::Path ;
2022-08-23 00:59:17 +00:00
#[ derive(Debug, Parser) ]
pub struct Options {
/// Targets to build.
#[ clap(
short ,
long = " target " ,
2022-10-31 12:49:22 +00:00
action = ArgAction ::Append ,
num_args ( 0 .. ) ,
2022-08-23 00:59:17 +00:00
default_value = Target ::DEFAULT_KEY ,
value_parser ( clap ::builder ::PossibleValuesParser ::new ( Target ::name_list ( ) ) )
) ]
targets : Option < Vec < String > > ,
/// Builds with the release flag
#[ clap(short, long) ]
release : bool ,
}
pub fn command ( options : Options ) -> Result < ( ) > {
2024-08-11 12:44:15 +00:00
crate ::helpers ::app_paths ::resolve ( ) ;
2022-08-23 00:59:17 +00:00
let profile = if options . release {
Profile ::Release
} else {
Profile ::Debug
} ;
2023-09-12 16:18:23 +00:00
let tauri_config = get_tauri_config ( tauri_utils ::platform ::Target ::Android , None ) ? ;
2023-05-26 16:45:20 +00:00
let ( config , metadata , cli_options ) = {
let tauri_config_guard = tauri_config . lock ( ) . unwrap ( ) ;
let tauri_config_ = tauri_config_guard . as_ref ( ) . unwrap ( ) ;
2024-02-03 03:39:48 +00:00
let cli_options = read_options ( & tauri_config_ . identifier ) ;
2024-02-03 00:43:33 +00:00
let ( config , metadata ) = get_config (
& get_app ( tauri_config_ , & AppInterface ::new ( tauri_config_ , None ) ? ) ,
tauri_config_ ,
2024-02-26 18:17:45 +00:00
None ,
2024-02-03 00:43:33 +00:00
& cli_options ,
) ;
2023-05-26 16:45:20 +00:00
( config , metadata , cli_options )
} ;
2024-08-05 12:45:18 +00:00
ensure_init (
& tauri_config ,
config . app ( ) ,
config . project_dir ( ) ,
MobileTarget ::Android ,
) ? ;
2023-05-26 16:45:20 +00:00
let env = env ( ) ? ;
2024-08-03 13:04:26 +00:00
if cli_options . dev {
let dev_url = tauri_config
. lock ( )
. unwrap ( )
. as_ref ( )
. unwrap ( )
. build
. dev_url
. clone ( ) ;
if let Some ( port ) = dev_url . and_then ( | url | url . port_or_known_default ( ) ) {
let forward = format! ( " tcp: {port} " ) ;
// ignore errors in case we do not have a device available
let _ = adb ::adb ( & env , [ " reverse " , & forward , & forward ] )
. stdin_file ( os_pipe ::dup_stdin ( ) . unwrap ( ) )
. stdout_file ( os_pipe ::dup_stdout ( ) . unwrap ( ) )
. stderr_capture ( )
. run ( ) ;
}
}
2024-08-05 12:46:28 +00:00
let mut validated_lib = false ;
2023-05-26 16:45:20 +00:00
call_for_targets_with_fallback (
options . targets . unwrap_or_default ( ) . iter ( ) ,
& detect_target_ok ,
& env ,
| target : & Target | {
2024-08-05 12:46:28 +00:00
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 ( ( ) )
2023-05-26 16:45:20 +00:00
} ,
)
. map_err ( | e | anyhow ::anyhow! ( e . to_string ( ) ) ) ?
2022-08-23 00:59:17 +00:00
}
2024-08-05 12:46:28 +00:00
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 ( ( ) )
}