From a99a7c87ffd7ffaaa5fae1a17f731a59aac60581 Mon Sep 17 00:00:00 2001 From: Mike Maietta Date: Sun, 8 Aug 2021 20:37:34 -0700 Subject: [PATCH] feat: allow custom makensis and nsis logging (#6024) * feat: allowing a custom nsis binary to be specified. This will indirectly enable debugger logs for nsis installers (user specifies download url to nsis dev bundler). implements #5119 * update makensis to 3.0.4.2 --- .changeset/old-planes-look.md | 5 ++ packages/app-builder-lib/scheme.json | 66 ++++++++++++++++++- packages/app-builder-lib/src/binDownload.ts | 5 ++ .../src/targets/nsis/NsisTarget.ts | 7 +- .../src/targets/nsis/nsisOptions.ts | 36 ++++++++++ .../src/targets/nsis/nsisUtil.ts | 25 ++++++- .../app-builder-lib/templates/nsis/common.nsh | 14 ++++ .../templates/nsis/installer.nsi | 3 + .../templates/nsis/uninstaller.nsh | 3 + test/src/windows/assistedInstallerTest.ts | 28 ++++++++ 10 files changed, 187 insertions(+), 5 deletions(-) create mode 100644 .changeset/old-planes-look.md diff --git a/.changeset/old-planes-look.md b/.changeset/old-planes-look.md new file mode 100644 index 0000000000..c497e7a816 --- /dev/null +++ b/.changeset/old-planes-look.md @@ -0,0 +1,5 @@ +--- +"app-builder-lib": minor +--- + +feat: allowing custom makensis url to be specified and adding flag to enable debug logging for NSIS scripts diff --git a/packages/app-builder-lib/scheme.json b/packages/app-builder-lib/scheme.json index 4ebba1ecc0..bd2bcd5890 100644 --- a/packages/app-builder-lib/scheme.json +++ b/packages/app-builder-lib/scheme.json @@ -3447,6 +3447,38 @@ "description": "Whether to create start menu shortcut.", "type": "boolean" }, + "customNsisBinary": { + "description": "Allows providing the URL configuration for `makensis`.", + "type": [ + "null", + "object" + ], + "properties": { + "url": { + "description": "URL to download from", + "type": "string" + }, + "checksum": { + "description": "SHA256 to validate downloaded `makensis`", + "type": [ + "null", + "string" + ] + }, + "version": { + "description": "Version of `makensis` (used for caching)", + "type": [ + "null", + "string" + ] + } + } + }, + "debugLogging": { + "default": false, + "description": "Enables `LogText` to be used in `nsh` scripts", + "type": "boolean" + }, "deleteAppDataOnUninstall": { "default": false, "description": "*one-click installer only.* Whether to delete app data on uninstall.", @@ -3748,6 +3780,38 @@ "description": "Whether to create start menu shortcut.", "type": "boolean" }, + "customNsisBinary": { + "description": "Allows providing the URL configuration for `makensis`.", + "type": [ + "null", + "object" + ], + "properties": { + "url": { + "description": "URL to download from", + "type": "string" + }, + "checksum": { + "description": "SHA256 to validate downloaded `makensis`", + "type": [ + "null", + "string" + ] + }, + "version": { + "description": "Version of `makensis` (used for caching)", + "type": [ + "null", + "string" + ] + } + } + }, + "debugLogging": { + "default": false, + "description": "Enables `LogText` to be used in `nsh` scripts", + "type": "boolean" + }, "deleteAppDataOnUninstall": { "default": false, "description": "*one-click installer only.* Whether to delete app data on uninstall.", @@ -6581,4 +6645,4 @@ } }, "type": "object" -} +} \ No newline at end of file diff --git a/packages/app-builder-lib/src/binDownload.ts b/packages/app-builder-lib/src/binDownload.ts index f6141e2f69..7478192b26 100644 --- a/packages/app-builder-lib/src/binDownload.ts +++ b/packages/app-builder-lib/src/binDownload.ts @@ -10,6 +10,11 @@ export function download(url: string, output: string, checksum?: string | null): return executeAppBuilder(args) as Promise } +export function getBinFromCustomLoc(name: string, version: string, binariesLocUrl: string, checksum: string): Promise { + const dirName = `${name}-${version}` + return getBin(dirName, binariesLocUrl, checksum) +} + export function getBinFromUrl(name: string, version: string, checksum: string): Promise { const dirName = `${name}-${version}` let url: string diff --git a/packages/app-builder-lib/src/targets/nsis/NsisTarget.ts b/packages/app-builder-lib/src/targets/nsis/NsisTarget.ts index 8fcf0c1ebf..e2fce06e13 100644 --- a/packages/app-builder-lib/src/targets/nsis/NsisTarget.ts +++ b/packages/app-builder-lib/src/targets/nsis/NsisTarget.ts @@ -23,7 +23,7 @@ import { addCustomMessageFileInclude, createAddLangsMacro, LangConfigurator } fr import { computeLicensePage } from "./nsisLicense" import { NsisOptions, PortableOptions } from "./nsisOptions" import { NsisScriptGenerator } from "./nsisScriptGenerator" -import { AppPackageHelper, nsisTemplatesDir, NSIS_PATH, UninstallerReader } from "./nsisUtil" +import { AppPackageHelper, nsisTemplatesDir, NSIS_PATH, UninstallerReader, NsisTargetOptions } from "./nsisUtil" const debug = _debug("electron-builder:nsis") @@ -62,6 +62,8 @@ export class NsisTarget extends Target { if (deps != null && deps["electron-squirrel-startup"] != null) { log.warn('"electron-squirrel-startup" dependency is not required for NSIS') } + + NsisTargetOptions.resolve(this.options) } build(appOutDir: string, arch: Arch) { @@ -189,6 +191,9 @@ export class NsisTarget extends Target { APP_PACKAGE_NAME: appInfo.name, } + if (options.debugLogging) { + defines.ENABLE_LOGGING = null + } if (uninstallAppKey !== guid) { defines.UNINSTALL_REGISTRY_KEY_2 = `Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${guid}` } diff --git a/packages/app-builder-lib/src/targets/nsis/nsisOptions.ts b/packages/app-builder-lib/src/targets/nsis/nsisOptions.ts index 4aada863fe..41db6a6572 100644 --- a/packages/app-builder-lib/src/targets/nsis/nsisOptions.ts +++ b/packages/app-builder-lib/src/targets/nsis/nsisOptions.ts @@ -1,6 +1,28 @@ import { TargetSpecificOptions } from "../../core" import { CommonWindowsInstallerConfiguration } from "../.." +interface CustomNsisBinary { + /** + * @private + * @default https://github.com/electron-userland/electron-builder-binaries/releases/download + */ + + readonly url: string | null + + /** + * @private + * @default o+YZsXHp8LNihhuk7JsCDhdIgx0MKKK+1b3sGD+4zX5djZULe4/4QMcAsfQ+0r+a8FnwBt7BVBHkIkJHjKQ0sg== + */ + + readonly checksum?: string | null + + /** + * @private + * @default 3.0.4.2 + */ + + readonly version?: string | null +} export interface CommonNsisOptions { /** * Whether to create [Unicode installer](http://nsis.sourceforge.net/Docs/Chapter1.html#intro-unicode). @@ -24,6 +46,20 @@ export interface CommonNsisOptions { * @default false */ readonly useZip?: boolean + + /** + * @private + */ + readonly customNsisBinary?: CustomNsisBinary | null + + /** + * Whether or not to enable NSIS logging for debugging. + * Note: Requires a debug-enabled NSIS build. + * electron-builder's included `makensis` only supports building debug-enabled NSIS installers on Windows currently + * https://github.com/electron-userland/electron-builder/issues/5119#issuecomment-811353612 + * @private + */ + readonly debugLogging?: boolean | null } export interface NsisOptions extends CommonNsisOptions, CommonWindowsInstallerConfiguration, TargetSpecificOptions { diff --git a/packages/app-builder-lib/src/targets/nsis/nsisUtil.ts b/packages/app-builder-lib/src/targets/nsis/nsisUtil.ts index 716d96d97f..e096274f01 100644 --- a/packages/app-builder-lib/src/targets/nsis/nsisUtil.ts +++ b/packages/app-builder-lib/src/targets/nsis/nsisUtil.ts @@ -1,22 +1,41 @@ import { Arch, log } from "builder-util" import { PackageFileInfo } from "builder-util-runtime" -import { getBinFromUrl } from "../../binDownload" +import { getBinFromUrl, getBinFromCustomLoc } from "../../binDownload" import { copyFile } from "builder-util/out/fs" import * as path from "path" import { getTemplatePath } from "../../util/pathManager" import { NsisTarget } from "./NsisTarget" import * as fs from "fs/promises" import * as zlib from "zlib" +import { NsisOptions } from "./nsisOptions" export const nsisTemplatesDir = getTemplatePath("nsis") +export const NsisTargetOptions = (() => { + let _resolve: (options: NsisOptions) => any + const promise = new Promise(resolve => (_resolve = resolve)) + return { + then: (callback: (options: NsisOptions) => any): Promise => promise.then(callback), + resolve: (options: NsisOptions): any => _resolve(options), + } +})() + export const NSIS_PATH = () => { const custom = process.env.ELECTRON_BUILDER_NSIS_DIR if (custom != null && custom.length > 0) { return Promise.resolve(custom.trim()) } - // noinspection SpellCheckingInspection - return getBinFromUrl("nsis", "3.0.4.1", "VKMiizYdmNdJOWpRGz4trl4lD++BvYP2irAXpMilheUP0pc93iKlWAoP843Vlraj8YG19CVn0j+dCo/hURz9+Q==") + return NsisTargetOptions.then((options: NsisOptions) => { + if (options.customNsisBinary) { + const { checksum, url, version } = options.customNsisBinary + if (checksum && url) { + const binaryVersion = version || checksum.substr(0, 8) + return getBinFromCustomLoc("nsis", binaryVersion, url, checksum) + } + } + // noinspection SpellCheckingInspection + return getBinFromUrl("nsis", "3.0.4.2", "o+YZsXHp8LNihhuk7JsCDhdIgx0MKKK+1b3sGD+4zX5djZULe4/4QMcAsfQ+0r+a8FnwBt7BVBHkIkJHjKQ0sg==") + }) } export class AppPackageHelper { diff --git a/packages/app-builder-lib/templates/nsis/common.nsh b/packages/app-builder-lib/templates/nsis/common.nsh index d105a07707..77d9c7296f 100644 --- a/packages/app-builder-lib/templates/nsis/common.nsh +++ b/packages/app-builder-lib/templates/nsis/common.nsh @@ -99,3 +99,17 @@ Name "${PRODUCT_NAME}" ${StdUtils.ExecShellAsUser} $0 "$launchLink" "open" "$startAppArgs" !macroend + +!define LogSet "!insertmacro LogSetMacro" +!macro LogSetMacro SETTING + !ifdef ENABLE_LOGGING + LogSet ${SETTING} + !endif +!macroend + +!define LogText "!insertmacro LogTextMacro" +!macro LogTextMacro INPUT_TEXT + !ifdef ENABLE_LOGGING + LogText ${INPUT_TEXT} + !endif +!macroend \ No newline at end of file diff --git a/packages/app-builder-lib/templates/nsis/installer.nsi b/packages/app-builder-lib/templates/nsis/installer.nsi index a228a2945d..929762282b 100644 --- a/packages/app-builder-lib/templates/nsis/installer.nsi +++ b/packages/app-builder-lib/templates/nsis/installer.nsi @@ -40,6 +40,9 @@ Var oldMenuDirectory !endif Function .onInit + SetOutPath $INSTDIR + ${LogSet} on + !ifmacrodef preInit !insertmacro preInit !endif diff --git a/packages/app-builder-lib/templates/nsis/uninstaller.nsh b/packages/app-builder-lib/templates/nsis/uninstaller.nsh index 41089a358d..8db1f9acc2 100644 --- a/packages/app-builder-lib/templates/nsis/uninstaller.nsh +++ b/packages/app-builder-lib/templates/nsis/uninstaller.nsh @@ -3,6 +3,9 @@ Function un.checkAppRunning FunctionEnd Function un.onInit + SetOutPath $INSTDIR + ${LogSet} on + !insertmacro check64BitAndSetRegView ${If} ${Silent} diff --git a/test/src/windows/assistedInstallerTest.ts b/test/src/windows/assistedInstallerTest.ts index 14c797f39f..3a34e3da5d 100644 --- a/test/src/windows/assistedInstallerTest.ts +++ b/test/src/windows/assistedInstallerTest.ts @@ -117,6 +117,34 @@ test.ifAll.ifNotCiMac("assisted, MUI_HEADER as option", () => { ) }) +test.ifNotCiMac( + "custom makensis.exe", + app({ + targets: nsisTarget, + config: { + nsis: { + customNsisBinary: { + url: "https://github.com/electron-userland/electron-builder-binaries/releases/download/nsis-3.0.4.1/nsis-3.0.4.1.7z", + version: "3.0.4.1", + checksum: "VKMiizYdmNdJOWpRGz4trl4lD++BvYP2irAXpMilheUP0pc93iKlWAoP843Vlraj8YG19CVn0j+dCo/hURz9+Q==", + }, + }, + }, + }) +) + +test.ifNotCiMac( + "debug logging enabled", + app({ + targets: nsisTarget, + config: { + nsis: { + debugLogging: true, + }, + }, + }) +) + test.ifNotCiMac( "assisted, only perMachine", app({