|
@@ -21,7 +21,7 @@ use std::{
|
|
|
path::{Path, PathBuf},
|
|
|
process::Command,
|
|
|
};
|
|
|
-use tauri_utils::resources::resource_relpath;
|
|
|
+use tauri_utils::{config::WebviewInstallMode, resources::resource_relpath};
|
|
|
use uuid::Uuid;
|
|
|
use zip::ZipArchive;
|
|
|
|
|
@@ -29,6 +29,11 @@ use zip::ZipArchive;
|
|
|
pub const WIX_URL: &str =
|
|
|
"https://github.com/wixtoolset/wix3/releases/download/wix3112rtm/wix311-binaries.zip";
|
|
|
pub const WIX_SHA256: &str = "2c1888d5d1dba377fc7fa14444cf556963747ff9a0a289a3599cf09da03b9e2e";
|
|
|
+pub const MSI_FOLDER_NAME: &str = "msi";
|
|
|
+pub const MSI_UPDATER_FOLDER_NAME: &str = "msi-updater";
|
|
|
+const WEBVIEW2_BOOTSTRAPPER_URL: &str = "https://go.microsoft.com/fwlink/p/?LinkId=2124703";
|
|
|
+const WEBVIEW2_X86_INSTALLER_GUID: &str = "a17bde80-b5ab-47b5-8bbb-1cbe93fc6ec9";
|
|
|
+const WEBVIEW2_X64_INSTALLER_GUID: &str = "aa5fd9b3-dc11-4cbc-8343-a50f57b311e1";
|
|
|
|
|
|
// For Cross Platform Compilation.
|
|
|
|
|
@@ -151,7 +156,7 @@ fn copy_icon(settings: &Settings, filename: &str, path: &Path) -> crate::Result<
|
|
|
let base_dir = settings.project_out_directory();
|
|
|
|
|
|
let resource_dir = base_dir.join("resources");
|
|
|
- std::fs::create_dir_all(&resource_dir)?;
|
|
|
+ create_dir_all(&resource_dir)?;
|
|
|
let icon_target_path = resource_dir.join(filename);
|
|
|
|
|
|
let icon_path = std::env::current_dir()?.join(&path);
|
|
@@ -168,14 +173,15 @@ fn copy_icon(settings: &Settings, filename: &str, path: &Path) -> crate::Result<
|
|
|
Ok(icon_target_path)
|
|
|
}
|
|
|
|
|
|
-/// Function used to download Wix and VC_REDIST. Checks SHA256 to verify the download.
|
|
|
-fn download_and_verify(url: &str, hash: &str) -> crate::Result<Vec<u8>> {
|
|
|
+fn download(url: &str) -> crate::Result<Vec<u8>> {
|
|
|
info!(action = "Downloading"; "{}", url);
|
|
|
-
|
|
|
let response = attohttpc::get(url).send()?;
|
|
|
+ response.bytes().map_err(Into::into)
|
|
|
+}
|
|
|
|
|
|
- let data: Vec<u8> = response.bytes()?;
|
|
|
-
|
|
|
+/// Function used to download Wix. Checks SHA256 to verify the download.
|
|
|
+fn download_and_verify(url: &str, hash: &str) -> crate::Result<Vec<u8>> {
|
|
|
+ let data = download(url)?;
|
|
|
info!("validating hash");
|
|
|
|
|
|
let mut hasher = sha2::Sha256::new();
|
|
@@ -192,7 +198,11 @@ fn download_and_verify(url: &str, hash: &str) -> crate::Result<Vec<u8>> {
|
|
|
}
|
|
|
|
|
|
/// The app installer output path.
|
|
|
-fn app_installer_output_path(settings: &Settings, language: &str) -> crate::Result<PathBuf> {
|
|
|
+fn app_installer_output_path(
|
|
|
+ settings: &Settings,
|
|
|
+ language: &str,
|
|
|
+ updater: bool,
|
|
|
+) -> crate::Result<PathBuf> {
|
|
|
let arch = match settings.binary_arch() {
|
|
|
"x86" => "x86",
|
|
|
"x86_64" => "x64",
|
|
@@ -212,12 +222,15 @@ fn app_installer_output_path(settings: &Settings, language: &str) -> crate::Resu
|
|
|
language,
|
|
|
);
|
|
|
|
|
|
- Ok(
|
|
|
- settings
|
|
|
- .project_out_directory()
|
|
|
- .to_path_buf()
|
|
|
- .join(format!("bundle/msi/{}.msi", package_base_name)),
|
|
|
- )
|
|
|
+ Ok(settings.project_out_directory().to_path_buf().join(format!(
|
|
|
+ "bundle/{}/{}.msi",
|
|
|
+ if updater {
|
|
|
+ MSI_UPDATER_FOLDER_NAME
|
|
|
+ } else {
|
|
|
+ MSI_FOLDER_NAME
|
|
|
+ },
|
|
|
+ package_base_name
|
|
|
+ )))
|
|
|
}
|
|
|
|
|
|
/// Extracts the zips from Wix and VC_REDIST into a useable path.
|
|
@@ -370,6 +383,7 @@ fn validate_version(version: &str) -> anyhow::Result<()> {
|
|
|
pub fn build_wix_app_installer(
|
|
|
settings: &Settings,
|
|
|
wix_toolset_path: &Path,
|
|
|
+ updater: bool,
|
|
|
) -> crate::Result<Vec<PathBuf>> {
|
|
|
let arch = match settings.binary_arch() {
|
|
|
"x86_64" => "x64",
|
|
@@ -421,13 +435,107 @@ pub fn build_wix_app_installer(
|
|
|
|
|
|
try_sign(&app_exe_source)?;
|
|
|
|
|
|
- // ensure that `target/{release, debug}/wix` folder exists
|
|
|
- std::fs::create_dir_all(settings.project_out_directory().join("wix"))?;
|
|
|
-
|
|
|
let output_path = settings.project_out_directory().join("wix").join(arch);
|
|
|
|
|
|
+ if output_path.exists() {
|
|
|
+ remove_dir_all(&output_path)?;
|
|
|
+ }
|
|
|
+ create_dir_all(&output_path)?;
|
|
|
+
|
|
|
let mut data = BTreeMap::new();
|
|
|
|
|
|
+ let silent_webview_install = if let WebviewInstallMode::DownloadBootstrapper { silent }
|
|
|
+ | WebviewInstallMode::EmbedBootstrapper { silent }
|
|
|
+ | WebviewInstallMode::OfflineInstaller { silent } =
|
|
|
+ settings.windows().webview_install_mode
|
|
|
+ {
|
|
|
+ silent
|
|
|
+ } else {
|
|
|
+ true
|
|
|
+ };
|
|
|
+
|
|
|
+ let webview_install_mode = if updater {
|
|
|
+ WebviewInstallMode::DownloadBootstrapper {
|
|
|
+ silent: silent_webview_install,
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ let mut webview_install_mode = settings.windows().webview_install_mode.clone();
|
|
|
+ if let Some(fixed_runtime_path) = settings.windows().webview_fixed_runtime_path.clone() {
|
|
|
+ webview_install_mode = WebviewInstallMode::FixedRuntime {
|
|
|
+ path: fixed_runtime_path,
|
|
|
+ };
|
|
|
+ } else if let Some(wix) = &settings.windows().wix {
|
|
|
+ if wix.skip_webview_install {
|
|
|
+ webview_install_mode = WebviewInstallMode::Skip;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ webview_install_mode
|
|
|
+ };
|
|
|
+
|
|
|
+ data.insert("install_webview", to_json(true));
|
|
|
+ data.insert(
|
|
|
+ "webview_installer_args",
|
|
|
+ to_json(if silent_webview_install {
|
|
|
+ "/silent"
|
|
|
+ } else {
|
|
|
+ ""
|
|
|
+ }),
|
|
|
+ );
|
|
|
+
|
|
|
+ match webview_install_mode {
|
|
|
+ WebviewInstallMode::Skip | WebviewInstallMode::FixedRuntime { .. } => {
|
|
|
+ data.insert("install_webview", to_json(false));
|
|
|
+ }
|
|
|
+ WebviewInstallMode::DownloadBootstrapper { silent: _ } => {
|
|
|
+ data.insert("download_bootstrapper", to_json(true));
|
|
|
+ data.insert(
|
|
|
+ "webview_installer_args",
|
|
|
+ to_json(if silent_webview_install {
|
|
|
+ "'/silent',"
|
|
|
+ } else {
|
|
|
+ ""
|
|
|
+ }),
|
|
|
+ );
|
|
|
+ }
|
|
|
+ WebviewInstallMode::EmbedBootstrapper { silent: _ } => {
|
|
|
+ let webview2_bootstrapper_path = output_path.join("MicrosoftEdgeWebview2Setup.exe");
|
|
|
+ std::fs::write(
|
|
|
+ &webview2_bootstrapper_path,
|
|
|
+ download(WEBVIEW2_BOOTSTRAPPER_URL)?,
|
|
|
+ )?;
|
|
|
+ data.insert(
|
|
|
+ "webview2_bootstrapper_path",
|
|
|
+ to_json(webview2_bootstrapper_path),
|
|
|
+ );
|
|
|
+ }
|
|
|
+ WebviewInstallMode::OfflineInstaller { silent: _ } => {
|
|
|
+ let guid = if arch == "x64" {
|
|
|
+ WEBVIEW2_X64_INSTALLER_GUID
|
|
|
+ } else {
|
|
|
+ WEBVIEW2_X86_INSTALLER_GUID
|
|
|
+ };
|
|
|
+ let mut offline_installer_path = dirs_next::cache_dir().unwrap();
|
|
|
+ offline_installer_path.push("tauri");
|
|
|
+ offline_installer_path.push(guid);
|
|
|
+ offline_installer_path.push(arch);
|
|
|
+ create_dir_all(&offline_installer_path)?;
|
|
|
+ let webview2_installer_path =
|
|
|
+ offline_installer_path.join("MicrosoftEdgeWebView2RuntimeInstaller.exe");
|
|
|
+ if !webview2_installer_path.exists() {
|
|
|
+ std::fs::write(
|
|
|
+ &webview2_installer_path,
|
|
|
+ download(
|
|
|
+ &format!("https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/{}/MicrosoftEdgeWebView2RuntimeInstaller{}.exe",
|
|
|
+ guid,
|
|
|
+ arch.to_uppercase(),
|
|
|
+ ),
|
|
|
+ )?,
|
|
|
+ )?;
|
|
|
+ }
|
|
|
+ data.insert("webview2_installer_path", to_json(webview2_installer_path));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
let language_map: HashMap<String, LanguageMetadata> =
|
|
|
serde_json::from_str(include_str!("./languages.json")).unwrap();
|
|
|
|
|
@@ -521,7 +629,6 @@ pub fn build_wix_app_installer(
|
|
|
let mut fragment_paths = Vec::new();
|
|
|
let mut handlebars = Handlebars::new();
|
|
|
let mut has_custom_template = false;
|
|
|
- let mut install_webview = settings.windows().webview_fixed_runtime_path.is_none();
|
|
|
let mut enable_elevated_update_task = false;
|
|
|
|
|
|
if let Some(wix) = &settings.windows().wix {
|
|
@@ -531,9 +638,6 @@ pub fn build_wix_app_installer(
|
|
|
data.insert("feature_refs", to_json(&wix.feature_refs));
|
|
|
data.insert("merge_refs", to_json(&wix.merge_refs));
|
|
|
fragment_paths = wix.fragment_paths.clone();
|
|
|
- if wix.skip_webview_install {
|
|
|
- install_webview = false;
|
|
|
- }
|
|
|
enable_elevated_update_task = wix.enable_elevated_update_task;
|
|
|
|
|
|
if let Some(temp_path) = &wix.template {
|
|
@@ -577,16 +681,6 @@ pub fn build_wix_app_installer(
|
|
|
.expect("Failed to setup handlebar template");
|
|
|
}
|
|
|
|
|
|
- if install_webview {
|
|
|
- data.insert("install_webview", to_json(true));
|
|
|
- }
|
|
|
-
|
|
|
- if output_path.exists() {
|
|
|
- remove_dir_all(&output_path)?;
|
|
|
- }
|
|
|
-
|
|
|
- create_dir_all(&output_path)?;
|
|
|
-
|
|
|
if enable_elevated_update_task {
|
|
|
data.insert(
|
|
|
"msiexec_args",
|
|
@@ -715,7 +809,7 @@ pub fn build_wix_app_installer(
|
|
|
"*.wixobj".into(),
|
|
|
];
|
|
|
let msi_output_path = output_path.join("output.msi");
|
|
|
- let msi_path = app_installer_output_path(settings, &language)?;
|
|
|
+ let msi_path = app_installer_output_path(settings, &language, updater)?;
|
|
|
create_dir_all(msi_path.parent().unwrap())?;
|
|
|
|
|
|
info!(action = "Running"; "light to produce {}", msi_path.display());
|