From 1f144e486f32cbb076a2cd3fb914c294adc2bd1e Mon Sep 17 00:00:00 2001 From: hensm Date: Tue, 5 Mar 2019 01:13:20 +0000 Subject: [PATCH] Add Windows installer script --- README.md | 8 ++--- app/bin/build.js | 55 +++++++++++++++++++++++++++------ app/package-lock.json | 15 +++++++++ app/package.json | 1 + app/packaging/win/installer.nsi | 42 +++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 13 deletions(-) create mode 100644 app/packaging/win/installer.nsi diff --git a/README.md b/README.md index d6f9a69..965ef9c 100644 --- a/README.md +++ b/README.md @@ -50,19 +50,19 @@ sudo dnf install fx_cast_bridge-..rpm macOS: ````sh -brew install dpkg rpm +brew install dpkg rpm makensis ```` Debian/Ubuntu: ````sh -sudo apt install dpkg rpm +sudo apt install dpkg rpm makensis ```` Fedora: ````sh -sudo dnf install dpkg rpm-build +sudo dnf install dpkg rpm-build mingw-nsis ```` Archlinux: @@ -71,7 +71,7 @@ At the moment, `pkg` has a [bug](https://github.com/zeit/pkg/issues/584), until ```sh sudo pacman -S nvm dpkg -yay -S rpm-org +yay -S rpm-org nsis echo 'source /usr/share/nvm/init-nvm.sh' >> ~/.bashrc nvm install 10.12.0 ``` diff --git a/app/bin/build.js b/app/bin/build.js index 5b3266f..9a7ebc7 100644 --- a/app/bin/build.js +++ b/app/bin/build.js @@ -1,9 +1,12 @@ +"use strict"; + const fs = require("fs-extra"); const os = require("os"); const path = require("path"); const minimist = require("minimist"); const glob = require("glob"); const mustache = require("mustache"); +const makensis = require("makensis"); const { spawnSync } = require("child_process"); const { exec: pkgExec } = require("pkg"); @@ -18,14 +21,16 @@ const { executableName , manifestName , manifestPath , pkgPlatform - , DIST_PATH } = require("./lib/paths"); + , DIST_PATH + , WIN_REGISTRY_KEY } = require("./lib/paths"); const argv = minimist(process.argv.slice(2), { boolean: [ "package" ] - , string: [ "platform", "packageType" ] + , string: [ "platform", "arch", "packageType" ] , default: { platform: os.platform() + , arch: os.arch() , package: false // Linux package type (deb/rpm) , packageType: "deb" @@ -75,8 +80,9 @@ async function build () { , "allowed_extensions": [ extensionId ] , "path": argv.package // Add either installed path or dist path - ? path.join(executablePath[argv.platform] - , executableName[argv.platform]) + ? (argv.platform === "win32" ? path.win32 : path) + .join(executablePath[argv.platform] + , executableName[argv.platform]) : path.join(DIST_PATH, executableName[argv.platform]) }; @@ -106,12 +112,12 @@ async function build () { // Package executable await pkgExec([ BUILD_PATH - , "--target", pkgPlatform[argv.platform] + , "--target", `${pkgPlatform[argv.platform]}-${argv.arch}` , "--output", path.join(BUILD_PATH, executableName[argv.platform]) ]); if (argv.package) { - const installerName = await package(argv.platform); + const installerName = await packageApp(argv.platform); if (installerName) { // Move installer to dist @@ -134,7 +140,7 @@ async function build () { } -function package (platform) { +function packageApp (platform) { switch (platform) { case "darwin": return packageDarwin(platform); @@ -148,7 +154,7 @@ function package (platform) { } case "win32": - return packageWin32(); + return packageWin32(platform); default: console.log("Cannot build installer package for this platform"); @@ -295,6 +301,7 @@ function packageLinuxRpm (platform, packageType) { fs.readFileSync(specPath).toString() , view)); + // TODO: Use argv.arch spawnSync( `rpmbuild -bb ${specOutputPath} ` + `--define "_distdir ${BUILD_PATH}" ` @@ -305,7 +312,37 @@ function packageLinuxRpm (platform, packageType) { return glob.sync("**/*.rpm", { cwd: BUILD_PATH })[0]; } -function packageWin32 () {} +function packageWin32 (platform) { + const scriptPath = path.join(__dirname, "../packaging/win/installer.nsi"); + const scriptOutputPath = path.join(BUILD_PATH, path.basename(scriptPath)); + + const outFile = "installer.exe"; + + const view = { + applicationName + , applicationVersion + , executableName: executableName[platform] + , executablePath: executablePath[platform] + , manifestName + , winRegistryKey: WIN_REGISTRY_KEY + , outFile + }; + + fs.writeFileSync(scriptOutputPath + , mustache.render( + fs.readFileSync(scriptPath).toString() + , view)); + + const output = makensis.compileSync(scriptOutputPath); + + if (output.status === 0) { + console.log(output.stdout); + } else { + console.error(output.stderr); + } + + return outFile; +} build().catch(e => { diff --git a/app/package-lock.json b/app/package-lock.json index 6454e31..9198c6c 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -18,6 +18,12 @@ "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", "dev": true }, + "@nsis/language-data": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@nsis/language-data/-/language-data-0.5.1.tgz", + "integrity": "sha512-rsbghvYNfVTmbTSHlMqF8kpG70mUlJTg6IiUf9IBAqidCyC19vlsYQXShrzPUeRqPP2GiXnIQPjDJ+Z7H0TTyw==", + "dev": true + }, "@types/dnssd": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@types/dnssd/-/dnssd-0.4.1.tgz", @@ -1453,6 +1459,15 @@ "resolved": "https://registry.npmjs.org/long/-/long-2.4.0.tgz", "integrity": "sha1-n6GAux2VAM3CnEFWdmoZleH0Uk8=" }, + "makensis": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/makensis/-/makensis-0.17.0.tgz", + "integrity": "sha512-tzNcjuYvhE+MWD3X0S5to7ufyRmzcCV70/h65mT7voeIINnQEJuzVOUh9pjBBX+WfhoiLmb3xAJS98EbDHgoUQ==", + "dev": true, + "requires": { + "@nsis/language-data": "^0.5.1" + } + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", diff --git a/app/package.json b/app/package.json index ce084c6..7fde7e3 100644 --- a/app/package.json +++ b/app/package.json @@ -26,6 +26,7 @@ "@types/mime-types": "^2.1.0", "@types/node": "^11.9.5", "@types/node-fetch": "^2.1.6", + "makensis": "^0.17.0", "mustache": "^3.0.1", "pkg": "^4.3.5", "tslint": "^5.13.0" diff --git a/app/packaging/win/installer.nsi b/app/packaging/win/installer.nsi new file mode 100644 index 0000000..ffb3541 --- /dev/null +++ b/app/packaging/win/installer.nsi @@ -0,0 +1,42 @@ +!include LogicLib.nsh + +!define MANIFEST_KEY "Software\Mozilla\NativeMessagingHosts\{{manifestName}}" +!define UNINSTALL_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\{{winRegistryKey}}" + +Name "{{applicationName}} v{{applicationVersion}}" +OutFile "{{outFile}}" +InstallDir "{{executablePath}}" +RequestExecutionLevel user + +Section + SetRegView 64 + + SetOutPath $INSTDIR + + # Main executable + File "{{executableName}}" + File "{{manifestName}}" + + # Native manifest key + WriteRegStr HKLM "${MANIFEST_KEY}" "" "$INSTDIR\{{manifestName}}" + + # Create and register uninstaller + WriteUninstaller "$INSTDIR\uninstall.exe" + WriteRegStr HKLM "${UNINSTALL_KEY}" "DisplayName" "{{applicationName}}" + WriteRegStr HKLM "${UNINSTALL_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" + WriteRegStr HKLM "${UNINSTALL_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" +SectionEnd + +Section "uninstall" + SetRegView 64 + + # Remove uninstaller + Delete "$INSTDIR\uninstall.exe" + DeleteRegKey HKLM "${UNINSTALL_KEY}" + + # Remove manifest and executable dir + DeleteRegKey HKLM "${MANIFEST_KEY}" + Delete "$INSTDIR\{{executableName}}" + Delete "$INSTDIR\{{manifestName}}" + RMDir $INSTDIR +SectionEnd