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
2024-08-05 12:45:18 +00:00
use super ::{ ensure_init , env , get_app , get_config , read_options , MobileTarget } ;
2022-12-12 13:36:47 +00:00
use crate ::{
2023-05-26 16:45:20 +00:00
helpers ::config ::get as get_tauri_config ,
2022-12-12 13:36:47 +00:00
interface ::{ AppInterface , AppSettings , Interface , Options as InterfaceOptions } ,
Result ,
} ;
2022-08-23 00:59:17 +00:00
2023-10-05 19:30:56 +00:00
use cargo_mobile2 ::{ apple ::target ::Target , opts ::Profile } ;
2022-12-12 13:36:47 +00:00
use clap ::Parser ;
2022-08-23 00:59:17 +00:00
2023-05-26 16:45:20 +00:00
use std ::{
collections ::HashMap ,
env ::{ current_dir , set_current_dir , var_os } ,
ffi ::OsStr ,
path ::PathBuf ,
} ;
2022-08-23 00:59:17 +00:00
#[ derive(Debug, Parser) ]
pub struct Options {
/// Value of `PLATFORM_DISPLAY_NAME` env var
#[ clap(long) ]
platform : String ,
/// Value of `SDKROOT` env var
#[ clap(long) ]
sdk_root : PathBuf ,
2022-11-11 14:43:25 +00:00
/// Value of `FRAMEWORK_SEARCH_PATHS` env var
#[ clap(long) ]
framework_search_paths : String ,
/// Value of `GCC_PREPROCESSOR_DEFINITIONS` env var
#[ clap(long) ]
gcc_preprocessor_definitions : String ,
/// Value of `HEADER_SEARCH_PATHS` env var
#[ clap(long) ]
header_search_paths : String ,
2022-08-23 00:59:17 +00:00
/// Value of `CONFIGURATION` env var
#[ clap(long) ]
configuration : String ,
/// Value of `FORCE_COLOR` env var
#[ clap(long) ]
force_color : bool ,
/// Value of `ARCHS` env var
#[ clap(index = 1, required = true) ]
arches : Vec < String > ,
}
pub fn command ( options : Options ) -> Result < ( ) > {
fn macos_from_platform ( platform : & str ) -> bool {
platform = = " macOS "
}
fn profile_from_configuration ( configuration : & str ) -> Profile {
if configuration = = " release " {
Profile ::Release
} else {
Profile ::Debug
}
}
2023-03-16 12:27:40 +00:00
// `xcode-script` is ran from the `gen/apple` folder when not using NPM.
2024-05-12 02:32:05 +00:00
if var_os ( " npm_lifecycle_event " ) . is_none ( ) & & var_os ( " PNPM_PACKAGE_NAME " ) . is_none ( ) {
2023-05-26 16:45:20 +00:00
set_current_dir ( current_dir ( ) ? . parent ( ) . unwrap ( ) . parent ( ) . unwrap ( ) ) . unwrap ( ) ;
2023-03-16 12:27:40 +00:00
}
2022-11-11 14:43:25 +00:00
2022-08-23 00:59:17 +00:00
let profile = profile_from_configuration ( & options . configuration ) ;
let macos = macos_from_platform ( & options . platform ) ;
2023-09-12 16:18:23 +00:00
let tauri_config = get_tauri_config ( tauri_utils ::platform ::Target ::Ios , None ) ? ;
2022-08-23 00:59:17 +00:00
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 ::Ios ,
) ? ;
2023-05-26 16:45:20 +00:00
let env = env ( ) ? . explicit_env_vars ( cli_options . vars ) ;
if ! options . sdk_root . is_dir ( ) {
return Err ( anyhow ::anyhow! (
" SDK root provided by Xcode was invalid. {} doesn't exist or isn't a directory " ,
options . sdk_root . display ( ) ,
) ) ;
}
let include_dir = options . sdk_root . join ( " usr/include " ) ;
if ! include_dir . is_dir ( ) {
return Err ( anyhow ::anyhow! (
" Include dir was invalid. {} doesn't exist or isn't a directory " ,
include_dir . display ( )
) ) ;
}
// Host flags that are used by build scripts
let macos_isysroot = {
let macos_sdk_root = options
. sdk_root
. join ( " ../../../../MacOSX.platform/Developer/SDKs/MacOSX.sdk " ) ;
if ! macos_sdk_root . is_dir ( ) {
2022-08-28 18:32:50 +00:00
return Err ( anyhow ::anyhow! (
2023-05-26 16:45:20 +00:00
" Invalid SDK root {} " ,
macos_sdk_root . display ( )
2022-08-28 18:32:50 +00:00
) ) ;
2022-08-23 00:59:17 +00:00
}
2023-05-26 16:45:20 +00:00
format! ( " -isysroot {} " , macos_sdk_root . display ( ) )
} ;
2022-08-23 00:59:17 +00:00
2023-05-26 16:45:20 +00:00
let mut host_env = HashMap ::< & str , & OsStr > ::new ( ) ;
2022-11-11 14:43:25 +00:00
2023-05-26 16:45:20 +00:00
host_env . insert ( " RUST_BACKTRACE " , " 1 " . as_ref ( ) ) ;
2022-08-23 00:59:17 +00:00
2023-05-26 16:45:20 +00:00
host_env . insert ( " CFLAGS_x86_64_apple_darwin " , macos_isysroot . as_ref ( ) ) ;
host_env . insert ( " CXXFLAGS_x86_64_apple_darwin " , macos_isysroot . as_ref ( ) ) ;
2022-08-23 00:59:17 +00:00
2023-05-26 16:45:20 +00:00
host_env . insert (
" OBJC_INCLUDE_PATH_x86_64_apple_darwin " ,
include_dir . as_os_str ( ) ,
) ;
2022-11-11 14:43:25 +00:00
2023-05-26 16:45:20 +00:00
host_env . insert (
" FRAMEWORK_SEARCH_PATHS " ,
options . framework_search_paths . as_ref ( ) ,
) ;
host_env . insert (
" GCC_PREPROCESSOR_DEFINITIONS " ,
options . gcc_preprocessor_definitions . as_ref ( ) ,
) ;
host_env . insert ( " HEADER_SEARCH_PATHS " , options . header_search_paths . as_ref ( ) ) ;
2022-11-11 14:43:25 +00:00
2023-05-26 16:45:20 +00:00
let macos_target = Target ::macos ( ) ;
2022-11-11 14:43:25 +00:00
2023-05-26 16:45:20 +00:00
let isysroot = format! ( " -isysroot {} " , options . sdk_root . display ( ) ) ;
2022-08-23 00:59:17 +00:00
2023-11-14 01:35:43 +00:00
for arch in options . arches {
2023-05-26 16:45:20 +00:00
// Set target-specific flags
let ( env_triple , rust_triple ) = match arch . as_str ( ) {
" arm64 " = > ( " aarch64_apple_ios " , " aarch64-apple-ios " ) ,
" arm64-sim " = > ( " aarch64_apple_ios_sim " , " aarch64-apple-ios-sim " ) ,
" x86_64 " = > ( " x86_64_apple_ios " , " x86_64-apple-ios " ) ,
2023-11-14 01:35:43 +00:00
" Simulator " = > {
// when using Xcode, the arches for a simulator build will be ['Simulator', 'arm64-sim'] instead of ['arm64-sim']
// so we ignore that on our end
continue ;
}
2023-05-26 16:45:20 +00:00
_ = > {
return Err ( anyhow ::anyhow! (
" Arch specified by Xcode was invalid. {} isn't a known arch " ,
arch
) )
2022-12-28 18:02:07 +00:00
}
2023-05-26 16:45:20 +00:00
} ;
2023-04-13 21:26:32 +00:00
2023-05-26 16:45:20 +00:00
let interface = AppInterface ::new (
tauri_config . lock ( ) . unwrap ( ) . as_ref ( ) . unwrap ( ) ,
Some ( rust_triple . into ( ) ) ,
) ? ;
let cflags = format! ( " CFLAGS_ {} " , env_triple ) ;
let cxxflags = format! ( " CFLAGS_ {} " , env_triple ) ;
let objc_include_path = format! ( " OBJC_INCLUDE_PATH_ {} " , env_triple ) ;
let mut target_env = host_env . clone ( ) ;
target_env . insert ( cflags . as_ref ( ) , isysroot . as_ref ( ) ) ;
target_env . insert ( cxxflags . as_ref ( ) , isysroot . as_ref ( ) ) ;
target_env . insert ( objc_include_path . as_ref ( ) , include_dir . as_ref ( ) ) ;
let target = if macos {
& macos_target
} else {
Target ::for_arch ( & arch ) . ok_or_else ( | | {
anyhow ::anyhow! (
" Arch specified by Xcode was invalid. {} isn't a known arch " ,
arch
)
} ) ?
} ;
target . compile_lib (
& config ,
& metadata ,
cli_options . noise_level ,
true ,
profile ,
& env ,
target_env ,
) ? ;
let bin_path = interface
. app_settings ( )
. app_binary_path ( & InterfaceOptions {
debug : matches ! ( profile , Profile ::Debug ) ,
target : Some ( rust_triple . into ( ) ) ,
.. Default ::default ( )
} ) ? ;
let out_dir = bin_path . parent ( ) . unwrap ( ) ;
let lib_path = out_dir . join ( format! ( " lib {} .a " , config . app ( ) . lib_name ( ) ) ) ;
if ! lib_path . exists ( ) {
2024-07-12 12:03:30 +00:00
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 ( ) ) ) ;
2022-08-23 00:59:17 +00:00
}
2023-05-26 16:45:20 +00:00
let project_dir = config . project_dir ( ) ;
2023-11-14 01:35:43 +00:00
let externals_lib_dir = project_dir . join ( format! ( " Externals/ {arch} / {} " , profile . as_str ( ) ) ) ;
std ::fs ::create_dir_all ( & externals_lib_dir ) ? ;
2023-05-26 16:45:20 +00:00
std ::fs ::copy (
lib_path ,
2023-11-14 01:35:43 +00:00
externals_lib_dir . join ( format! ( " lib {} .a " , config . app ( ) . lib_name ( ) ) ) ,
2023-05-26 16:45:20 +00:00
) ? ;
}
Ok ( ( ) )
2022-08-23 00:59:17 +00:00
}