build.rs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use tauri_bundler::bundle::{
  5. bundle_project, common::print_signed_updater_archive, PackageType, SettingsBuilder,
  6. };
  7. use crate::helpers::{
  8. app_paths::{app_dir, tauri_dir},
  9. config::get as get_config,
  10. execute_with_output,
  11. manifest::rewrite_manifest,
  12. updater_signature::sign_file_from_env_variables,
  13. Logger,
  14. };
  15. use std::{env::set_current_dir, fs::rename, path::PathBuf, process::Command};
  16. mod rust;
  17. #[derive(Default)]
  18. pub struct Build {
  19. debug: bool,
  20. verbose: bool,
  21. targets: Option<Vec<String>>,
  22. config: Option<String>,
  23. }
  24. impl Build {
  25. pub fn new() -> Self {
  26. Default::default()
  27. }
  28. pub fn debug(mut self) -> Self {
  29. self.debug = true;
  30. self
  31. }
  32. pub fn verbose(mut self) -> Self {
  33. self.verbose = true;
  34. self
  35. }
  36. pub fn targets(mut self, targets: Vec<String>) -> Self {
  37. self.targets = Some(targets);
  38. self
  39. }
  40. pub fn config(mut self, config: String) -> Self {
  41. self.config.replace(config);
  42. self
  43. }
  44. pub fn run(self) -> crate::Result<()> {
  45. let logger = Logger::new("tauri:build");
  46. let config = get_config(self.config.as_deref())?;
  47. let tauri_path = tauri_dir();
  48. set_current_dir(&tauri_path)?;
  49. rewrite_manifest(config.clone())?;
  50. let config_guard = config.lock().unwrap();
  51. let config_ = config_guard.as_ref().unwrap();
  52. let web_asset_path = PathBuf::from(&config_.build.dist_dir);
  53. if !web_asset_path.exists() {
  54. return Err(anyhow::anyhow!(
  55. "Unable to find your web assets, did you forget to build your web app? Your distDir is set to \"{:?}\".",
  56. web_asset_path
  57. ));
  58. }
  59. if let Some(before_build) = &config_.build.before_build_command {
  60. if !before_build.is_empty() {
  61. logger.log(format!("Running `{}`", before_build));
  62. #[cfg(target_os = "windows")]
  63. execute_with_output(
  64. &mut Command::new("cmd")
  65. .arg("/C")
  66. .arg(before_build)
  67. .current_dir(app_dir()),
  68. )?;
  69. #[cfg(not(target_os = "windows"))]
  70. execute_with_output(
  71. &mut Command::new("sh")
  72. .arg("-c")
  73. .arg(before_build)
  74. .current_dir(app_dir()),
  75. )?;
  76. }
  77. }
  78. rust::build_project(self.debug)?;
  79. let app_settings = rust::AppSettings::new(&config_)?;
  80. let out_dir = app_settings.get_out_dir(self.debug)?;
  81. if let Some(product_name) = config_.package.product_name.clone() {
  82. let bin_name = app_settings.cargo_package_settings().name.clone();
  83. #[cfg(windows)]
  84. rename(
  85. out_dir.join(format!("{}.exe", bin_name)),
  86. out_dir.join(format!("{}.exe", product_name)),
  87. )?;
  88. #[cfg(not(windows))]
  89. rename(out_dir.join(bin_name), out_dir.join(product_name))?;
  90. }
  91. if config_.tauri.bundle.active {
  92. // move merge modules to the out dir so the bundler can load it
  93. #[cfg(windows)]
  94. {
  95. let (filename, vcruntime_msm) = if cfg!(target_arch = "x86") {
  96. let _ = std::fs::remove_file(out_dir.join("Microsoft_VC142_CRT_x64.msm"));
  97. (
  98. "Microsoft_VC142_CRT_x86.msm",
  99. include_bytes!("./MergeModules/Microsoft_VC142_CRT_x86.msm").to_vec(),
  100. )
  101. } else {
  102. let _ = std::fs::remove_file(out_dir.join("Microsoft_VC142_CRT_x86.msm"));
  103. (
  104. "Microsoft_VC142_CRT_x64.msm",
  105. include_bytes!("./MergeModules/Microsoft_VC142_CRT_x64.msm").to_vec(),
  106. )
  107. };
  108. std::fs::write(out_dir.join(filename), vcruntime_msm)?;
  109. }
  110. let mut settings_builder = SettingsBuilder::new()
  111. .package_settings(app_settings.get_package_settings())
  112. .bundle_settings(app_settings.get_bundle_settings(&config_)?)
  113. .binaries(app_settings.get_binaries(&config_)?)
  114. .project_out_directory(out_dir);
  115. if self.verbose {
  116. settings_builder = settings_builder.verbose();
  117. }
  118. if let Some(names) = self.targets {
  119. let mut types = vec![];
  120. for name in names {
  121. if name == "none" {
  122. break;
  123. }
  124. match PackageType::from_short_name(&name) {
  125. Some(package_type) => {
  126. types.push(package_type);
  127. }
  128. None => {
  129. return Err(anyhow::anyhow!(format!(
  130. "Unsupported bundle format: {}",
  131. name
  132. )));
  133. }
  134. }
  135. }
  136. settings_builder = settings_builder.package_types(types);
  137. }
  138. // Bundle the project
  139. let settings = settings_builder.build()?;
  140. let bundles = bundle_project(settings)?;
  141. // If updater is active and pubkey is available
  142. if config_.tauri.updater.active && config_.tauri.updater.pubkey.is_some() {
  143. // make sure we have our package builts
  144. let mut signed_paths = Vec::new();
  145. for elem in bundles
  146. .iter()
  147. .filter(|bundle| bundle.package_type == PackageType::Updater)
  148. {
  149. // we expect to have only one path in the vec but we iter if we add
  150. // another type of updater package who require multiple file signature
  151. for path in elem.bundle_paths.iter() {
  152. // sign our path from environment variables
  153. let (signature_path, _signature) = sign_file_from_env_variables(path)?;
  154. signed_paths.append(&mut vec![signature_path]);
  155. }
  156. }
  157. if !signed_paths.is_empty() {
  158. print_signed_updater_archive(&signed_paths)?;
  159. }
  160. }
  161. }
  162. Ok(())
  163. }
  164. }