2023-02-19 14:21:50 +00:00
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
2022-09-01 00:40:51 +00:00
use super ::{ env , with_config } ;
2022-12-12 13:36:47 +00:00
use crate ::{
helpers ::config ::get as get_config ,
interface ::{ AppInterface , AppSettings , Interface , Options as InterfaceOptions } ,
Result ,
} ;
2022-08-23 00:59:17 +00:00
2022-12-12 13:36:47 +00:00
use clap ::Parser ;
2023-03-21 16:43:09 +00:00
use tauri_mobile ::{ apple ::target ::Target , opts ::Profile } ;
2022-08-23 00:59:17 +00:00
2023-03-16 12:27:40 +00:00
use std ::{ collections ::HashMap , env ::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.
if var_os ( " npm_lifecycle_event " ) . is_none ( ) {
std ::env ::set_current_dir (
std ::env ::current_dir ( )
. unwrap ( )
. parent ( )
. unwrap ( )
. parent ( )
. unwrap ( ) ,
)
. unwrap ( ) ;
}
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 ) ;
2022-09-01 00:40:51 +00:00
with_config ( None , | _root_conf , config , metadata , cli_options | {
2023-03-21 16:43:09 +00:00
let env = env ( ) ? . explicit_env_vars ( cli_options . vars ) ;
2022-08-23 00:59:17 +00:00
if ! options . sdk_root . is_dir ( ) {
2022-08-28 18:32:50 +00:00
return Err ( anyhow ::anyhow! (
" SDK root provided by Xcode was invalid. {} doesn't exist or isn't a directory " ,
options . sdk_root . display ( ) ,
) ) ;
2022-08-23 00:59:17 +00:00
}
let include_dir = options . sdk_root . join ( " usr/include " ) ;
if ! include_dir . is_dir ( ) {
2022-08-28 18:32:50 +00:00
return Err ( anyhow ::anyhow! (
" Include dir was invalid. {} doesn't exist or isn't a directory " ,
include_dir . display ( )
) ) ;
2022-08-23 00:59:17 +00:00
}
2022-11-11 14:43:25 +00:00
// 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 ( ) {
return Err ( anyhow ::anyhow! (
" Invalid SDK root {} " ,
macos_sdk_root . display ( )
) ) ;
}
format! ( " -isysroot {} " , macos_sdk_root . display ( ) )
} ;
2022-08-23 00:59:17 +00:00
let mut host_env = HashMap ::< & str , & OsStr > ::new ( ) ;
host_env . insert ( " RUST_BACKTRACE " , " 1 " . as_ref ( ) ) ;
2022-11-11 14:43:25 +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 ( ) ) ;
host_env . insert (
" OBJC_INCLUDE_PATH_x86_64_apple_darwin " ,
include_dir . as_os_str ( ) ,
) ;
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-08-23 00:59:17 +00:00
let macos_target = Target ::macos ( ) ;
let isysroot = format! ( " -isysroot {} " , options . sdk_root . display ( ) ) ;
2022-12-12 13:36:47 +00:00
let tauri_config = get_config ( None ) ? ;
2023-02-24 13:22:59 +00:00
// when using Xcode, the arches will be ['Simulator', 'arm64'] instead of ['arm64-sim']
let arches = if options . arches . contains ( & " Simulator " . into ( ) ) {
vec! [ if cfg! ( target_arch = " aarch64 " ) {
" arm64-sim " . to_string ( )
} else {
" x86_64 " . to_string ( )
} ]
} else {
options . arches
} ;
for arch in arches {
2022-08-23 00:59:17 +00:00
// Set target-specific flags
2022-12-12 13:36:47 +00:00
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 " ) ,
2022-08-28 18:32:50 +00:00
_ = > {
return Err ( anyhow ::anyhow! (
" Arch specified by Xcode was invalid. {} isn't a known arch " ,
arch
) )
}
2022-08-23 00:59:17 +00:00
} ;
2022-12-12 13:36:47 +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 ) ;
2022-08-23 00:59:17 +00:00
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 {
2022-08-28 18:32:50 +00:00
Target ::for_arch ( & arch ) . ok_or_else ( | | {
anyhow ::anyhow! (
" Arch specified by Xcode was invalid. {} isn't a known arch " ,
arch
)
2022-08-23 00:59:17 +00:00
} ) ?
} ;
2022-08-28 18:32:50 +00:00
target . compile_lib (
config ,
metadata ,
cli_options . noise_level ,
true ,
profile ,
& env ,
target_env ,
) ? ;
2022-12-12 13:36:47 +00:00
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 ( ) ;
2023-01-06 17:31:48 +00:00
let lib_path = out_dir . join ( format! ( " lib {} .a " , config . app ( ) . lib_name ( ) ) ) ;
2022-12-28 18:02:07 +00:00
if ! lib_path . exists ( ) {
return Err ( anyhow ::anyhow! ( " Library not found at {}. Make sure your Cargo.toml file has a [lib] block with `crate-type = [ \" staticlib \" , \" cdylib \" , \" rlib \" ]` " , lib_path . display ( ) ) ) ;
}
2022-12-12 13:36:47 +00:00
std ::fs ::create_dir_all ( format! (
2023-02-24 13:22:59 +00:00
" gen/apple/Externals/{} " ,
2022-12-12 13:36:47 +00:00
profile . as_str ( )
) ) ? ;
std ::fs ::copy (
2022-12-28 18:02:07 +00:00
lib_path ,
2022-12-12 13:36:47 +00:00
format! (
2023-02-24 13:22:59 +00:00
" gen/apple/Externals/{}/lib{}.a " ,
2022-12-12 13:36:47 +00:00
profile . as_str ( ) ,
2023-01-06 17:31:48 +00:00
config . app ( ) . lib_name ( )
2022-12-12 13:36:47 +00:00
) ,
) ? ;
2022-08-23 00:59:17 +00:00
}
Ok ( ( ) )
} )
. map_err ( Into ::into )
}