build.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. use super::{
  2. detect_target_ok, ensure_init, env, init_dot_cargo, log_finished, open_and_wait, with_config,
  3. MobileTarget,
  4. };
  5. use crate::{
  6. helpers::flock,
  7. interface::{AppSettings, Interface, Options as InterfaceOptions},
  8. mobile::{write_options, CliOptions},
  9. Result,
  10. };
  11. use clap::{ArgAction, Parser};
  12. use tauri_mobile::{
  13. apple::{config::Config as AppleConfig, target::Target},
  14. env::Env,
  15. opts::{NoiseLevel, Profile},
  16. target::{call_for_targets_with_fallback, TargetInvalid, TargetTrait},
  17. };
  18. use std::fs;
  19. #[derive(Debug, Clone, Parser)]
  20. #[clap(about = "iOS build")]
  21. pub struct Options {
  22. /// Builds with the debug flag
  23. #[clap(short, long)]
  24. pub debug: bool,
  25. /// Which targets to build.
  26. #[clap(
  27. short,
  28. long = "target",
  29. action = ArgAction::Append,
  30. num_args(0..),
  31. default_value = Target::DEFAULT_KEY,
  32. value_parser(clap::builder::PossibleValuesParser::new(Target::name_list()))
  33. )]
  34. pub targets: Vec<String>,
  35. /// List of cargo features to activate
  36. #[clap(short, long, action = ArgAction::Append, num_args(0..))]
  37. pub features: Option<Vec<String>>,
  38. /// JSON string or path to JSON file to merge with tauri.conf.json
  39. #[clap(short, long)]
  40. pub config: Option<String>,
  41. /// Build number to append to the app version.
  42. #[clap(long)]
  43. pub build_number: Option<u32>,
  44. /// Open Xcode
  45. #[clap(short, long)]
  46. pub open: bool,
  47. }
  48. impl From<Options> for crate::build::Options {
  49. fn from(options: Options) -> Self {
  50. Self {
  51. runner: None,
  52. debug: options.debug,
  53. target: None,
  54. features: options.features,
  55. bundles: None,
  56. config: options.config,
  57. args: Vec::new(),
  58. }
  59. }
  60. }
  61. pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
  62. with_config(
  63. Some(Default::default()),
  64. |app, config, _metadata, _cli_options| {
  65. ensure_init(config.project_dir(), MobileTarget::Ios)?;
  66. let mut env = env()?;
  67. init_dot_cargo(app, None)?;
  68. let open = options.open;
  69. run_build(options, config, &mut env, noise_level)?;
  70. if open {
  71. open_and_wait(config, &env);
  72. }
  73. Ok(())
  74. },
  75. )
  76. .map_err(Into::into)
  77. }
  78. fn run_build(
  79. mut options: Options,
  80. config: &AppleConfig,
  81. env: &mut Env,
  82. noise_level: NoiseLevel,
  83. ) -> Result<()> {
  84. let profile = if options.debug {
  85. Profile::Debug
  86. } else {
  87. Profile::Release
  88. };
  89. let mut build_options = options.clone().into();
  90. let interface = crate::build::setup(&mut build_options, true)?;
  91. let app_settings = interface.app_settings();
  92. let bin_path = app_settings.app_binary_path(&InterfaceOptions {
  93. debug: build_options.debug,
  94. ..Default::default()
  95. })?;
  96. let out_dir = bin_path.parent().unwrap();
  97. let _lock = flock::open_rw(&out_dir.join("lock").with_extension("ios"), "iOS")?;
  98. let cli_options = CliOptions {
  99. features: build_options.features.clone(),
  100. args: build_options.args.clone(),
  101. noise_level,
  102. vars: Default::default(),
  103. };
  104. let _handle = write_options(cli_options, env)?;
  105. options
  106. .features
  107. .get_or_insert(Vec::new())
  108. .push("custom-protocol".into());
  109. let mut out_files = Vec::new();
  110. call_for_targets_with_fallback(
  111. options.targets.iter(),
  112. &detect_target_ok,
  113. env,
  114. |target: &Target| -> Result<()> {
  115. let mut app_version = config.bundle_version().clone();
  116. if let Some(build_number) = options.build_number {
  117. app_version.push_extra(build_number);
  118. }
  119. target.build(config, env, noise_level, profile)?;
  120. target.archive(config, env, noise_level, profile, Some(app_version))?;
  121. target.export(config, env, noise_level)?;
  122. if let Ok(ipa_path) = config.ipa_path() {
  123. let out_dir = config.export_dir().join(target.arch);
  124. fs::create_dir_all(&out_dir)?;
  125. let path = out_dir.join(ipa_path.file_name().unwrap());
  126. fs::rename(&ipa_path, &path)?;
  127. out_files.push(path);
  128. }
  129. Ok(())
  130. },
  131. )
  132. .map_err(|e: TargetInvalid| anyhow::anyhow!(e.to_string()))??;
  133. log_finished(out_files, "IPA");
  134. Ok(())
  135. }