diff options
| -rwxr-xr-x | build.sh | 33 | ||||
| -rw-r--r-- | desktop/packages/mullvad-vpn/tasks/distribution.js | 102 | ||||
| -rw-r--r-- | scripts/pack-universal-win.sh | 66 |
3 files changed, 138 insertions, 63 deletions
@@ -28,8 +28,8 @@ OPTIMIZE="false" SIGN="false" # If the produced app and pkg should be notarized by apple (macOS only) NOTARIZE="false" -# If a macOS build should create an installer artifact working on both -# Intel and Apple Silicon Macs +# If a macOS or Windows build should create an installer artifact working on both +# x86 and arm64 UNIVERSAL="false" while [[ "$#" -gt 0 ]]; do @@ -38,8 +38,8 @@ while [[ "$#" -gt 0 ]]; do --sign) SIGN="true";; --notarize) NOTARIZE="true";; --universal) - if [[ "$(uname -s)" != "Darwin" ]]; then - log_error "--universal only works on macOS" + if [[ "$(uname -s)" != "Darwin" && "$(uname -s)" != "MINGW"* ]]; then + log_error "--universal only works on macOS and Windows" exit 1 fi UNIVERSAL="true" @@ -79,11 +79,11 @@ if [[ "$UNIVERSAL" == "true" ]]; then log_error "'TARGETS' and '--universal' cannot be specified simultaneously." exit 1 else - log_info "Building universal macOS distribution" + log_info "Building universal distribution" fi - # Universal macOS builds package targets for both aarch64-apple-darwin and x86_64-apple-darwin. - # We leave the target corresponding to the host machine empty to avoid rebuilding multiple times. + # Universal builds package targets for both aarch64 and x86_64. We leave the target + # corresponding to the host machine empty to avoid rebuilding multiple times. # When the --target flag is provided to cargo it always puts the build in the target/$ENV_TARGET # folder even when it matches you local machine, as opposed to just the target folder. # This causes the cached build not to get used when later running e.g. @@ -91,6 +91,8 @@ if [[ "$UNIVERSAL" == "true" ]]; then case $HOST in x86_64-apple-darwin) TARGETS=("" aarch64-apple-darwin);; aarch64-apple-darwin) TARGETS=("" x86_64-apple-darwin);; + x86_64-pc-windows-msvc) TARGETS=("" aarch64-pc-windows-msvc);; + aarch64-pc-windows-msvc) TARGETS=("" x86_64-pc-windows-msvc);; esac NPM_PACK_ARGS+=(--universal) @@ -311,7 +313,7 @@ function build { if [[ "$(uname -s)" == "MINGW"* ]]; then for t in "${TARGETS[@]:-"$HOST"}"; do - case $t in + case "${t:-"$HOST"}" in x86_64-pc-windows-msvc) CPP_BUILD_TARGET=x64;; aarch64-pc-windows-msvc) CPP_BUILD_TARGET=ARM64;; *) @@ -384,6 +386,21 @@ if [[ "$SIGN" == "true" && "$(uname -s)" == "MINGW"* ]]; then done fi +# pack universal installer on Windows +if [[ "$UNIVERSAL" == "true" && "$(uname -s)" == "MINGW"* ]]; then + WIN_PACK_ARGS=() + if [[ "$OPTIMIZE" == "true" ]]; then + WIN_PACK_ARGS+=(--optimize) + fi + ./scripts/pack-universal-win.sh \ + --x64-installer "$SCRIPT_DIR/dist/"*"$PRODUCT_VERSION"_x64.exe \ + --arm64-installer "$SCRIPT_DIR/dist/"*"$PRODUCT_VERSION"_arm64.exe \ + "${WIN_PACK_ARGS[@]}" + if [[ "$SIGN" == "true" ]]; then + sign_win "dist/MullvadVPN-${PRODUCT_VERSION}.exe" + fi +fi + # notarize installer on macOS if [[ "$NOTARIZE" == "true" && "$(uname -s)" == "Darwin" ]]; then log_info "Notarizing pkg" diff --git a/desktop/packages/mullvad-vpn/tasks/distribution.js b/desktop/packages/mullvad-vpn/tasks/distribution.js index 6401e24a45..afc6e85b69 100644 --- a/desktop/packages/mullvad-vpn/tasks/distribution.js +++ b/desktop/packages/mullvad-vpn/tasks/distribution.js @@ -132,29 +132,25 @@ const config = { }, win: { - target: [ - { - target: 'nsis', - arch: getWindowsTargetArch(), - }, - ], - artifactName: getWindowsArtifactName(), + target: [], + signAndEditExecutable: false, + artifactName: 'MullvadVPN-${version}_${arch}.${ext}', publisherName: 'Mullvad VPN AB', extraResources: [ - { from: distAssets(path.join(getWindowsDistSubdir(), 'mullvad.exe')), to: '.' }, + { from: distAssets(path.join('${env.DIST_SUBDIR}', 'mullvad.exe')), to: '.' }, { - from: distAssets(path.join(getWindowsDistSubdir(), 'mullvad-problem-report.exe')), + from: distAssets(path.join('${env.DIST_SUBDIR}', 'mullvad-problem-report.exe')), to: '.', }, - { from: distAssets(path.join(getWindowsDistSubdir(), 'mullvad-daemon.exe')), to: '.' }, - { from: distAssets(path.join(getWindowsDistSubdir(), 'talpid_openvpn_plugin.dll')), to: '.' }, + { from: distAssets(path.join('${env.DIST_SUBDIR}', 'mullvad-daemon.exe')), to: '.' }, + { from: distAssets(path.join('${env.DIST_SUBDIR}', 'talpid_openvpn_plugin.dll')), to: '.' }, { from: root( path.join( 'windows', 'winfw', 'bin', - getWindowsTargetArch() + '-${env.CPP_BUILD_MODE}', + '${env.TARGET_ARCHITECTURE}-${env.CPP_BUILD_MODE}', 'winfw.dll', ), ), @@ -163,22 +159,22 @@ const config = { // TODO: OpenVPN does not have an ARM64 build yet. { from: distAssets('binaries/x86_64-pc-windows-msvc/openvpn.exe'), to: '.' }, { - from: distAssets(path.join('binaries', getWindowsTargetSubdir(), 'apisocks5.exe')), + from: distAssets(path.join('binaries', '${env.TARGET_SUBDIR}', 'apisocks5.exe')), to: '.', }, { - from: distAssets(path.join('binaries', getWindowsTargetSubdir(), 'wintun/wintun.dll')), + from: distAssets(path.join('binaries', '${env.TARGET_SUBDIR}', 'wintun/wintun.dll')), to: '.', }, { from: distAssets( - path.join('binaries', getWindowsTargetSubdir(), 'split-tunnel/mullvad-split-tunnel.sys'), + path.join('binaries', '${env.TARGET_SUBDIR}', 'split-tunnel/mullvad-split-tunnel.sys'), ), to: '.', }, { from: distAssets( - path.join('binaries', getWindowsTargetSubdir(), 'wireguard-nt/mullvad-wireguard.dll'), + path.join('binaries', '${env.TARGET_SUBDIR}', 'wireguard-nt/mullvad-wireguard.dll'), ), to: '.', }, @@ -277,11 +273,23 @@ const config = { }, }; -function packWin() { - return builder.build({ - targets: builder.Platform.WINDOWS.createTarget(), - config: { +async function packWin() { + const DEFAULT_ARCH = targets === 'aarch64-pc-windows-msvc' ? 'arm64' : 'x64'; + + function prepareConfig(arch) { + return { ...config, + files: [...config.files], + win: { + ...config.win, + extraResources: [...config.win.extraResources], + target: [ + { + target: 'nsis', + arch: arch, + }, + ], + }, asarUnpack: ['build/assets/images/menubar-icons/win32/lock-*.ico'], beforeBuild: (options) => { process.env.CPP_BUILD_MODE = release ? 'Release' : 'Debug'; @@ -291,10 +299,14 @@ function packWin() { case 'x64': process.env.TARGET_TRIPLE = 'x86_64-pc-windows-msvc'; process.env.SETUP_SUBDIR = '.'; + process.env.TARGET_SUBDIR = 'x86_64-pc-windows-msvc'; + process.env.DIST_SUBDIR = ''; break; case 'arm64': process.env.TARGET_TRIPLE = 'aarch64-pc-windows-msvc'; process.env.SETUP_SUBDIR = 'aarch64-pc-windows-msvc'; + process.env.TARGET_SUBDIR = 'aarch64-pc-windows-msvc'; + process.env.DIST_SUBDIR = 'aarch64-pc-windows-msvc'; break; default: throw new Error('Invalid or unknown target (only one may be specified)'); @@ -320,7 +332,21 @@ function packWin() { fs.renameSync(artifactPath, targetArtifactPath); } }, - }, + }; + } + + if (universal) { + // For universal builds, we simply build for all targets. It is up to build.sh to pack the + // installers in the same binary. + await builder.build({ + targets: builder.Platform.WINDOWS.createTarget(), + config: prepareConfig(DEFAULT_ARCH === 'x64' ? 'arm64' : 'x64'), + }); + } + + return builder.build({ + targets: builder.Platform.WINDOWS.createTarget(), + config: prepareConfig(DEFAULT_ARCH), }); } @@ -441,40 +467,6 @@ function root(relativePath) { return path.join(path.resolve(__dirname, '../../../../'), relativePath); } -function getWindowsDistSubdir() { - if (targets === 'aarch64-pc-windows-msvc') { - return targets; - } else { - return ''; - } -} - -function getWindowsTargetArch() { - if (targets && process.platform === 'win32') { - if (targets === 'aarch64-pc-windows-msvc') { - return 'arm64'; - } - throw new Error('Invalid or unknown target (only one may be specified)'); - } - // Use host architecture (we assume this is x64 since building on Arm64 isn't supported). - return 'x64'; -} - -function getWindowsArtifactName() { - return 'MullvadVPN-${version}_${arch}.${ext}'; -} - -function getWindowsTargetSubdir() { - if (targets && process.platform === 'win32') { - if (targets === 'aarch64-pc-windows-msvc') { - return targets; - } - throw new Error('Invalid or unknown target (only one may be specified)'); - } - // Use host architecture (we assume this is x64 since building on Arm64 isn't supported). - return 'x86_64-pc-windows-msvc'; -} - function getLinuxTargetArch() { if (targets && process.platform === 'linux') { if (targets === 'aarch64-unknown-linux-gnu') { diff --git a/scripts/pack-universal-win.sh b/scripts/pack-universal-win.sh new file mode 100644 index 0000000000..453b722011 --- /dev/null +++ b/scripts/pack-universal-win.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# shellcheck shell=bash +# Build universal installer for both ARM and x64. + +set -eu + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "$SCRIPT_DIR/.." + +CARGO_TARGET_DIR=${CARGO_TARGET_DIR:-"target"} + +# If enabled, build in release mode with optimizations enabled +OPTIMIZE="false" + +source scripts/utils/log + +echo "Computing build version..." +PRODUCT_VERSION=$(cargo run -q --bin mullvad-version) +log_header "Building universal Windows installer for Mullvad VPN $PRODUCT_VERSION" + +while [[ "$#" -gt 0 ]]; do + case $1 in + --x64-installer) + export WIN_X64_INSTALLER="$2" + shift 2 + ;; + --arm64-installer) + export WIN_ARM64_INSTALLER="$2" + shift 2 + ;; + --optimize) + OPTIMIZE="true" + shift + ;; + *) + log_error "Unknown argument: $1" + exit 1 + ;; + esac +done + +CARGO_ARGS=() + +if [[ "$OPTIMIZE" == "true" ]]; then + CARGO_ARGS+=(--release) + RUST_BUILD_MODE="release" +else + RUST_BUILD_MODE="debug" +fi + +if [[ "$OPTIMIZE" == "true" && "$PRODUCT_VERSION" != *"-dev-"* ]]; then + CARGO_ARGS+=(--locked) +fi + +if [[ -z ${WIN_X64_INSTALLER-} ]] || [[ -z ${WIN_ARM64_INSTALLER-} ]]; then + log_error "Must provide --x64-installer and --arm64-installer" + exit 1 +fi + +cargo build "${CARGO_ARGS[@]}" -p windows-installer --target x86_64-pc-windows-msvc + +dest="dist/MullvadVPN-${PRODUCT_VERSION}.exe" + +cp "$CARGO_TARGET_DIR/x86_64-pc-windows-msvc/${RUST_BUILD_MODE}/windows-installer.exe" "$dest" + +log_success "Built universal installer: $dest" |
