From 962ecb9d6ab6f4bf6eb83fe19df789d42b112cc5 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 17 Feb 2025 09:38:53 +0000 Subject: [PATCH] Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .github/workflows/build_and_test.yaml | 25 +- ...tron-builder-squirrel-windows+26.0.6.patch | 220 +++++++++++++----- 2 files changed, 168 insertions(+), 77 deletions(-) diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml index c8fe3577..0cea1bd2 100644 --- a/.github/workflows/build_and_test.yaml +++ b/.github/workflows/build_and_test.yaml @@ -22,7 +22,7 @@ jobs: uses: ./.github/workflows/build_windows.yaml strategy: matrix: - arch: [x64] + arch: [x64, ia32, arm64] with: arch: ${{ matrix.arch }} @@ -82,25 +82,14 @@ jobs: artifact: linux-arm64-sqlcipher-static executable: "/opt/Element/element-desktop" prepare_cmd: "sudo apt-get -qq update && sudo apt install -y ./dist/*.deb" - # - name: Windows (x86) Squirrel - # os: windows-2022 - # artifact: win-ia32 - # executable: "./dist/win-ia32-unpacked/Element.exe" - # - name: Windows (x86) MSI - # os: windows-2022 - # artifact: win-ia32 - # executable: "C:/Program Files (x86)/Element/Element*.exe" - # prepare_cmd: "msiexec ./dist/Element*.msi" - - name: Windows (x64) Squirrel + - name: Windows (x86) + os: windows-2022 + artifact: win-ia32 + executable: "./dist/win-ia32-unpacked/Element.exe" + - name: Windows (x64) os: windows-2022 artifact: win-x64 - executable: "%LOCALAPPDATA%/element-desktop*/Element.exe" - prepare_cmd: "./dist/squirrel-windows*/Element Setup*.exe" - - name: Windows (x64) MSI - os: windows-2022 - artifact: win-x64 - executable: "C:/Program Files/Element/Element*.exe" - prepare_cmd: "msiexec ./dist/Element*.msi" + executable: "./dist/win-unpacked/Element.exe" name: Test ${{ matrix.name }} runs-on: ${{ matrix.os }} steps: diff --git a/patches/electron-builder-squirrel-windows+26.0.6.patch b/patches/electron-builder-squirrel-windows+26.0.6.patch index 4dc2b8b4..8fc6f966 100644 --- a/patches/electron-builder-squirrel-windows+26.0.6.patch +++ b/patches/electron-builder-squirrel-windows+26.0.6.patch @@ -1,64 +1,36 @@ diff --git a/node_modules/electron-builder-squirrel-windows/out/SquirrelWindowsTarget.js b/node_modules/electron-builder-squirrel-windows/out/SquirrelWindowsTarget.js -index 15312f4..1d7a8d6 100644 +index 15312f4..06ac3d0 100644 --- a/node_modules/electron-builder-squirrel-windows/out/SquirrelWindowsTarget.js +++ b/node_modules/electron-builder-squirrel-windows/out/SquirrelWindowsTarget.js -@@ -38,7 +38,15 @@ class SquirrelWindowsTarget extends app_builder_lib_1.Target { - if (distOptions.vendorDirectory) { - this.select7zipArch(distOptions.vendorDirectory, arch); - } -+ distOptions.fixUpPaths = true; -+ if (this.options.msi) { -+ distOptions.setupMsi = setupFile; -+ } -+ else { -+ distOptions.setupExe = setupFile; -+ } - await (0, electron_winstaller_1.createWindowsInstaller)(distOptions); -+ await packager.signAndEditResources(artifactPath, arch, installerOutDir); - await packager.info.callArtifactBuildCompleted({ - file: artifactPath, - target: this, -@@ -93,24 +101,26 @@ class SquirrelWindowsTarget extends app_builder_lib_1.Target { - const appInfo = packager.appInfo; - // If not specified will use the Squirrel.Windows that is shipped with electron-installer(https://github.com/electron/windows-installer/tree/main/vendor) - // After https://github.com/electron-userland/electron-builder-binaries/pull/56 merged, will add `electron-builder-binaries` to get the latest version of squirrel. -- let vendorDirectory = this.options.customSquirrelVendorDir; +@@ -1,11 +1,10 @@ + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + const builder_util_1 = require("builder-util"); +-const app_builder_lib_1 = require("app-builder-lib"); + const filename_1 = require("builder-util/out/filename"); ++const app_builder_lib_1 = require("app-builder-lib"); + const path = require("path"); + const fs = require("fs"); +-const promises_1 = require("fs/promises"); + const electron_winstaller_1 = require("electron-winstaller"); + class SquirrelWindowsTarget extends app_builder_lib_1.Target { + constructor(packager, outDir) { +@@ -14,8 +13,28 @@ class SquirrelWindowsTarget extends app_builder_lib_1.Target { + this.outDir = outDir; + //tslint:disable-next-line:no-object-literal-type-assertion + this.options = { ...this.packager.platformSpecificBuildOptions, ...this.packager.config.squirrelWindows }; +- this.appDirectory = ""; +- this.outputDirectory = ""; ++ } ++ async prepareSignedVendorDirectory() { ++ // If not specified will use the Squirrel.Windows that is shipped with electron-installer(https://github.com/electron/windows-installer/tree/main/vendor) ++ // After https://github.com/electron-userland/electron-builder-binaries/pull/56 merged, will add `electron-builder-binaries` to get the latest version of squirrel. + let vendorDirectory = this.options.customSquirrelVendorDir || path.join(require.resolve("electron-winstaller/package.json"), "..", "vendor"); - if ((0, builder_util_1.isEmptyOrSpaces)(vendorDirectory) || !fs.existsSync(vendorDirectory)) { - builder_util_1.log.warn({ vendorDirectory }, "unable to access Squirrel.Windows vendor directory, falling back to default electron-winstaller"); -- vendorDirectory = undefined; ++ if ((0, builder_util_1.isEmptyOrSpaces)(vendorDirectory) || !fs.existsSync(vendorDirectory)) { ++ builder_util_1.log.warn({ vendorDirectory }, "unable to access Squirrel.Windows vendor directory, falling back to default electron-winstaller"); + vendorDirectory = path.join(require.resolve("electron-winstaller/package.json"), "..", "vendor"); - } - const options = { - appDirectory: this.appDirectory, - outputDirectory: this.outputDirectory, - name: this.options.useAppIdAsId ? appInfo.id : this.appName, -+ title: appInfo.productName || appInfo.name, - version: appInfo.version, - description: appInfo.description, -- exe: `${this.packager.platformSpecificBuildOptions.executableName || this.options.name || appInfo.productName}.exe`, -+ exe: `${appInfo.productFilename || this.options.name || appInfo.productName}.exe`, - authors: appInfo.companyName || "", - iconUrl, - copyright: appInfo.copyright, - vendorDirectory, - nuspecTemplate: path.join(__dirname, "..", "template.nuspectemplate"), - noMsi: !this.options.msi, -+ usePackageJson: false, - }; - const projectUrl = await appInfo.computePackageUrl(); - if (projectUrl != null) { -@@ -121,13 +131,19 @@ class SquirrelWindowsTarget extends app_builder_lib_1.Target { - await (0, promises_1.writeFile)(nuspecTemplate, templateContent); - options.nuspecTemplate = nuspecTemplate; - } -- if (await (await packager.signingManager.value).cscInfo.value) { -- options.windowsSign = { -- hookFunction: async (file) => { -- await packager.sign(file); -- }, -- }; -+ const tmpVendorDirectory = await packager.info.tempDirManager.createTempDir({ prefix: "squirrel-windows-vendor" }); ++ } ++ const tmpVendorDirectory = await this.packager.info.tempDirManager.createTempDir({ prefix: "squirrel-windows-vendor" }); + // Copy entire vendor directory to temp directory + await fs.promises.cp(vendorDirectory, tmpVendorDirectory, { recursive: true }); + builder_util_1.log.debug({ from: vendorDirectory, to: tmpVendorDirectory }, "copied vendor directory"); @@ -67,10 +39,140 @@ index 15312f4..1d7a8d6 100644 + if (["Squirrel.exe", "StubExecutable.exe"].includes(file)) { + const filePath = path.join(tmpVendorDirectory, file); + builder_util_1.log.debug({ file: filePath }, "signing vendor executable"); -+ await packager.sign(filePath); ++ await this.packager.sign(filePath); + } ++ } ++ return tmpVendorDirectory; + } + async build(appOutDir, arch) { + const packager = this.packager; +@@ -24,28 +43,35 @@ class SquirrelWindowsTarget extends app_builder_lib_1.Target { + const setupFile = packager.expandArtifactNamePattern(this.options, "exe", arch, "${productName} Setup ${version}.${ext}"); + const installerOutDir = path.join(this.outDir, `squirrel-windows${(0, app_builder_lib_1.getArchSuffix)(arch)}`); + const artifactPath = path.join(installerOutDir, setupFile); ++ const msiArtifactPath = path.join(installerOutDir, packager.expandArtifactNamePattern(this.options, "msi", arch, "${productName} Setup ${version}.${ext}")); + await packager.info.callArtifactBuildStarted({ + targetPresentableName: "Squirrel.Windows", + file: artifactPath, + arch, + }); +- if (arch === app_builder_lib_1.Arch.ia32) { +- builder_util_1.log.warn("For windows consider only distributing 64-bit or use nsis target, see https://github.com/electron-userland/electron-builder/issues/359#issuecomment-214851130"); +- } +- this.appDirectory = appOutDir; +- this.outputDirectory = installerOutDir; +- const distOptions = await this.computeEffectiveDistOptions(); +- if (distOptions.vendorDirectory) { +- this.select7zipArch(distOptions.vendorDirectory, arch); +- } ++ const distOptions = await this.computeEffectiveDistOptions(appOutDir, installerOutDir, setupFile, arch); + await (0, electron_winstaller_1.createWindowsInstaller)(distOptions); ++ await packager.signAndEditResources(artifactPath, arch, installerOutDir); ++ if (this.options.msi) { ++ await packager.sign(msiArtifactPath); ++ } ++ const safeArtifactName = (ext) => `${sanitizedName}-Setup-${version}${(0, app_builder_lib_1.getArchSuffix)(arch)}.${ext}`; + await packager.info.callArtifactBuildCompleted({ + file: artifactPath, + target: this, + arch, +- safeArtifactName: `${sanitizedName}-Setup-${version}${(0, app_builder_lib_1.getArchSuffix)(arch)}.exe`, ++ safeArtifactName: safeArtifactName("exe"), + packager: this.packager, + }); ++ if (this.options.msi) { ++ await packager.info.callArtifactBuildCompleted({ ++ file: msiArtifactPath, ++ target: this, ++ arch, ++ safeArtifactName: safeArtifactName("msi"), ++ packager: this.packager, ++ }); ++ } + const packagePrefix = `${this.appName}-${(0, electron_winstaller_1.convertVersion)(version)}-`; + packager.info.dispatchArtifactCreated({ + file: path.join(installerOutDir, `${packagePrefix}full.nupkg`), +@@ -73,11 +99,24 @@ class SquirrelWindowsTarget extends app_builder_lib_1.Target { + } + select7zipArch(vendorDirectory, arch) { + // Copy the 7-Zip executable for the configured architecture. +- const resolvedArch = (0, app_builder_lib_1.getArchSuffix)(arch) === "" ? process.arch : (0, app_builder_lib_1.getArchSuffix)(arch); +- fs.copyFileSync(path.join(vendorDirectory, `7z-${resolvedArch}.exe`), path.join(vendorDirectory, "7z.exe")); +- fs.copyFileSync(path.join(vendorDirectory, `7z-${resolvedArch}.dll`), path.join(vendorDirectory, "7z.dll")); ++ const resolvedArch = (0, app_builder_lib_1.getArchSuffix)(arch) || `-${process.arch}`; ++ fs.copyFileSync(path.join(vendorDirectory, `7z${resolvedArch}.exe`), path.join(vendorDirectory, "7z.exe")); ++ fs.copyFileSync(path.join(vendorDirectory, `7z${resolvedArch}.dll`), path.join(vendorDirectory, "7z.dll")); + } +- async computeEffectiveDistOptions() { ++ async createNuspecTemplateWithProjectUrl() { ++ const templatePath = path.resolve(__dirname, "..", "template.nuspectemplate"); ++ const projectUrl = await this.packager.appInfo.computePackageUrl(); ++ if (projectUrl != null) { ++ const nuspecTemplate = await this.packager.info.tempDirManager.getTempFile({ prefix: "template", suffix: ".nuspectemplate" }); ++ let templateContent = await fs.promises.readFile(templatePath, "utf8"); ++ const searchString = "<%- copyright %>"; ++ templateContent = templateContent.replace(searchString, `${searchString}\n ${projectUrl}`); ++ await fs.promises.writeFile(nuspecTemplate, templateContent); ++ return nuspecTemplate; ++ } ++ return templatePath; ++ } ++ async computeEffectiveDistOptions(appDirectory, outputDirectory, setupFile, arch) { + const packager = this.packager; + let iconUrl = this.options.iconUrl; + if (iconUrl == null) { +@@ -91,42 +130,27 @@ class SquirrelWindowsTarget extends app_builder_lib_1.Target { + } + checkConflictingOptions(this.options); + const appInfo = packager.appInfo; +- // If not specified will use the Squirrel.Windows that is shipped with electron-installer(https://github.com/electron/windows-installer/tree/main/vendor) +- // After https://github.com/electron-userland/electron-builder-binaries/pull/56 merged, will add `electron-builder-binaries` to get the latest version of squirrel. +- let vendorDirectory = this.options.customSquirrelVendorDir; +- if ((0, builder_util_1.isEmptyOrSpaces)(vendorDirectory) || !fs.existsSync(vendorDirectory)) { +- builder_util_1.log.warn({ vendorDirectory }, "unable to access Squirrel.Windows vendor directory, falling back to default electron-winstaller"); +- vendorDirectory = undefined; +- } + const options = { +- appDirectory: this.appDirectory, +- outputDirectory: this.outputDirectory, ++ appDirectory: appDirectory, ++ outputDirectory: outputDirectory, + name: this.options.useAppIdAsId ? appInfo.id : this.appName, ++ title: appInfo.productName || appInfo.name, + version: appInfo.version, + description: appInfo.description, +- exe: `${this.packager.platformSpecificBuildOptions.executableName || this.options.name || appInfo.productName}.exe`, ++ exe: `${appInfo.productFilename || this.options.name || appInfo.productName}.exe`, + authors: appInfo.companyName || "", ++ nuspecTemplate: await this.createNuspecTemplateWithProjectUrl(), + iconUrl, + copyright: appInfo.copyright, +- vendorDirectory, +- nuspecTemplate: path.join(__dirname, "..", "template.nuspectemplate"), + noMsi: !this.options.msi, ++ usePackageJson: false, + }; +- const projectUrl = await appInfo.computePackageUrl(); +- if (projectUrl != null) { +- const nuspecTemplate = await this.packager.info.tempDirManager.getTempFile({ prefix: "template", suffix: ".nuspectemplate" }); +- let templateContent = await (0, promises_1.readFile)(path.resolve(__dirname, "..", "template.nuspectemplate"), "utf8"); +- const searchString = "<%- copyright %>"; +- templateContent = templateContent.replace(searchString, `${searchString}\n ${projectUrl}`); +- await (0, promises_1.writeFile)(nuspecTemplate, templateContent); +- options.nuspecTemplate = nuspecTemplate; +- } +- if (await (await packager.signingManager.value).cscInfo.value) { +- options.windowsSign = { +- hookFunction: async (file) => { +- await packager.sign(file); +- }, +- }; ++ options.vendorDirectory = await this.prepareSignedVendorDirectory(); ++ this.select7zipArch(options.vendorDirectory, arch); ++ options.fixUpPaths = true; ++ options.setupExe = setupFile; ++ if (this.options.msi) { ++ options.setupMsi = setupFile.replace(".exe", ".msi"); } -+ options.vendorDirectory = tmpVendorDirectory; if ((0, builder_util_1.isEmptyOrSpaces)(options.description)) { options.description = this.options.name || appInfo.productName; - }