Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow custom makensis and logging #6024

Merged
merged 13 commits into from Aug 9, 2021
5 changes: 5 additions & 0 deletions packages/app-builder-lib/src/binDownload.ts
Expand Up @@ -10,6 +10,11 @@ export function download(url: string, output: string, checksum?: string | null):
return executeAppBuilder(args) as Promise<any>
}

export function getBinFromCustomLoc(name: string, version: string, binariesLocUrl: string, checksum: string): Promise<string> {
const dirName = `${name}-${version}`
return getBin(dirName, binariesLocUrl, checksum)
}

export function getBinFromUrl(name: string, version: string, checksum: string): Promise<string> {
const dirName = `${name}-${version}`
let url: string
Expand Down
7 changes: 6 additions & 1 deletion packages/app-builder-lib/src/targets/nsis/NsisTarget.ts
Expand Up @@ -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")

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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}`
}
Expand Down
35 changes: 35 additions & 0 deletions 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).
Expand All @@ -24,6 +46,19 @@ 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
* https://github.com/electron-userland/electron-builder/issues/5119#issuecomment-811353612
* @private
*/
readonly debugLogging?: boolean | null
}

export interface NsisOptions extends CommonNsisOptions, CommonWindowsInstallerConfiguration, TargetSpecificOptions {
Expand Down
25 changes: 22 additions & 3 deletions 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<NsisOptions>(resolve => (_resolve = resolve))
return {
then: (callback: (options: NsisOptions) => any): Promise<string> => 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==")
Copy link
Collaborator Author

@mmaietta mmaietta Jul 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@develar I tried to update to 3.0.5.0 that is uploaded in electron-builder-binaries, but that throws CI errors:

    Command line defined: "UNINSTALLER_OUT_FILE=C:\Users\RUNNER~1\AppData\Local\Temp\et-d8d6360ca6c99632f01b203b451e295c\t-oEMxqx\test-project-0\dist\__uninstaller-nsis-TestApp.exe"
    Processing config: C:\Users\runneradmin\AppData\Local\electron-builder\Cache\nsis\nsis-3.0.5.0\nsisconf.nsh
    Processing script file: "<stdin>" (ACP)

    Error output:
    Bad text encoding
    Error in macro MUI_LANGUAGEEX on macroline 13
    Error in macro MUI_LANGUAGE on macroline 4
    Error in macro addLangs on macroline 5
    Error in script "<stdin>" on line 112 -- aborting creation process

I couldn't easily identify why (MUI_LANGUAGEEX is no where in the codebase AFAICT) and 3.0.4.2 seems to have the log and max string length compiler flags enabled, so I'm just upgrading to that patch version here.

Copy link
Collaborator Author

@mmaietta mmaietta Jul 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@develar it happens here AFAICT
LoadLanguageFile "${LangDir}\${NLFID}.nlf"
https://github.com/electron-userland/electron-builder-binaries/blob/ec807af771a341b93d122734a9a1d6d2ae9bf90a/nsis/Contrib/Modern%20UI%202/Localization.nsh#L42

My best guess is that this file is no longer valid for newer versions of makensis:
https://github.com/electron-userland/electron-builder-binaries/blob/master/nsis-lang-fixes/SimpChinese.nlf

Alternatively, we could upgrade to makensis 3.0.6.1, but I'm struggling to figure out how to compile it for both windows & mac on my hackintosh.

})
}

export class AppPackageHelper {
Expand Down
15 changes: 15 additions & 0 deletions packages/app-builder-lib/templates/nsis/common.nsh
Expand Up @@ -10,6 +10,7 @@ SpaceTexts none
FileBufSize 64
Name "${PRODUCT_NAME}"

!define ENABLE_LOGGING
!define APP_EXECUTABLE_FILENAME "${PRODUCT_FILENAME}.exe"
!define UNINSTALL_FILENAME "Uninstall ${PRODUCT_FILENAME}.exe"

Expand Down Expand Up @@ -99,3 +100,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
3 changes: 3 additions & 0 deletions packages/app-builder-lib/templates/nsis/installer.nsi
Expand Up @@ -40,6 +40,9 @@ Var oldMenuDirectory
!endif

Function .onInit
SetOutPath $INSTDIR
${LogSet} on

!ifmacrodef preInit
!insertmacro preInit
!endif
Expand Down
3 changes: 3 additions & 0 deletions packages/app-builder-lib/templates/nsis/uninstaller.nsh
@@ -1,4 +1,7 @@
Function un.onInit
SetOutPath $INSTDIR
${LogSet} on

!insertmacro check64BitAndSetRegView

${IfNot} ${Silent}
Expand Down
7 changes: 2 additions & 5 deletions test/src/BuildTest.ts
Expand Up @@ -367,11 +367,8 @@ test.ifDevOrLinuxCi(
files: [
// test ignore pattern for node_modules defined as file set filter
{
filter: [
"!node_modules/napi-build-utils/napi-build-utils-1.0.0.tgz",
"!node_modules/node-abi/*"
]
}
filter: ["!node_modules/napi-build-utils/napi-build-utils-1.0.0.tgz", "!node_modules/node-abi/*"],
},
],
},
},
Expand Down
13 changes: 6 additions & 7 deletions test/src/ignoreTest.ts
Expand Up @@ -114,7 +114,7 @@ test.ifDevOrLinuxCi(
targets: Platform.LINUX.createTarget(DIR_TARGET),
config: {
asar: false,
includeSubNodeModules: false // defaults to false too
includeSubNodeModules: false, // defaults to false too
},
},
{
Expand Down Expand Up @@ -148,7 +148,7 @@ test.ifDevOrLinuxCi(
targets: Platform.LINUX.createTarget(DIR_TARGET),
config: {
asar: false,
includeSubNodeModules: true
includeSubNodeModules: true,
},
},
{
Expand Down Expand Up @@ -182,10 +182,7 @@ test.ifDevOrLinuxCi(
targets: Platform.LINUX.createTarget(DIR_TARGET),
config: {
asar: false,
files: [
"**/*",
"*/submodule-1-test/node_modules/**",
],
files: ["**/*", "*/submodule-1-test/node_modules/**"],
},
},
{
Expand All @@ -205,7 +202,9 @@ test.ifDevOrLinuxCi(
packed: context => {
return Promise.all([
assertThat(path.join(context.getResources(Platform.LINUX, archFromString(process.arch)), "app", "node_modules", "submodule-1-test", "node_modules")).isDirectory(),
assertThat(path.join(context.getResources(Platform.LINUX, archFromString(process.arch)), "app", "node_modules", "submodule-1-test", "node_modules", "package.json")).isFile(),
assertThat(
path.join(context.getResources(Platform.LINUX, archFromString(process.arch)), "app", "node_modules", "submodule-1-test", "node_modules", "package.json")
).isFile(),
assertThat(path.join(context.getResources(Platform.LINUX, archFromString(process.arch)), "app", "node_modules", "submodule-2-test", "node_modules")).doesNotExist(),
])
},
Expand Down