Skip to content

Commit

Permalink
fix(bundler/nsis): calculate estimated size on build system (#8233)
Browse files Browse the repository at this point in the history
* fix(bundler): Fix nsis installer taking longer than expected to install resources

* create dir structure for resources before extracting files

* calculate size in rust on the build system

* i'm sorry clippy, i programmed in unholy languages where += wasn't a thing so i forgot it exists in rust...

* i'm a better clippy than clippy🌚
  • Loading branch information
FabianLars authored Nov 15, 2023
1 parent 9e3aff0 commit 92bc7d0
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 18 deletions.
7 changes: 7 additions & 0 deletions .changes/nsis-slow-resources-installation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@tauri-apps/cli": patch:bug
"tauri-cli": patch:bug
"tauri-bundler": patch:bug
---

Fixes an issue in the NSIS installer which caused the installation to take much longer than expected when many `resources` were added to the bundle.
34 changes: 28 additions & 6 deletions tooling/bundler/src/bundle/windows/nsis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,23 +290,27 @@ fn build_nsis_app_installer(
.iter()
.find(|bin| bin.main())
.ok_or_else(|| anyhow::anyhow!("Failed to get main binary"))?;
let main_binary_path = settings.binary_path(main_binary).with_extension("exe");
data.insert(
"main_binary_name",
to_json(main_binary.name().replace(".exe", "")),
);
data.insert(
"main_binary_path",
to_json(settings.binary_path(main_binary).with_extension("exe")),
);
data.insert("main_binary_path", to_json(&main_binary_path));

let out_file = "nsis-output.exe";
data.insert("out_file", to_json(out_file));

let resources = generate_resource_data(settings)?;
data.insert("resources", to_json(resources));
let resources_dirs =
std::collections::HashSet::<PathBuf>::from_iter(resources.values().map(|r| r.0.to_owned()));
data.insert("resources_dirs", to_json(resources_dirs));
data.insert("resources", to_json(&resources));

let binaries = generate_binaries_data(settings)?;
data.insert("binaries", to_json(binaries));
data.insert("binaries", to_json(&binaries));

let estimated_size = generate_estimated_size(&main_binary_path, &binaries, &resources)?;
data.insert("estimated_size", to_json(estimated_size));

let silent_webview2_install = if let WebviewInstallMode::DownloadBootstrapper { silent }
| WebviewInstallMode::EmbedBootstrapper { silent }
Expand Down Expand Up @@ -552,6 +556,24 @@ fn generate_binaries_data(settings: &Settings) -> crate::Result<BinariesMap> {
Ok(binaries)
}

fn generate_estimated_size(
main: &Path,
binaries: &BinariesMap,
resources: &ResourcesMap,
) -> crate::Result<String> {
use std::fs::metadata;

let mut size = metadata(main)?.len();

for k in binaries.keys().chain(resources.keys()) {
size += metadata(k)?.len();
}

size /= 1000;

Ok(format!("{size:#08x}"))
}

fn get_lang_data(
lang: &str,
custom_lang_files: Option<&HashMap<String, PathBuf>>,
Expand Down
18 changes: 6 additions & 12 deletions tooling/bundler/src/bundle/windows/templates/installer.nsi
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ ${StrLoc}
!define UNINSTKEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCTNAME}"
!define MANUPRODUCTKEY "Software\${MANUFACTURER}\${PRODUCTNAME}"
!define UNINSTALLERSIGNCOMMAND "{{uninstaller_sign_cmd}}"
!define ESTIMATEDSIZE "{{estimated_size}}"

Name "${PRODUCTNAME}"
BrandingText "${COPYRIGHT}"
Expand Down Expand Up @@ -522,31 +523,26 @@ SectionEnd
app_check_done:
!macroend

Var AppSize
Section Install
SetOutPath $INSTDIR
StrCpy $AppSize 0

!insertmacro CheckIfAppIsRunning

; Copy main executable
File "${MAINBINARYSRCPATH}"
${GetSize} "$INSTDIR" "/M=${MAINBINARYNAME}.exe /S=0B" $0 $1 $2
IntOp $AppSize $AppSize + $0

; Copy resources
{{#each resources_dirs}}
; `\\` is not a typo.
CreateDirectory "$INSTDIR\\{{this}}"
{{/each}}
{{#each resources}}
CreateDirectory "$INSTDIR\\{{this.[0]}}"
File /a "/oname={{this.[1]}}" "{{@key}}"
${GetSize} "$INSTDIR" "/M={{this.[1]}} /S=0B" $0 $1 $2
IntOp $AppSize $AppSize + $0
{{/each}}

; Copy external binaries
{{#each binaries}}
File /a "/oname={{this}}" "{{@key}}"
${GetSize} "$INSTDIR" "/M={{this}} /S=0B" $0 $1 $2
IntOp $AppSize $AppSize + $0
{{/each}}

; Create uninstaller
Expand All @@ -570,9 +566,7 @@ Section Install
WriteRegStr SHCTX "${UNINSTKEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
WriteRegDWORD SHCTX "${UNINSTKEY}" "NoModify" "1"
WriteRegDWORD SHCTX "${UNINSTKEY}" "NoRepair" "1"
IntOp $AppSize $AppSize / 1000
IntFmt $AppSize "0x%08X" $AppSize
WriteRegDWORD SHCTX "${UNINSTKEY}" "EstimatedSize" "$AppSize"
WriteRegDWORD SHCTX "${UNINSTKEY}" "EstimatedSize" "${ESTIMATEDSIZE}"

; Create start menu shortcut (GUI)
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
Expand Down

0 comments on commit 92bc7d0

Please sign in to comment.