From f2056fa89e42c9f271022d5ede94f64c44412be6 Mon Sep 17 00:00:00 2001
From: develar <develar@gmail.com>
Date: Wed, 8 Mar 2017 09:33:47 +0100
Subject: [PATCH] feat: Different architectures for different platforms

Close #1314
---
 .idea/dictionaries/develar.xml                |   1 +
 README.md                                     |   2 +-
 package.json                                  |  11 +-
 packages/electron-builder-core/src/core.ts    |  25 ++-
 .../src/squirrelWindows.ts                    |  10 +-
 packages/electron-builder-util/src/util.ts    |  29 +++-
 packages/electron-builder/package.json        |   2 +-
 packages/electron-builder/src/builder.ts      |  61 +++-----
 packages/electron-builder/src/index.ts        |   5 +-
 .../electron-builder/src/linuxPackager.ts     |   4 +-
 packages/electron-builder/src/macPackager.ts  |   4 +-
 packages/electron-builder/src/metadata.ts     |  15 +-
 .../src/options/linuxOptions.ts               |   3 +-
 .../src/options/macOptions.ts                 |   4 +-
 .../src/options/winOptions.ts                 |   3 +-
 packages/electron-builder/src/packager.ts     |  30 ++--
 packages/electron-builder/src/packagerApi.ts  |   2 +-
 .../electron-builder/src/targets/appImage.ts  |   2 +-
 .../electron-builder/src/targets/archive.ts   |  40 +++--
 packages/electron-builder/src/targets/dmg.ts  |   7 +-
 packages/electron-builder/src/targets/snap.ts |  19 +--
 .../src/targets/targetFactory.ts              |  48 ++++--
 packages/electron-builder/src/winPackager.ts  |   4 +-
 packages/electron-publisher-s3/package.json   |   2 +-
 test/out/__snapshots__/BuildTest.js.snap      |  70 +++++++--
 test/out/__snapshots__/ExtraBuildTest.js.snap |  53 +++++--
 .../__snapshots__/extraMetadataTest.js.snap   |  12 ++
 test/out/__snapshots__/filesTest.js.snap      |  58 +++++--
 test/out/__snapshots__/globTest.js.snap       |  30 ++++
 test/out/__snapshots__/ignoreTest.js.snap     |  19 +++
 test/out/__snapshots__/mainEntryTest.js.snap  |  14 ++
 test/out/linux/__snapshots__/debTest.js.snap  |  26 +--
 test/out/linux/__snapshots__/fpmTest.js.snap  |  64 ++++----
 .../__snapshots__/linuxArchiveTest.js.snap    |  30 ++--
 .../__snapshots__/linuxPackagerTest.js.snap   |  26 +--
 test/out/linux/__snapshots__/snapTest.js.snap |  13 +-
 test/out/mac/__snapshots__/dmgTest.js.snap    |  28 ++--
 .../mac/__snapshots__/macArchiveTest.js.snap  | 134 ++++++++++++----
 .../mac/__snapshots__/macPackagerTest.js.snap |  56 ++++---
 test/out/mac/__snapshots__/masTest.js.snap    |  36 +++--
 .../__snapshots__/installerTest.js.snap       |  56 ++++---
 .../oneClickInstallerTest.js.snap             | 148 +++++++++---------
 .../__snapshots__/squirrelWindowsTest.js.snap |  36 ++---
 test/src/BuildTest.ts                         |  30 ++--
 test/src/ExtraBuildTest.ts                    |  26 ++-
 test/src/helpers/packTester.ts                | 134 +++++++---------
 test/src/helpers/runTests.ts                  |   2 +-
 test/src/linux/linuxPackagerTest.ts           |   4 +-
 test/src/mac/macArchiveTest.ts                |   1 -
 test/src/mac/macPackagerTest.ts               |   4 +-
 test/src/mainEntryTest.ts                     |  17 +-
 test/src/windows/oneClickInstallerTest.ts     |   1 -
 yarn.lock                                     |  64 ++++----
 53 files changed, 920 insertions(+), 605 deletions(-)
 create mode 100644 test/out/__snapshots__/ignoreTest.js.snap

diff --git a/.idea/dictionaries/develar.xml b/.idea/dictionaries/develar.xml
index 025fdd888e5..84060d6e55d 100644
--- a/.idea/dictionaries/develar.xml
+++ b/.idea/dictionaries/develar.xml
@@ -197,6 +197,7 @@
       <w>udif</w>
       <w>udro</w>
       <w>udrw</w>
+      <w>uitk</w>
       <w>ulfo</w>
       <w>unassociate</w>
       <w>unicon</w>
diff --git a/README.md b/README.md
index 00323229072..69c349d2f2c 100755
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# electron-builder [![npm version](https://img.shields.io/npm/v/electron-builder.svg)](https://npmjs.org/package/electron-builder) [![donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W6V79R2RGCCHL)
+# electron-builder [![npm version](https://img.shields.io/npm/v/electron-builder.svg)](https://npmjs.org/package/electron-builder) [![downloads per month](http://img.shields.io/npm/dm/electron-builder.svg)](https://www.npmjs.org/package/fs-extra) [![donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W6V79R2RGCCHL)
 A complete solution to package and build a ready for distribution Electron app for macOS, Windows and Linux with “auto update” support out of the box.
 
 * NPM packages management:
diff --git a/package.json b/package.json
index 357b389d90c..cfb2672a724 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,7 @@
     "ajv": "^5.0.3-beta",
     "ajv-keywords": "^2.0.1-beta.1",
     "archiver": "^1.3.0",
-    "aws-sdk": "^2.22.0",
+    "aws-sdk": "^2.24.0",
     "bluebird-lst": "^1.0.1",
     "chalk": "^1.1.3",
     "chromium-pickle-js": "^0.2.0",
@@ -48,13 +48,14 @@
     "minimatch": "^3.0.3",
     "node-emoji": "^1.5.1",
     "node-forge": "^0.7.0",
-    "normalize-package-data": "^2.3.5",
+    "normalize-package-data": "^2.3.6",
     "parse-color": "^1.0.0",
     "plist": "^2.0.1",
     "progress-ex": "^2.0.0",
     "sanitize-filename": "^1.6.1",
     "semver": "^5.3.0",
     "stat-mode": "^0.2.2",
+    "ts-jsdoc": "^1.0.0",
     "tunnel-agent": "^0.6.0",
     "update-notifier": "^2.1.0",
     "uuid-1345": "^0.99.6",
@@ -65,7 +66,7 @@
     "@types/ini": "^1.3.29",
     "@types/jest": "^18.1.1",
     "@types/js-yaml": "^3.5.29",
-    "@types/node-forge": "^0.6.5",
+    "@types/node-forge": "^0.6.6",
     "@types/source-map-support": "^0.2.28",
     "@types/xml2js": "^0.0.32",
     "babel-plugin-array-includes": "^2.0.3",
@@ -81,11 +82,11 @@
     "electron-download-tf": "4.0.0",
     "jest-cli": "^19.0.2",
     "jest-environment-node-debug": "^2.0.0",
-    "jest-junit": "^1.2.0",
+    "jest-junit": "^1.3.0",
     "jsdoc": "^3.4.3",
     "path-sort": "^0.1.0",
     "source-map-support": "^0.4.11",
-    "ts-babel": "^1.4.4",
+    "ts-babel": "^2.0.0",
     "tslint": "^4.5.1",
     "typescript": "^2.2.1",
     "typescript-json-schema": "0.10.0",
diff --git a/packages/electron-builder-core/src/core.ts b/packages/electron-builder-core/src/core.ts
index c2050753e1a..8f304696fe8 100644
--- a/packages/electron-builder-core/src/core.ts
+++ b/packages/electron-builder-core/src/core.ts
@@ -2,10 +2,26 @@ export enum Arch {
   ia32, x64, armv7l
 }
 
+export type ArchType = "x64" | "ia32" | "armv7l"
+
 export function getArchSuffix(arch: Arch): string {
   return arch === Arch.x64 ? "" : `-${Arch[arch]}`
 }
 
+export type TargetConfigType = Array<string | TargetConfig> | string | TargetConfig | null
+
+export interface TargetConfig {
+  /**
+   * The target name. e.g. `snap`.
+   */
+  readonly target: string
+
+  /**
+   * The arch or list of archs.
+   */
+  readonly arch?: Array<"x64" | "ia32" | "armv7l"> | string
+}
+
 export function toLinuxArchString(arch: Arch) {
   return arch === Arch.ia32 ? "i386" : (arch === Arch.x64 ? "amd64" : "armv7l")
 }
@@ -41,6 +57,10 @@ export class Platform {
   }
 
   createTarget(type?: string | Array<string> | null, ...archs: Array<Arch>): Map<Platform, Map<Arch, Array<string>>> {
+    if (type == null && (archs == null || archs.length === 0)) {
+      return new Map([[this, new Map()]])
+    }
+
     const archToType = new Map()
     if (this === Platform.MAC) {
       archs = [Arch.x64]
@@ -97,4 +117,7 @@ export interface TargetSpecificOptions {
   readonly artifactName?: string | null
 
   readonly forceCodeSigning?: boolean
-}
\ No newline at end of file
+}
+
+export const DEFAULT_TARGET = "default"
+export const DIR_TARGET = "dir"
\ No newline at end of file
diff --git a/packages/electron-builder-squirrel-windows/src/squirrelWindows.ts b/packages/electron-builder-squirrel-windows/src/squirrelWindows.ts
index 7eb9eea7dc5..5dbb8ec8bdd 100644
--- a/packages/electron-builder-squirrel-windows/src/squirrelWindows.ts
+++ b/packages/electron-builder-squirrel-windows/src/squirrelWindows.ts
@@ -1,10 +1,10 @@
+import { Arch, getArchSuffix, Target } from "electron-builder-core"
+import { getBinFromBintray } from "electron-builder-util/out/binDownload"
+import { log, warn } from "electron-builder-util/out/log"
+import { SquirrelWindowsOptions } from "electron-builder/out/options/winOptions"
 import { WinPackager } from "electron-builder/out/winPackager"
 import * as path from "path"
-import { warn, log } from "electron-builder-util/out/log"
-import { getBinFromBintray } from "electron-builder-util/out/binDownload"
 import { buildInstaller, convertVersion, SquirrelOptions } from "./squirrelPack"
-import { SquirrelWindowsOptions } from "electron-builder/out/options/winOptions"
-import { Target, Arch, getArchSuffix } from "electron-builder-core"
 
 const SW_VERSION = "1.5.2.0"
 //noinspection SpellCheckingInspection
@@ -75,7 +75,7 @@ export default class SquirrelWindowsTarget extends Target {
       iconUrl: iconUrl,
       extraMetadataSpecs: projectUrl == null ? null : `\n    <projectUrl>${projectUrl}</projectUrl>`,
       copyright: appInfo.copyright,
-      packageCompressionLevel: packager.config.compression === "store" ? 0 : 9,
+      packageCompressionLevel: parseInt(process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL) || (packager.config.compression === "store" ? 0 : 9),
       vendorPath: await getBinFromBintray("Squirrel.Windows", SW_VERSION, SW_SHA2)
     }, this.options)
 
diff --git a/packages/electron-builder-util/src/util.ts b/packages/electron-builder-util/src/util.ts
index 69af53e437d..054589d81c4 100644
--- a/packages/electron-builder-util/src/util.ts
+++ b/packages/electron-builder-util/src/util.ts
@@ -1,4 +1,3 @@
-import "source-map-support/register"
 import BluebirdPromise from "bluebird-lst"
 import { red, yellow } from "chalk"
 import { ChildProcess, execFile, spawn as _spawn, SpawnOptions } from "child_process"
@@ -6,6 +5,7 @@ import { createHash } from "crypto"
 import _debug from "debug"
 import { homedir, tmpdir } from "os"
 import * as path from "path"
+import "source-map-support/register"
 import { statOrNull } from "./fs"
 import { log, warn } from "./log"
 
@@ -252,4 +252,31 @@ export class Lazy<T> {
   constructor(creator: () => Promise<T>) {
     this.creator = creator
   }
+}
+
+export function addValue<K, T>(map: Map<K, Array<T>>, key: K, value: T) {
+  const list = map.get(key)
+  if (list == null) {
+    map.set(key, [value])
+  }
+  else if (!list.includes(value)) {
+    list.push(value)
+  }
+}
+
+export function replaceDefault(inList: Array<string> | null | undefined, defaultList: Array<string>): Array<string> {
+  if (inList == null) {
+    return defaultList
+  }
+
+  const index = inList.indexOf("default")
+  if (index >= 0) {
+    let list = inList.slice(0, index)
+    list.push(...defaultList)
+    if (index != (inList.length - 1)) {
+      list.push(...inList.slice(index + 1))
+    }
+    inList = list
+  }
+  return inList
 }
\ No newline at end of file
diff --git a/packages/electron-builder/package.json b/packages/electron-builder/package.json
index 9ebc1287b61..3530748719e 100644
--- a/packages/electron-builder/package.json
+++ b/packages/electron-builder/package.json
@@ -63,7 +63,7 @@
     "isbinaryfile": "^3.0.2",
     "js-yaml": "^3.8.2",
     "minimatch": "^3.0.3",
-    "normalize-package-data": "^2.3.5",
+    "normalize-package-data": "^2.3.6",
     "parse-color": "^1.0.0",
     "plist": "^2.0.1",
     "sanitize-filename": "^1.6.1",
diff --git a/packages/electron-builder/src/builder.ts b/packages/electron-builder/src/builder.ts
index 24be562534c..0d769326e23 100644
--- a/packages/electron-builder/src/builder.ts
+++ b/packages/electron-builder/src/builder.ts
@@ -1,14 +1,13 @@
 import BluebirdPromise from "bluebird-lst"
-import { Arch, archFromString, Platform } from "electron-builder-core"
+import { Arch, archFromString, DIR_TARGET, Platform } from "electron-builder-core"
 import { CancellationToken } from "electron-builder-http/out/CancellationToken"
-import { isEmptyOrSpaces } from "electron-builder-util"
+import { addValue, isEmptyOrSpaces } from "electron-builder-util"
 import { warn } from "electron-builder-util/out/log"
 import { executeFinally } from "electron-builder-util/out/promise"
 import { PublishOptions } from "electron-publish"
 import { normalizePlatforms, Packager } from "./packager"
 import { PackagerOptions } from "./packagerApi"
 import { PublishManager } from "./publish/PublishManager"
-import { DIR_TARGET } from "./targets/targetFactory"
 
 export interface BuildOptions extends PackagerOptions, PublishOptions {
 }
@@ -31,16 +30,6 @@ export interface CliOptions extends PackagerOptions, PublishOptions {
   project?: string
 }
 
-function addValue<K, T>(map: Map<K, Array<T>>, key: K, value: T) {
-  const list = map.get(key)
-  if (list == null) {
-    map.set(key, [value])
-  }
-  else {
-    list.push(value)
-  }
-}
-
 export function normalizeOptions(args: CliOptions): BuildOptions {
   if (args.targets != null) {
     return args
@@ -49,14 +38,11 @@ export function normalizeOptions(args: CliOptions): BuildOptions {
   let targets = new Map<Platform, Map<Arch, Array<string>>>()
 
   function processTargets(platform: Platform, types: Array<string>) {
-    if (args.platform != null) {
-      throw new Error(`--platform cannot be used if --${platform.buildConfigurationKey} is passed`)
-    }
-    if (args.arch != null) {
-      throw new Error(`--arch cannot be used if --${platform.buildConfigurationKey} is passed`)
-    }
+    function commonArch(currentIfNotSpecified: boolean): Array<Arch> {
+      if (platform === Platform.MAC) {
+        return args.x64 || currentIfNotSpecified ? [Arch.x64] : []
+      }
 
-    function commonArch(): Array<Arch> {
       const result = Array<Arch>()
       if (args.x64) {
         result.push(Arch.x64)
@@ -68,7 +54,14 @@ export function normalizeOptions(args: CliOptions): BuildOptions {
         result.push(Arch.ia32)
       }
 
-      return result.length === 0 ? [archFromString(process.arch)] : result
+      return result.length === 0 && currentIfNotSpecified ? [archFromString(process.arch)] : result
+    }
+
+    if (args.platform != null) {
+      throw new Error(`--platform cannot be used if --${platform.buildConfigurationKey} is passed`)
+    }
+    if (args.arch != null) {
+      throw new Error(`--arch cannot be used if --${platform.buildConfigurationKey} is passed`)
     }
 
     let archToType = targets.get(platform)
@@ -79,32 +72,20 @@ export function normalizeOptions(args: CliOptions): BuildOptions {
 
     if (types.length === 0) {
       const defaultTargetValue = args.dir ? [DIR_TARGET] : []
-      if (platform === Platform.MAC) {
-        archToType.set(Arch.x64, defaultTargetValue)
-      }
-      else {
-        for (const arch of commonArch()) {
-          archToType.set(arch, defaultTargetValue)
-        }
+      for (const arch of commonArch(args.dir === true)) {
+        archToType.set(arch, defaultTargetValue)
       }
       return
     }
 
     for (const type of types) {
-      let arch: string
-      if (platform === Platform.MAC) {
-        arch = "x64"
-        addValue(archToType, Arch.x64, type)
+      const suffixPos = type.lastIndexOf(":")
+      if (suffixPos > 0) {
+        addValue(archToType, archFromString(type.substring(suffixPos + 1)), type.substring(0, suffixPos))
       }
       else {
-        const suffixPos = type.lastIndexOf(":")
-        if (suffixPos > 0) {
-          addValue(archToType, archFromString(type.substring(suffixPos + 1)), type.substring(0, suffixPos))
-        }
-        else {
-          for (const arch of commonArch()) {
-            addValue(archToType, arch, type)
-          }
+        for (const arch of commonArch(true)) {
+          addValue(archToType, arch, type)
         }
       }
     }
diff --git a/packages/electron-builder/src/index.ts b/packages/electron-builder/src/index.ts
index d51cea3e9ec..3ac5f5145bd 100644
--- a/packages/electron-builder/src/index.ts
+++ b/packages/electron-builder/src/index.ts
@@ -1,9 +1,8 @@
 export { Packager } from "./packager"
 export { PackagerOptions, ArtifactCreated, BuildInfo, SourceRepositoryInfo } from "./packagerApi"
-export { getArchSuffix, Platform, Arch, archFromString, Target } from "electron-builder-core"
+export { getArchSuffix, Platform, Arch, archFromString, Target, DIR_TARGET } from "electron-builder-core"
 export { BuildOptions, build, CliOptions, createTargets } from "./builder"
 export { Metadata, Config, CompressionLevel, FilePattern } from "./metadata"
 export { MacOptions, DmgOptions, MasBuildOptions, MacOsTargetName, PkgOptions } from "./options/macOptions"
 export { WinBuildOptions, NsisOptions, SquirrelWindowsOptions, AppXOptions } from "./options/winOptions"
-export { LinuxBuildOptions, DebOptions } from "./options/linuxOptions"
-export { DIR_TARGET } from "./targets/targetFactory"
\ No newline at end of file
+export { LinuxBuildOptions, DebOptions } from "./options/linuxOptions"
\ No newline at end of file
diff --git a/packages/electron-builder/src/linuxPackager.ts b/packages/electron-builder/src/linuxPackager.ts
index 224f3b0cd94..c5bbc7f7989 100755
--- a/packages/electron-builder/src/linuxPackager.ts
+++ b/packages/electron-builder/src/linuxPackager.ts
@@ -1,4 +1,4 @@
-import { Platform, Target } from "electron-builder-core"
+import { DIR_TARGET, Platform, Target } from "electron-builder-core"
 import { rename } from "fs-extra-p"
 import * as path from "path"
 import sanitizeFileName from "sanitize-filename"
@@ -9,7 +9,7 @@ import AppImageTarget from "./targets/appImage"
 import FpmTarget from "./targets/fpm"
 import { LinuxTargetHelper } from "./targets/LinuxTargetHelper"
 import SnapTarget from "./targets/snap"
-import { createCommonTarget, DIR_TARGET } from "./targets/targetFactory"
+import { createCommonTarget } from "./targets/targetFactory"
 
 export class LinuxPackager extends PlatformPackager<LinuxBuildOptions> {
   readonly executableName: string
diff --git a/packages/electron-builder/src/macPackager.ts b/packages/electron-builder/src/macPackager.ts
index be4694594d8..04c754db6e9 100644
--- a/packages/electron-builder/src/macPackager.ts
+++ b/packages/electron-builder/src/macPackager.ts
@@ -1,5 +1,5 @@
 import BluebirdPromise from "bluebird-lst"
-import { Arch, Platform, Target } from "electron-builder-core"
+import { Arch, DIR_TARGET, Platform, Target } from "electron-builder-core"
 import { exec } from "electron-builder-util"
 import { deepAssign } from "electron-builder-util/out/deepAssign"
 import { log, task, warn } from "electron-builder-util/out/log"
@@ -13,7 +13,7 @@ import { BuildInfo } from "./packagerApi"
 import { PlatformPackager } from "./platformPackager"
 import { DmgTarget } from "./targets/dmg"
 import { PkgTarget, prepareProductBuildArgs } from "./targets/pkg"
-import { createCommonTarget, DIR_TARGET, NoOpTarget } from "./targets/targetFactory"
+import { createCommonTarget, NoOpTarget } from "./targets/targetFactory"
 
 export default class MacPackager extends PlatformPackager<MacOptions> {
   readonly codeSigningInfo: Promise<CodeSigningInfo>
diff --git a/packages/electron-builder/src/metadata.ts b/packages/electron-builder/src/metadata.ts
index 9eb75008c2b..439ee883972 100755
--- a/packages/electron-builder/src/metadata.ts
+++ b/packages/electron-builder/src/metadata.ts
@@ -1,6 +1,6 @@
-import { Arch, Platform, Target, TargetSpecificOptions } from "electron-builder-core"
+import { Arch, Platform, Target, TargetConfig, TargetSpecificOptions } from "electron-builder-core"
 import { Publish } from "electron-builder-http/out/publishOptions"
-import { DebOptions, LinuxBuildOptions, SnapOptions } from "./options/linuxOptions"
+import { AppImageOptions, DebOptions, LinuxBuildOptions, SnapOptions } from "./options/linuxOptions"
 import { DmgOptions, MacOptions, MasBuildOptions, PkgOptions } from "./options/macOptions"
 import { AppXOptions, NsisOptions, SquirrelWindowsOptions, WinBuildOptions } from "./options/winOptions"
 import { PlatformPackager } from "./platformPackager"
@@ -143,13 +143,20 @@ export interface Config extends PlatformSpecificBuildOptions, TargetSpecificOpti
 
   readonly win?: WinBuildOptions  | null
   readonly nsis?: NsisOptions  | null
+  readonly portable?: NsisOptions  | null
   readonly pkg?: PkgOptions  | null
-  readonly squirrelWindows?: SquirrelWindowsOptions  | null
   readonly appx?: AppXOptions  | null
+  readonly squirrelWindows?: SquirrelWindowsOptions  | null
 
   readonly linux?: LinuxBuildOptions | null
   readonly deb?: DebOptions | null
   readonly snap?: SnapOptions | null
+  readonly appimage?: AppImageOptions | null
+  readonly pacman?: LinuxBuildOptions | null
+  readonly rpm?: LinuxBuildOptions | null
+  readonly freebsd?: LinuxBuildOptions | null
+  readonly p5p?: LinuxBuildOptions | null
+  readonly apk?: LinuxBuildOptions | null
 
   /**
    The compression level, one of `store`, `normal`, `maximum` (default: `normal`). If you want to rapidly test build, `store` can reduce build time significantly.
@@ -336,7 +343,7 @@ export interface PlatformSpecificBuildOptions extends TargetSpecificOptions {
 
   readonly asar?: AsarOptions | boolean | null
 
-  readonly target?: Array<string> | string | null
+  readonly target?: Array<string | TargetConfig> | string | TargetConfig | null
 
   readonly icon?: string | null
 
diff --git a/packages/electron-builder/src/options/linuxOptions.ts b/packages/electron-builder/src/options/linuxOptions.ts
index f94fad73774..07e20f5093a 100644
--- a/packages/electron-builder/src/options/linuxOptions.ts
+++ b/packages/electron-builder/src/options/linuxOptions.ts
@@ -1,3 +1,4 @@
+import { TargetConfigType } from "electron-builder-core"
 import { PlatformSpecificBuildOptions } from "../metadata"
 
 /**
@@ -26,7 +27,7 @@ export interface LinuxBuildOptions extends PlatformSpecificBuildOptions {
 
    electron-builder [docker image](https://github.com/electron-userland/electron-builder/wiki/Docker) can be used to build Linux targets on any platform. See [Multi platform build](https://github.com/electron-userland/electron-builder/wiki/Multi-Platform-Build).
    */
-  readonly target?: Array<string> | null
+  readonly target?: TargetConfigType
 
   /**
    The maintainer. Defaults to [author](#AppMetadata-author).
diff --git a/packages/electron-builder/src/options/macOptions.ts b/packages/electron-builder/src/options/macOptions.ts
index 2825e545172..13f8f990d66 100644
--- a/packages/electron-builder/src/options/macOptions.ts
+++ b/packages/electron-builder/src/options/macOptions.ts
@@ -1,4 +1,4 @@
-import { TargetSpecificOptions } from "electron-builder-core"
+import { TargetConfig, TargetSpecificOptions } from "electron-builder-core"
 import { PlatformSpecificBuildOptions } from "../metadata"
 
 export type MacOsTargetName = "default" | "dmg" | "mas" | "pkg" | "7z" | "zip" | "tar.xz" | "tar.lz" | "tar.gz" | "tar.bz2" | "dir"
@@ -19,7 +19,7 @@ export interface MacOptions extends PlatformSpecificBuildOptions {
   /**
    The target package type: list of `default`, `dmg`, `mas`, `pkg`, `7z`, `zip`, `tar.xz`, `tar.lz`, `tar.gz`, `tar.bz2`, `dir`. Defaults to `default` (dmg and zip for Squirrel.Mac).
   */
-  readonly target?: Array<MacOsTargetName> | null
+  readonly target?: Array<MacOsTargetName | TargetConfig> | MacOsTargetName | TargetConfig | null
 
   /**
    The name of certificate to use when signing. Consider using environment variables [CSC_LINK or CSC_NAME](https://github.com/electron-userland/electron-builder/wiki/Code-Signing) instead of specifying this option.
diff --git a/packages/electron-builder/src/options/winOptions.ts b/packages/electron-builder/src/options/winOptions.ts
index 6af2c7d6d4d..1ca3d672e65 100644
--- a/packages/electron-builder/src/options/winOptions.ts
+++ b/packages/electron-builder/src/options/winOptions.ts
@@ -1,3 +1,4 @@
+import { TargetConfigType } from "electron-builder-core"
 import { PlatformSpecificBuildOptions } from "../metadata"
 
 /**
@@ -11,7 +12,7 @@ export interface WinBuildOptions extends PlatformSpecificBuildOptions {
 
    To use Squirrel.Windows please install `electron-builder-squirrel-windows` dependency.
   */
-  readonly target?: Array<string> | null
+  readonly target?: TargetConfigType
 
   /**
    Array of signing algorithms used. Defaults to `['sha1', 'sha256']`
diff --git a/packages/electron-builder/src/packager.ts b/packages/electron-builder/src/packager.ts
index b40ca1245ab..a935745542d 100644
--- a/packages/electron-builder/src/packager.ts
+++ b/packages/electron-builder/src/packager.ts
@@ -17,7 +17,7 @@ import { AfterPackContext, Config, Metadata } from "./metadata"
 import { ArtifactCreated, BuildInfo, PackagerOptions, SourceRepositoryInfo } from "./packagerApi"
 import { PlatformPackager } from "./platformPackager"
 import { getRepositoryInfo } from "./repositoryInfo"
-import { createTargets, NoOpTarget } from "./targets/targetFactory"
+import { computeArchToTargetNamesMap, createTargets, NoOpTarget } from "./targets/targetFactory"
 import { doLoadConfig, getElectronVersion, loadConfig, readPackageJson, validateConfig } from "./util/readPackageJson"
 import { WinPackager } from "./winPackager"
 import { getGypEnv, installOrRebuild } from "./yarn"
@@ -86,7 +86,7 @@ export class Packager implements BuildInfo {
     this.eventEmitter.emit("artifactCreated", event)
   }
 
-  async build(): Promise<Map<Platform, Map<String, Target>>> {
+  async build(): Promise<BuildResult> {
     //noinspection JSDeprecatedSymbols
     const devMetadataFromOptions = this.options.devMetadata
     if (devMetadataFromOptions != null) {
@@ -160,7 +160,11 @@ export class Packager implements BuildInfo {
 
     this.appInfo = new AppInfo(this.metadata, this)
     const cleanupTasks: Array<() => Promise<any>> = []
-    return await executeFinally(this.doBuild(cleanupTasks), () => all(cleanupTasks.map(it => it()).concat(this.tempDirManager.cleanup())))
+    const outDir = path.resolve(this.projectDir, use(this.config.directories, it => it!.output) || "dist")
+    return {
+      outDir: outDir,
+      platformToTargets: await executeFinally(this.doBuild(outDir, cleanupTasks), () => all(cleanupTasks.map(it => it()).concat(this.tempDirManager.cleanup())))
+    }
   }
 
   private async readProjectMetadata(appPackageFile: string, extraMetadata: any) {
@@ -190,12 +194,9 @@ export class Packager implements BuildInfo {
     }
   }
 
-  private async doBuild(cleanupTasks: Array<() => Promise<any>>): Promise<Map<Platform, Map<String, Target>>> {
+  private async doBuild(outDir: string, cleanupTasks: Array<() => Promise<any>>): Promise<Map<Platform, Map<String, Target>>> {
     const distTasks: Array<Promise<any>> = []
-    const outDir = path.resolve(this.projectDir, use(this.config.directories, it => it!.output) || "dist")
-
-    const platformToTarget: Map<Platform, Map<String, Target>> = new Map()
-
+    const platformToTarget = new Map<Platform, Map<String, Target>>()
     const createdOutDirs = new Set<string>()
 
     // custom packager - don't check wine
@@ -214,11 +215,11 @@ export class Packager implements BuildInfo {
         wineCheck = exec("wine", ["--version"])
       }
 
-      const helper = this.createHelper(platform, cleanupTasks)
+      const packager = this.createHelper(platform, cleanupTasks)
       const nameToTarget: Map<String, Target> = new Map()
       platformToTarget.set(platform, nameToTarget)
 
-      for (const [arch, targets] of archToType) {
+      for (const [arch, targetNames] of computeArchToTargetNamesMap(archToType, packager.platformSpecificBuildOptions, platform)) {
         if (this.cancellationToken.cancelled) {
           break
         }
@@ -234,7 +235,7 @@ export class Packager implements BuildInfo {
           await checkWineVersion(wineCheck)
         }
 
-        const targetList = createTargets(nameToTarget, targets, outDir, helper, cleanupTasks)
+        const targetList = createTargets(nameToTarget, targetNames.length === 0 ? packager.defaultTarget : targetNames, outDir, packager, cleanupTasks)
         const ourDirs = new Set<string>()
         for (const target of targetList) {
           if (!(target instanceof NoOpTarget) && !createdOutDirs.has(target.outDir)) {
@@ -249,7 +250,7 @@ export class Packager implements BuildInfo {
           })
         }
 
-        await helper.pack(outDir, arch, targetList, distTasks)
+        await packager.pack(outDir, arch, targetList, distTasks)
       }
 
       if (this.cancellationToken.cancelled) {
@@ -492,4 +493,9 @@ function checkDependencies(dependencies: { [key: string]: string } | null | unde
         + `Please remove it from the "dependencies" section in your package.json.`)
     }
   }
+}
+
+export interface BuildResult {
+  readonly outDir: string
+  readonly platformToTargets: Map<Platform, Map<String, Target>>
 }
\ No newline at end of file
diff --git a/packages/electron-builder/src/packagerApi.ts b/packages/electron-builder/src/packagerApi.ts
index 46f591c9a84..c47b1aad818 100644
--- a/packages/electron-builder/src/packagerApi.ts
+++ b/packages/electron-builder/src/packagerApi.ts
@@ -7,7 +7,7 @@ import { AfterPackContext, Config, Metadata } from "./metadata"
 import { PlatformPackager } from "./platformPackager"
 
 export interface PackagerOptions {
-  targets?: Map<Platform, Map<Arch, string[]>>
+  targets?: Map<Platform, Map<Arch, Array<string>>>
 
   projectDir?: string | null
 
diff --git a/packages/electron-builder/src/targets/appImage.ts b/packages/electron-builder/src/targets/appImage.ts
index 5911d93f4f5..1d6eb8f4ccf 100644
--- a/packages/electron-builder/src/targets/appImage.ts
+++ b/packages/electron-builder/src/targets/appImage.ts
@@ -69,7 +69,7 @@ export default class AppImageTarget extends Target {
     }
 
     args.push("-chown_r", "0", "/", "--")
-    args.push("-zisofs", `level=${packager.config.compression === "store" ? "0" : "9"}:block_size=128k:by_magic=off`)
+    args.push("-zisofs", `level=${process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL || (packager.config.compression === "store" ? "0" : "9")}:block_size=128k:by_magic=off`)
     args.push("set_filter_r", "--zisofs", "/")
 
     if (this.packager.packagerOptions.effectiveOptionComputed != null && await this.packager.packagerOptions.effectiveOptionComputed([args, desktopFile])) {
diff --git a/packages/electron-builder/src/targets/archive.ts b/packages/electron-builder/src/targets/archive.ts
index 293f852304f..5ecd3e6017d 100644
--- a/packages/electron-builder/src/targets/archive.ts
+++ b/packages/electron-builder/src/targets/archive.ts
@@ -1,9 +1,9 @@
-import { spawn, debug7zArgs } from "electron-builder-util"
-import { CompressionLevel } from "../metadata"
-import * as path from "path"
-import { unlink } from "fs-extra-p"
 import { path7za } from "7zip-bin"
+import { debug7zArgs, spawn } from "electron-builder-util"
 import { exists } from "electron-builder-util/out/fs"
+import { unlink } from "fs-extra-p"
+import * as path from "path"
+import { CompressionLevel } from "../metadata"
 
 class CompressionDescriptor {
   constructor(public flag: string, public env: string, public minLevel: string, public maxLevel: string = "-9") {
@@ -22,7 +22,11 @@ export async function tar(compression: CompressionLevel | n, format: string, out
   // and in any case it is better to use system tools (in the light of docker - it is not problem for user because we provide complete docker image).
   const info = extToCompressionDescriptor[format]
   let tarEnv = process.env
-  if (compression != null && compression !== "normal") {
+  if (process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL != null) {
+    tarEnv = Object.assign({}, process.env)
+    tarEnv[info.env] = "-" + process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL
+  }
+  else if (compression != null && compression !== "normal") {
     tarEnv = Object.assign({}, process.env)
     tarEnv[info.env] = compression === "store" ? info.minLevel : info.maxLevel
   }
@@ -40,25 +44,27 @@ export async function tar(compression: CompressionLevel | n, format: string, out
 }
 
 export async function archive(compression: CompressionLevel | n, format: string, outFile: string, dirToArchive: string, withoutDir: boolean = false): Promise<string> {
-  const storeOnly = compression === "store"
+  let storeOnly = compression === "store"
   const args = debug7zArgs("a")
   if (format === "7z" || format.endsWith(".7z")) {
-    if (!storeOnly) {
+    if (process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL != null) {
+      storeOnly = false
+      args.push(`-mx=${process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL}`)
+    }
+    else if (!storeOnly) {
       // 7z is very fast, so, use ultra compression
       args.push("-mx=9", "-mfb=64", "-md=64m", "-ms=on")
     }
   }
-  else if (format === "zip") {
-    if (compression === "maximum") {
-      // http://superuser.com/a/742034
-      //noinspection SpellCheckingInspection
-      args.push("-mfb=258", "-mpass=15")
-    }
-    else if (!storeOnly) {
-      args.push("-mpass=7")
-    }
+  else if (format === "zip" && compression === "maximum") {
+    // http://superuser.com/a/742034
+    args.push("-mfb=258", "-mpass=15")
+  }
+  else if (process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL != null) {
+    storeOnly = false
+    args.push(`-mx=${process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL}`)
   }
-  else if (compression === "maximum") {
+  else if (!storeOnly) {
     args.push("-mx=9")
   }
 
diff --git a/packages/electron-builder/src/targets/dmg.ts b/packages/electron-builder/src/targets/dmg.ts
index 438c8a861aa..98359740d9a 100644
--- a/packages/electron-builder/src/targets/dmg.ts
+++ b/packages/electron-builder/src/targets/dmg.ts
@@ -166,7 +166,7 @@ export class DmgTarget extends Target {
 
     // dmg file must not exist otherwise hdiutil failed (https://github.com/electron-userland/electron-builder/issues/1308#issuecomment-282847594), so, -ov must be specified
     //noinspection SpellCheckingInspection
-    await spawn("hdiutil", addVerboseIfNeed(["convert", tempDmg, "-ov", "-format", specification.format!, "-imagekey", "zlib-level=9", "-o", artifactPath]))
+    await spawn("hdiutil", addVerboseIfNeed(["convert", tempDmg, "-ov", "-format", specification.format!, "-imagekey", `zlib-level=${process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL || "9"}`, "-o", artifactPath]))
     await exec("hdiutil", addVerboseIfNeed(["internet-enable", "-no"]).concat(artifactPath))
 
     this.packager.dispatchArtifactCreated(artifactPath, this, `${appInfo.name}-${appInfo.version}.dmg`)
@@ -253,7 +253,10 @@ export class DmgTarget extends Target {
     }
 
     if (specification.format == null) {
-      if (packager.config.compression === "store") {
+      if (process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL != null) {
+        specification.format = "UDZO"
+      }
+      else if (packager.config.compression === "store") {
         specification.format = "UDRO"
       }
       else {
diff --git a/packages/electron-builder/src/targets/snap.ts b/packages/electron-builder/src/targets/snap.ts
index 0099717ae00..51d4105451a 100644
--- a/packages/electron-builder/src/targets/snap.ts
+++ b/packages/electron-builder/src/targets/snap.ts
@@ -1,5 +1,5 @@
 import { Arch, Target, toLinuxArchString } from "electron-builder-core"
-import { spawn } from "electron-builder-util"
+import { replaceDefault, spawn } from "electron-builder-util"
 import { log } from "electron-builder-util/out/log"
 import { copy, emptyDir, outputFile } from "fs-extra-p"
 import { safeDump } from "js-yaml"
@@ -128,21 +128,4 @@ export default class SnapTarget extends Target {
     }
     packager.dispatchArtifactCreated(resultFile, this)
   }
-}
-
-function replaceDefault(inList: Array<string> | n, defaultList: Array<string>): Array<string> {
-  if (inList == null) {
-    return defaultList
-  }
-
-  const index = inList.indexOf("default")
-  if (index >= 0) {
-    let list = inList.slice(0, index)
-    list.push(...defaultList)
-    if (index != (inList.length - 1)) {
-      list.push(...inList.slice(index + 1))
-    }
-    inList = list
-  }
-  return inList
 }
\ No newline at end of file
diff --git a/packages/electron-builder/src/targets/targetFactory.ts b/packages/electron-builder/src/targets/targetFactory.ts
index 636920ddb0c..e8454aec6a0 100644
--- a/packages/electron-builder/src/targets/targetFactory.ts
+++ b/packages/electron-builder/src/targets/targetFactory.ts
@@ -1,12 +1,38 @@
+import { Arch, archFromString, DEFAULT_TARGET, DIR_TARGET, Platform, Target, TargetConfig } from "electron-builder-core"
+import { addValue, asArray } from "electron-builder-util"
+import { PlatformSpecificBuildOptions } from "../metadata"
 import { PlatformPackager } from "../platformPackager"
-import { Arch, Target } from "electron-builder-core"
 import { ArchiveTarget } from "./ArchiveTarget"
 
 const archiveTargets = new Set(["zip", "7z", "tar.xz", "tar.lz", "tar.gz", "tar.bz2"])
-export const DEFAULT_TARGET = "default"
-export const DIR_TARGET = "dir"
 
-export function createTargets(nameToTarget: Map<String, Target>, rawList: Array<string> | n, outDir: string, packager: PlatformPackager<any>, cleanupTasks: Array<() => Promise<any>>): Array<Target> {
+export function computeArchToTargetNamesMap(raw: Map<Arch, string[]>, options: PlatformSpecificBuildOptions, platform: Platform): Map<Arch, string[]> {
+  const result = new Map(raw)
+  const defaultArch = platform === Platform.MAC ? "x64" : process.arch
+  for (const target of asArray(options.target).map<TargetConfig>(it => typeof it === "string" ? {target: it} : it)) {
+    let name = target.target
+    let archs = target.arch
+    const suffixPos = name.lastIndexOf(":")
+    if (suffixPos > 0) {
+      name = target.target.substring(0, suffixPos)
+      if (archs == null) {
+        archs = target.target.substring(suffixPos + 1)
+      }
+    }
+
+    for (const arch of asArray(archs || defaultArch)) {
+      addValue(result, archFromString(arch), name)
+    }
+  }
+
+  if (result.size === 0) {
+    result.set(archFromString(defaultArch), [])
+  }
+
+  return result
+}
+
+export function createTargets(nameToTarget: Map<String, Target>, rawList: Array<string>, outDir: string, packager: PlatformPackager<any>, cleanupTasks: Array<() => Promise<any>>): Array<Target> {
   const result: Array<Target> = []
 
   const mapper = (name: string, factory: (outDir: string) => Target) => {
@@ -18,18 +44,14 @@ export function createTargets(nameToTarget: Map<String, Target>, rawList: Array<
     result.push(target)
   }
 
-  const targets = normalizeTargets(rawList == null || rawList.length === 0 ? packager.platformSpecificBuildOptions.target : rawList, packager.defaultTarget)
+  const targets = normalizeTargets(rawList, packager.defaultTarget)
   packager.createTargets(targets, mapper, cleanupTasks)
   return result
 }
 
-function normalizeTargets(targets: Array<string> | string | null | undefined, defaultTarget: Array<string>): Array<string> {
-  if (targets == null) {
-    return defaultTarget
-  }
-
+function normalizeTargets(targets: Array<string>, defaultTarget: Array<string>): Array<string> {
   const list: Array<string> = []
-  for (const t of (Array.isArray(targets) ? targets : [targets])) {
+  for (const t of targets) {
     const name = t.toLowerCase().trim()
     if (name === DEFAULT_TARGET) {
       list.push(...defaultTarget)
@@ -45,8 +67,8 @@ export function createCommonTarget(target: string, outDir: string, packager: Pla
   if (archiveTargets.has(target)) {
     return new ArchiveTarget(target, outDir, packager)
   }
-  else if (target === "dir") {
-    return new NoOpTarget("dir")
+  else if (target === DIR_TARGET) {
+    return new NoOpTarget(DIR_TARGET)
   }
   else {
     throw new Error(`Unknown target: ${target}`)
diff --git a/packages/electron-builder/src/winPackager.ts b/packages/electron-builder/src/winPackager.ts
index 87c1d572dbb..67cc0dcb735 100644
--- a/packages/electron-builder/src/winPackager.ts
+++ b/packages/electron-builder/src/winPackager.ts
@@ -1,5 +1,5 @@
 import BluebirdPromise from "bluebird-lst"
-import { Platform, Target } from "electron-builder-core"
+import { DIR_TARGET, Platform, Target } from "electron-builder-core"
 import { asArray, exec, Lazy, use } from "electron-builder-util"
 import { log } from "electron-builder-util/out/log"
 import { close, open, read, readFile, rename } from "fs-extra-p"
@@ -11,7 +11,7 @@ import { BuildInfo } from "./packagerApi"
 import { PlatformPackager } from "./platformPackager"
 import AppXTarget from "./targets/appx"
 import NsisTarget from "./targets/nsis"
-import { createCommonTarget, DIR_TARGET } from "./targets/targetFactory"
+import { createCommonTarget } from "./targets/targetFactory"
 import { FileCodeSigningInfo, getSignVendorPath, sign, SignOptions } from "./windowsCodeSign"
 
 export class WinPackager extends PlatformPackager<WinBuildOptions> {
diff --git a/packages/electron-publisher-s3/package.json b/packages/electron-publisher-s3/package.json
index bdae7454468..717a38f6662 100644
--- a/packages/electron-publisher-s3/package.json
+++ b/packages/electron-publisher-s3/package.json
@@ -12,7 +12,7 @@
   ],
   "dependencies": {
     "fs-extra-p": "^4.0.2",
-    "aws-sdk": "^2.22.0",
+    "aws-sdk": "^2.24.0",
     "mime": "^1.3.4",
     "electron-publish": "~0.0.0-semantic-release",
     "electron-builder-util": "~0.0.0-semantic-release"
diff --git a/test/out/__snapshots__/BuildTest.js.snap b/test/out/__snapshots__/BuildTest.js.snap
index cc5a3149500..754124f87ac 100644
--- a/test/out/__snapshots__/BuildTest.js.snap
+++ b/test/out/__snapshots__/BuildTest.js.snap
@@ -1,5 +1,19 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`afterPack 1`] = `
+Object {
+  "linux": Array [],
+  "mac": Array [],
+}
+`;
+
+exports[`beforeBuild 1`] = `
+Object {
+  "linux": Array [],
+  "mac": Array [],
+}
+`;
+
 exports[`build in the app package.json 1`] = `"'build' in the application package.json (<path>/package.json) is not supported since 3.0 anymore. Please move 'build' into the development package.json (<path>/package.json)"`;
 
 exports[`cli 1`] = `
@@ -83,9 +97,7 @@ Object {
       "buildConfigurationKey": "linux",
       "name": "linux",
       "nodeName": "linux",
-    } => Map {
-      1 => Array [],
-    },
+    } => Map {},
   },
 }
 `;
@@ -104,9 +116,7 @@ Object {
       "buildConfigurationKey": "win",
       "name": "windows",
       "nodeName": "win32",
-    } => Map {
-      1 => Array [],
-    },
+    } => Map {},
   },
 }
 `;
@@ -125,23 +135,17 @@ Object {
       "buildConfigurationKey": "mac",
       "name": "mac",
       "nodeName": "darwin",
-    } => Map {
-      1 => Array [],
-    },
+    } => Map {},
     Platform {
       "buildConfigurationKey": "linux",
       "name": "linux",
       "nodeName": "linux",
-    } => Map {
-      1 => Array [],
-    },
+    } => Map {},
     Platform {
       "buildConfigurationKey": "win",
       "name": "windows",
       "nodeName": "win32",
-    } => Map {
-      1 => Array [],
-    },
+    } => Map {},
   },
 }
 `;
@@ -237,3 +241,39 @@ Object {
   },
 }
 `;
+
+exports[`electron version from build 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
+exports[`electron version from electron dependency 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
+exports[`electron version from electron-prebuilt dependency 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
+exports[`relative index 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
+exports[`smart unpack 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
+exports[`www as default dir 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
diff --git a/test/out/__snapshots__/ExtraBuildTest.js.snap b/test/out/__snapshots__/ExtraBuildTest.js.snap
index b78c9509dce..0aa3d858899 100644
--- a/test/out/__snapshots__/ExtraBuildTest.js.snap
+++ b/test/out/__snapshots__/ExtraBuildTest.js.snap
@@ -1,21 +1,36 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`custom buildResources and output dirs: linux 1`] = `
-Array [
-  Object {
-    "file": "TestApp-1.1.0-x86_64.AppImage",
-    "safeArtifactName": undefined,
-  },
-]
+Object {
+  "linux": Array [
+    Object {
+      "file": "TestApp-1.1.0-x86_64.AppImage",
+    },
+  ],
+}
+`;
+
+exports[`custom buildResources and output dirs: mac 1`] = `
+Object {
+  "mac": Array [],
+}
 `;
 
 exports[`custom buildResources and output dirs: win 1`] = `
-Array [
-  Object {
-    "file": "Test App ßW Setup 1.1.0.exe",
-    "safeArtifactName": "TestApp-Setup-1.1.0.exe",
-  },
-]
+Object {
+  "win": Array [
+    Object {
+      "file": "Test App ßW Setup 1.1.0.exe",
+      "safeArtifactName": "TestApp-Setup-1.1.0.exe",
+    },
+  ],
+}
+`;
+
+exports[`prepackaged 1`] = `
+Object {
+  "linux": Array [],
+}
 `;
 
 exports[`scheme validation 1`] = `
@@ -86,3 +101,17 @@ Raw validation errors: [
   }
 ]"
 `;
+
+exports[`scheme validation extraFiles 1`] = `
+Object {
+  "linux": Array [
+    Object {
+      "file": "TestApp-1.1.0-x86_64.AppImage",
+    },
+    Object {
+      "file": "TestApp-1.1.0-ia32.zip",
+      "safeArtifactName": "TestApp-1.1.0-ia32.zip",
+    },
+  ],
+}
+`;
diff --git a/test/out/__snapshots__/extraMetadataTest.js.snap b/test/out/__snapshots__/extraMetadataTest.js.snap
index 255e8ea8fbc..cab50c80ed3 100644
--- a/test/out/__snapshots__/extraMetadataTest.js.snap
+++ b/test/out/__snapshots__/extraMetadataTest.js.snap
@@ -2,7 +2,19 @@
 
 exports[`extra metadata - override icon 1`] = `"Cannot find specified resource \\"dev.icns\\""`;
 
+exports[`extra metadata - two 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
 exports[`extra metadata 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
+exports[`extra metadata 2`] = `
 Object {
   "author": "Foo Bar <foo@example.com>",
   "description": "Test Application (test quite \\" #378)",
diff --git a/test/out/__snapshots__/filesTest.js.snap b/test/out/__snapshots__/filesTest.js.snap
index b90783f6c97..1abe527cdd1 100644
--- a/test/out/__snapshots__/filesTest.js.snap
+++ b/test/out/__snapshots__/filesTest.js.snap
@@ -2,19 +2,49 @@
 
 exports[`expand not defined env 1`] = `"Env FOO_NOT_DEFINED is not defined"`;
 
+exports[`extraResources - two-package 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
 exports[`extraResources on Linux and Windows 1`] = `
-Array [
-  Object {
-    "file": "Test App ßW Setup 1.1.0.exe",
-    "safeArtifactName": "TestApp-Setup-1.1.0.exe",
-  },
-  Object {
-    "file": "TestApp-1.1.0-full.nupkg",
-    "safeArtifactName": undefined,
-  },
-  Object {
-    "file": "RELEASES",
-    "safeArtifactName": undefined,
-  },
-]
+Object {
+  "linux": Array [],
+}
+`;
+
+exports[`extraResources on Linux and Windows 2`] = `
+Object {
+  "win": Array [
+    Object {
+      "file": "RELEASES",
+    },
+    Object {
+      "file": "Test App ßW Setup 1.1.0.exe",
+      "safeArtifactName": "TestApp-Setup-1.1.0.exe",
+    },
+    Object {
+      "file": "TestApp-1.1.0-full.nupkg",
+    },
+  ],
+}
+`;
+
+exports[`extraResources on macOS 1`] = `
+Object {
+  "mac": Array [],
+}
+`;
+
+exports[`files 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
+exports[`map resources 1`] = `
+Object {
+  "linux": Array [],
+}
 `;
diff --git a/test/out/__snapshots__/globTest.js.snap b/test/out/__snapshots__/globTest.js.snap
index f815c54c553..072668de96e 100644
--- a/test/out/__snapshots__/globTest.js.snap
+++ b/test/out/__snapshots__/globTest.js.snap
@@ -1,14 +1,44 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`failed peer dep 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
 exports[`link 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
+exports[`link 2`] = `
 Object {
   "link": "index.js",
 }
 `;
 
 exports[`outside link 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
+exports[`outside link 2`] = `
 Object {
   "offset": "4876",
   "size": 4,
 }
 `;
+
+exports[`unpackDir 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
+exports[`unpackDir one 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
diff --git a/test/out/__snapshots__/ignoreTest.js.snap b/test/out/__snapshots__/ignoreTest.js.snap
new file mode 100644
index 00000000000..4576f933359
--- /dev/null
+++ b/test/out/__snapshots__/ignoreTest.js.snap
@@ -0,0 +1,19 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ignore build resources 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
+exports[`ignore known ignored files 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
+
+exports[`ignore node_modules dev dep 1`] = `
+Object {
+  "linux": Array [],
+}
+`;
diff --git a/test/out/__snapshots__/mainEntryTest.js.snap b/test/out/__snapshots__/mainEntryTest.js.snap
index d8bcded748d..b89aa62ab9f 100644
--- a/test/out/__snapshots__/mainEntryTest.js.snap
+++ b/test/out/__snapshots__/mainEntryTest.js.snap
@@ -5,3 +5,17 @@ exports[`invalid main in the app package.json (custom asar) 1`] = `"Application
 exports[`invalid main in the app package.json (no asar) 1`] = `"Application entry file \\"main.js\\" does not exist. Seems like a wrong configuration."`;
 
 exports[`invalid main in the app package.json 1`] = `"Application entry file \\"main.js\\" in the \\"<path>/app.asar\\" does not exist. Seems like a wrong configuration."`;
+
+exports[`main in the app package.json (custom asar) 1`] = `
+Object {
+  "linux": Array [],
+  "mac": Array [],
+}
+`;
+
+exports[`main in the app package.json (no asar) 1`] = `
+Object {
+  "linux": Array [],
+  "mac": Array [],
+}
+`;
diff --git a/test/out/linux/__snapshots__/debTest.js.snap b/test/out/linux/__snapshots__/debTest.js.snap
index e1cdbdaf536..b488d325fcf 100644
--- a/test/out/linux/__snapshots__/debTest.js.snap
+++ b/test/out/linux/__snapshots__/debTest.js.snap
@@ -1,12 +1,13 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`arm deb 1`] = `
-Array [
-  Object {
-    "file": "TestApp_1.1.0_armv7l.deb",
-    "safeArtifactName": undefined,
-  },
-]
+Object {
+  "linux": Array [
+    Object {
+      "file": "TestApp_1.1.0_armv7l.deb",
+    },
+  ],
+}
 `;
 
 exports[`custom depends 1`] = `
@@ -22,10 +23,11 @@ Categories=Development;
 `;
 
 exports[`deb 1`] = `
-Array [
-  Object {
-    "file": "TestApp_1.1.0_amd64.deb",
-    "safeArtifactName": undefined,
-  },
-]
+Object {
+  "linux": Array [
+    Object {
+      "file": "TestApp_1.1.0_amd64.deb",
+    },
+  ],
+}
 `;
diff --git a/test/out/linux/__snapshots__/fpmTest.js.snap b/test/out/linux/__snapshots__/fpmTest.js.snap
index bdfbaa83c7c..1b3a5473d9e 100644
--- a/test/out/linux/__snapshots__/fpmTest.js.snap
+++ b/test/out/linux/__snapshots__/fpmTest.js.snap
@@ -1,39 +1,39 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`rpm and tar.gz 1`] = `
-Array [
-  Object {
-    "file": "TestApp-1.1.0.rpm",
-    "safeArtifactName": undefined,
-  },
-  Object {
-    "file": "TestApp-1.1.0.tar.gz",
-    "safeArtifactName": "TestApp-1.1.0.tar.gz",
-  },
-]
+Object {
+  "linux": Array [
+    Object {
+      "file": "TestApp-1.1.0.rpm",
+    },
+    Object {
+      "file": "TestApp-1.1.0.tar.gz",
+      "safeArtifactName": "TestApp-1.1.0.tar.gz",
+    },
+  ],
+}
 `;
 
 exports[`targets 1`] = `
-Array [
-  Object {
-    "file": "TestApp-1.1.0.7z",
-    "safeArtifactName": "TestApp-1.1.0.7z",
-  },
-  Object {
-    "file": "TestApp-1.1.0.freebsd",
-    "safeArtifactName": undefined,
-  },
-  Object {
-    "file": "TestApp-1.1.0.pacman",
-    "safeArtifactName": undefined,
-  },
-  Object {
-    "file": "TestApp-1.1.0.sh",
-    "safeArtifactName": undefined,
-  },
-  Object {
-    "file": "TestApp-1.1.0.zip",
-    "safeArtifactName": "TestApp-1.1.0.zip",
-  },
-]
+Object {
+  "linux": Array [
+    Object {
+      "file": "TestApp-1.1.0.7z",
+      "safeArtifactName": "TestApp-1.1.0.7z",
+    },
+    Object {
+      "file": "TestApp-1.1.0.freebsd",
+    },
+    Object {
+      "file": "TestApp-1.1.0.pacman",
+    },
+    Object {
+      "file": "TestApp-1.1.0.sh",
+    },
+    Object {
+      "file": "TestApp-1.1.0.zip",
+      "safeArtifactName": "TestApp-1.1.0.zip",
+    },
+  ],
+}
 `;
diff --git a/test/out/linux/__snapshots__/linuxArchiveTest.js.snap b/test/out/linux/__snapshots__/linuxArchiveTest.js.snap
index 7ef14d3b198..a99e46e0407 100644
--- a/test/out/linux/__snapshots__/linuxArchiveTest.js.snap
+++ b/test/out/linux/__snapshots__/linuxArchiveTest.js.snap
@@ -1,18 +1,20 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`tar 1`] = `
-Array [
-  Object {
-    "file": "TestApp-1.1.0.tar.bz2",
-    "safeArtifactName": "TestApp-1.1.0.tar.bz2",
-  },
-  Object {
-    "file": "TestApp-1.1.0.tar.lz",
-    "safeArtifactName": "TestApp-1.1.0.tar.lz",
-  },
-  Object {
-    "file": "TestApp-1.1.0.tar.xz",
-    "safeArtifactName": "TestApp-1.1.0.tar.xz",
-  },
-]
+Object {
+  "linux": Array [
+    Object {
+      "file": "TestApp-1.1.0.tar.bz2",
+      "safeArtifactName": "TestApp-1.1.0.tar.bz2",
+    },
+    Object {
+      "file": "TestApp-1.1.0.tar.lz",
+      "safeArtifactName": "TestApp-1.1.0.tar.lz",
+    },
+    Object {
+      "file": "TestApp-1.1.0.tar.xz",
+      "safeArtifactName": "TestApp-1.1.0.tar.xz",
+    },
+  ],
+}
 `;
diff --git a/test/out/linux/__snapshots__/linuxPackagerTest.js.snap b/test/out/linux/__snapshots__/linuxPackagerTest.js.snap
index 13debef6948..851864c36ae 100644
--- a/test/out/linux/__snapshots__/linuxPackagerTest.js.snap
+++ b/test/out/linux/__snapshots__/linuxPackagerTest.js.snap
@@ -14,21 +14,23 @@ Categories=Development;
 `;
 
 exports[`AppImage 1`] = `
-Array [
-  Object {
-    "file": "TestApp-1.1.0-x86_64.AppImage",
-    "safeArtifactName": undefined,
-  },
-]
+Object {
+  "linux": Array [
+    Object {
+      "file": "TestApp-1.1.0-x86_64.AppImage",
+    },
+  ],
+}
 `;
 
 exports[`icons from ICNS 1`] = `
-Array [
-  Object {
-    "file": "TestApp-1.1.0-x86_64.AppImage",
-    "safeArtifactName": undefined,
-  },
-]
+Object {
+  "linux": Array [
+    Object {
+      "file": "TestApp-1.1.0-x86_64.AppImage",
+    },
+  ],
+}
 `;
 
 exports[`no-author-email 1`] = `
diff --git a/test/out/linux/__snapshots__/snapTest.js.snap b/test/out/linux/__snapshots__/snapTest.js.snap
index 688962d4c70..bcd0f7cf328 100644
--- a/test/out/linux/__snapshots__/snapTest.js.snap
+++ b/test/out/linux/__snapshots__/snapTest.js.snap
@@ -256,10 +256,11 @@ Categories=Development;
 `;
 
 exports[`snap 1`] = `
-Array [
-  Object {
-    "file": "sep_1.1.0_amd64.snap",
-    "safeArtifactName": undefined,
-  },
-]
+Object {
+  "linux": Array [
+    Object {
+      "file": "sep_1.1.0_amd64.snap",
+    },
+  ],
+}
 `;
diff --git a/test/out/mac/__snapshots__/dmgTest.js.snap b/test/out/mac/__snapshots__/dmgTest.js.snap
index 0a410603bb8..a1f171e4702 100644
--- a/test/out/mac/__snapshots__/dmgTest.js.snap
+++ b/test/out/mac/__snapshots__/dmgTest.js.snap
@@ -16,21 +16,25 @@ Array [
 `;
 
 exports[`no background 1`] = `
-Array [
-  Object {
-    "file": "NoBackground-1.1.0.dmg",
-    "safeArtifactName": "TestApp-1.1.0.dmg",
-  },
-]
+Object {
+  "mac": Array [
+    Object {
+      "file": "NoBackground-1.1.0.dmg",
+      "safeArtifactName": "TestApp-1.1.0.dmg",
+    },
+  ],
+}
 `;
 
 exports[`no build directory 1`] = `undefined`;
 
 exports[`unset dmg icon 1`] = `
-Array [
-  Object {
-    "file": "Test ß No Volume Icon-1.1.0.dmg",
-    "safeArtifactName": "TestApp-1.1.0.dmg",
-  },
-]
+Object {
+  "mac": Array [
+    Object {
+      "file": "Test ß No Volume Icon-1.1.0.dmg",
+      "safeArtifactName": "TestApp-1.1.0.dmg",
+    },
+  ],
+}
 `;
diff --git a/test/out/mac/__snapshots__/macArchiveTest.js.snap b/test/out/mac/__snapshots__/macArchiveTest.js.snap
index f9bd66c5beb..51867f2a73b 100644
--- a/test/out/mac/__snapshots__/macArchiveTest.js.snap
+++ b/test/out/mac/__snapshots__/macArchiveTest.js.snap
@@ -5,18 +5,73 @@ exports[`invalid target 1`] = `
 {
   \\"mac\\": [
     {
-      \\"target[0]\\": \\"Should be equal to one of the allowed values\\",
-      \\"target\\": \\"Invalid option object\\"
+      \\"target\\": [
+        \\"Should be object\\",
+        \\"Should be equal to one of the allowed values\\",
+        \\"Should be string\\",
+        \\"Invalid option object\\"
+      ],
+      \\"target[0]\\": [
+        \\"Should be object\\",
+        \\"Should be equal to one of the allowed values\\",
+        \\"Invalid option object\\"
+      ]
     },
     \\"Invalid option object\\"
   ]
 }
 
 Raw validation errors: [
+  {
+    \\"keyword\\": \\"type\\",
+    \\"dataPath\\": \\".mac.target\\",
+    \\"schemaPath\\": \\"#/definitions/TargetConfig/type\\",
+    \\"params\\": {
+      \\"type\\": \\"object\\"
+    },
+    \\"message\\": \\"should be object\\"
+  },
+  {
+    \\"keyword\\": \\"type\\",
+    \\"dataPath\\": \\".mac.target[0]\\",
+    \\"schemaPath\\": \\"#/definitions/TargetConfig/type\\",
+    \\"params\\": {
+      \\"type\\": \\"object\\"
+    },
+    \\"message\\": \\"should be object\\"
+  },
   {
     \\"keyword\\": \\"enum\\",
     \\"dataPath\\": \\".mac.target[0]\\",
-    \\"schemaPath\\": \\"#/properties/target/anyOf/0/items/enum\\",
+    \\"schemaPath\\": \\"#/properties/target/anyOf/1/items/anyOf/1/enum\\",
+    \\"params\\": {
+      \\"allowedValues\\": [
+        \\"7z\\",
+        \\"default\\",
+        \\"dir\\",
+        \\"dmg\\",
+        \\"mas\\",
+        \\"pkg\\",
+        \\"tar.bz2\\",
+        \\"tar.gz\\",
+        \\"tar.lz\\",
+        \\"tar.xz\\",
+        \\"zip\\"
+      ]
+    },
+    \\"message\\": \\"should be equal to one of the allowed values\\"
+  },
+  {
+    \\"keyword\\": \\"anyOf\\",
+    \\"dataPath\\": \\".mac.target[0]\\",
+    \\"schemaPath\\": \\"#/properties/target/anyOf/1/items/anyOf\\",
+    \\"params\\": {},
+    \\"message\\": \\"should match some schema in anyOf\\"
+  },
+  {
+    \\"keyword\\": \\"enum\\",
+    \\"dataPath\\": \\".mac.target\\",
+    \\"schemaPath\\": \\"#/properties/target/anyOf/2/enum\\",
     \\"params\\": {
       \\"allowedValues\\": [
         \\"7z\\",
@@ -37,7 +92,16 @@ Raw validation errors: [
   {
     \\"keyword\\": \\"type\\",
     \\"dataPath\\": \\".mac.target\\",
-    \\"schemaPath\\": \\"#/properties/target/anyOf/1/type\\",
+    \\"schemaPath\\": \\"#/properties/target/anyOf/2/type\\",
+    \\"params\\": {
+      \\"type\\": \\"string\\"
+    },
+    \\"message\\": \\"should be string\\"
+  },
+  {
+    \\"keyword\\": \\"type\\",
+    \\"dataPath\\": \\".mac.target\\",
+    \\"schemaPath\\": \\"#/properties/target/anyOf/3/type\\",
     \\"params\\": {
       \\"type\\": \\"null\\"
     },
@@ -70,33 +134,39 @@ Raw validation errors: [
 `;
 
 exports[`only zip 1`] = `
-Array [
-  Object {
-    "file": "latest-mac.json",
-  },
-  Object {
-    "file": "Test App ßW-1.1.0-mac.zip",
-    "safeArtifactName": "TestApp-1.1.0-mac.zip",
-  },
-]
+Object {
+  "mac": Array [
+    Object {
+      "file": "latest-mac.json",
+    },
+    Object {
+      "file": "Test App ßW-1.1.0-mac.zip",
+      "safeArtifactName": "TestApp-1.1.0-mac.zip",
+    },
+  ],
+}
 `;
 
 exports[`pkg 1`] = `
-Array [
-  Object {
-    "file": "Test App ßW-1.1.0.pkg",
-    "safeArtifactName": "TestApp-1.1.0.pkg",
-  },
-]
+Object {
+  "mac": Array [
+    Object {
+      "file": "Test App ßW-1.1.0.pkg",
+      "safeArtifactName": "TestApp-1.1.0.pkg",
+    },
+  ],
+}
 `;
 
 exports[`pkg scripts 1`] = `
-Array [
-  Object {
-    "file": "Test App ßW-1.1.0.pkg",
-    "safeArtifactName": "TestApp-1.1.0.pkg",
-  },
-]
+Object {
+  "mac": Array [
+    Object {
+      "file": "Test App ßW-1.1.0.pkg",
+      "safeArtifactName": "TestApp-1.1.0.pkg",
+    },
+  ],
+}
 `;
 
 exports[`pkg scripts 2`] = `
@@ -490,10 +560,12 @@ Object {
 `;
 
 exports[`tar.gz 1`] = `
-Array [
-  Object {
-    "file": "Test App ßW-1.1.0-mac.tar.gz",
-    "safeArtifactName": "TestApp-1.1.0-mac.tar.gz",
-  },
-]
+Object {
+  "mac": Array [
+    Object {
+      "file": "Test App ßW-1.1.0-mac.tar.gz",
+      "safeArtifactName": "TestApp-1.1.0-mac.tar.gz",
+    },
+  ],
+}
 `;
diff --git a/test/out/mac/__snapshots__/macPackagerTest.js.snap b/test/out/mac/__snapshots__/macPackagerTest.js.snap
index 56102c1e790..f9c8c8b45de 100644
--- a/test/out/mac/__snapshots__/macPackagerTest.js.snap
+++ b/test/out/mac/__snapshots__/macPackagerTest.js.snap
@@ -3,19 +3,21 @@
 exports[`electronDist 1`] = `"ENOENT: no such file or directory, scandir '<path>/Electron.app'"`;
 
 exports[`one-package 1`] = `
-Array [
-  Object {
-    "file": "latest-mac.json",
-  },
-  Object {
-    "file": "Test App ßW-1.1.0.dmg",
-    "safeArtifactName": "TestApp-1.1.0.dmg",
-  },
-  Object {
-    "file": "Test App ßW-1.1.0-mac.zip",
-    "safeArtifactName": "TestApp-1.1.0-mac.zip",
-  },
-]
+Object {
+  "mac": Array [
+    Object {
+      "file": "Test App ßW-1.1.0.dmg",
+      "safeArtifactName": "TestApp-1.1.0.dmg",
+    },
+    Object {
+      "file": "latest-mac.json",
+    },
+    Object {
+      "file": "Test App ßW-1.1.0-mac.zip",
+      "safeArtifactName": "TestApp-1.1.0-mac.zip",
+    },
+  ],
+}
 `;
 
 exports[`one-package 2`] = `
@@ -79,17 +81,19 @@ Object {
 `;
 
 exports[`two-package 1`] = `
-Array [
-  Object {
-    "file": "latest-mac.json",
-  },
-  Object {
-    "file": "TestApp-1.1.0.dmg",
-    "safeArtifactName": "TestApp-1.1.0.dmg",
-  },
-  Object {
-    "file": "TestApp-1.1.0-mac.zip",
-    "safeArtifactName": "TestApp-1.1.0-mac.zip",
-  },
-]
+Object {
+  "mac": Array [
+    Object {
+      "file": "TestApp-1.1.0.dmg",
+      "safeArtifactName": "TestApp-1.1.0.dmg",
+    },
+    Object {
+      "file": "latest-mac.json",
+    },
+    Object {
+      "file": "TestApp-1.1.0-mac.zip",
+      "safeArtifactName": "TestApp-1.1.0-mac.zip",
+    },
+  ],
+}
 `;
diff --git a/test/out/mac/__snapshots__/masTest.js.snap b/test/out/mac/__snapshots__/masTest.js.snap
index c93b78b2922..6f5e6b8b47d 100644
--- a/test/out/mac/__snapshots__/masTest.js.snap
+++ b/test/out/mac/__snapshots__/masTest.js.snap
@@ -1,23 +1,27 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`mas 1`] = `
-Array [
-  Object {
-    "file": "Test App ßW-1.1.0.pkg",
-    "safeArtifactName": "TestApp-1.1.0.pkg",
-  },
-]
+Object {
+  "mac": Array [
+    Object {
+      "file": "Test App ßW-1.1.0.pkg",
+      "safeArtifactName": "TestApp-1.1.0.pkg",
+    },
+  ],
+}
 `;
 
 exports[`mas and 7z 1`] = `
-Array [
-  Object {
-    "file": "Test App ßW-1.1.0.pkg",
-    "safeArtifactName": "TestApp-1.1.0.pkg",
-  },
-  Object {
-    "file": "Test App ßW-1.1.0-mac.7z",
-    "safeArtifactName": "TestApp-1.1.0-mac.7z",
-  },
-]
+Object {
+  "mac": Array [
+    Object {
+      "file": "Test App ßW-1.1.0-mac.7z",
+      "safeArtifactName": "TestApp-1.1.0-mac.7z",
+    },
+    Object {
+      "file": "Test App ßW-1.1.0.pkg",
+      "safeArtifactName": "TestApp-1.1.0.pkg",
+    },
+  ],
+}
 `;
diff --git a/test/out/windows/__snapshots__/installerTest.js.snap b/test/out/windows/__snapshots__/installerTest.js.snap
index b8b84b8eeab..28c9a43055e 100644
--- a/test/out/windows/__snapshots__/installerTest.js.snap
+++ b/test/out/windows/__snapshots__/installerTest.js.snap
@@ -1,12 +1,14 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`allowToChangeInstallationDirectory 1`] = `
-Array [
-  Object {
-    "file": "Test Custom Installation Dir Setup 1.1.0.exe",
-    "safeArtifactName": "test-custom-inst-dir-Setup-1.1.0.exe",
-  },
-]
+Object {
+  "win": Array [
+    Object {
+      "file": "Test Custom Installation Dir Setup 1.1.0.exe",
+      "safeArtifactName": "test-custom-inst-dir-Setup-1.1.0.exe",
+    },
+  ],
+}
 `;
 
 exports[`allowToChangeInstallationDirectory 2`] = `
@@ -26,28 +28,34 @@ Object {
 `;
 
 exports[`boring 1`] = `
-Array [
-  Object {
-    "file": "Test App ßW Setup 1.1.0.exe",
-    "safeArtifactName": "TestApp-Setup-1.1.0.exe",
-  },
-]
+Object {
+  "win": Array [
+    Object {
+      "file": "Test App ßW Setup 1.1.0.exe",
+      "safeArtifactName": "TestApp-Setup-1.1.0.exe",
+    },
+  ],
+}
 `;
 
 exports[`boring, only perMachine 1`] = `
-Array [
-  Object {
-    "file": "Test App ßW Setup 1.1.0.exe",
-    "safeArtifactName": "TestApp-Setup-1.1.0.exe",
-  },
-]
+Object {
+  "win": Array [
+    Object {
+      "file": "Test App ßW Setup 1.1.0.exe",
+      "safeArtifactName": "TestApp-Setup-1.1.0.exe",
+    },
+  ],
+}
 `;
 
 exports[`portable 1`] = `
-Array [
-  Object {
-    "file": "Test App ßW 1.1.0.exe",
-    "safeArtifactName": "TestApp-1.1.0.exe",
-  },
-]
+Object {
+  "win": Array [
+    Object {
+      "file": "Test App ßW 1.1.0.exe",
+      "safeArtifactName": "TestApp-1.1.0.exe",
+    },
+  ],
+}
 `;
diff --git a/test/out/windows/__snapshots__/oneClickInstallerTest.js.snap b/test/out/windows/__snapshots__/oneClickInstallerTest.js.snap
index d07818f5829..c7eb90d172d 100644
--- a/test/out/windows/__snapshots__/oneClickInstallerTest.js.snap
+++ b/test/out/windows/__snapshots__/oneClickInstallerTest.js.snap
@@ -1,41 +1,49 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`custom include 1`] = `
-Array [
-  Object {
-    "file": "Test App ßW Setup 1.1.0.exe",
-    "safeArtifactName": "TestApp-Setup-1.1.0.exe",
-  },
-]
+Object {
+  "win": Array [
+    Object {
+      "file": "Test App ßW Setup 1.1.0.exe",
+      "safeArtifactName": "TestApp-Setup-1.1.0.exe",
+    },
+  ],
+}
 `;
 
 exports[`custom script 1`] = `
-Array [
-  Object {
-    "file": "Test App ßW Setup 1.1.0.exe",
-    "safeArtifactName": "TestApp-Setup-1.1.0.exe",
-  },
-]
+Object {
+  "win": Array [
+    Object {
+      "file": "Test App ßW Setup 1.1.0.exe",
+      "safeArtifactName": "TestApp-Setup-1.1.0.exe",
+    },
+  ],
+}
 `;
 
 exports[`file associations only perMachine 1`] = `"Please set perMachine to true — file associations works on Windows only if installed for all users"`;
 
 exports[`menuCategory 1`] = `
-Array [
-  Object {
-    "file": "Test Menu Category CustomName 1.1.0.exe",
-    "safeArtifactName": "test-menu-category-Setup-1.1.0.exe",
-  },
-]
+Object {
+  "win": Array [
+    Object {
+      "file": "Test Menu Category CustomName 1.1.0.exe",
+      "safeArtifactName": "test-menu-category-Setup-1.1.0.exe",
+    },
+  ],
+}
 `;
 
 exports[`one-click 1`] = `
-Array [
-  Object {
-    "file": "Test App ßW Setup 1.1.0.exe",
-    "safeArtifactName": "TestApp-Setup-1.1.0.exe",
-  },
-]
+Object {
+  "win": Array [
+    Object {
+      "file": "Test App ßW Setup 1.1.0.exe",
+      "safeArtifactName": "TestApp-Setup-1.1.0.exe",
+    },
+  ],
+}
 `;
 
 exports[`one-click 2`] = `
@@ -47,15 +55,17 @@ Object {
 `;
 
 exports[`perMachine, no run after finish 1`] = `
-Array [
-  Object {
-    "file": "latest.yml",
-  },
-  Object {
-    "file": "TestApp Setup 1.1.0.exe",
-    "safeArtifactName": "TestApp-Setup-1.1.0.exe",
-  },
-]
+Object {
+  "win": Array [
+    Object {
+      "file": "latest.yml",
+    },
+    Object {
+      "file": "TestApp Setup 1.1.0.exe",
+      "safeArtifactName": "TestApp-Setup-1.1.0.exe",
+    },
+  ],
+}
 `;
 
 exports[`perMachine, no run after finish 2`] = `
@@ -74,40 +84,23 @@ Object {
 `;
 
 exports[`web installer (default github) 1`] = `
-Array [
-  Object {
-    "file": "TestApp-1.1.0-ia32.nsis.7z",
-    "safeArtifactName": undefined,
-  },
-  Object {
-    "file": "TestApp-1.1.0-x64.nsis.7z",
-    "safeArtifactName": undefined,
-  },
-  Object {
-    "file": "Test App ßW Web Setup 1.1.0.exe",
-    "safeArtifactName": "TestApp-WebSetup-1.1.0.exe",
-  },
-]
+Object {
+  "win": Array [
+    Object {
+      "file": "Test App ßW Web Setup 1.1.0.exe",
+      "safeArtifactName": "TestApp-WebSetup-1.1.0.exe",
+    },
+    Object {
+      "file": "TestApp-1.1.0-ia32.nsis.7z",
+    },
+    Object {
+      "file": "TestApp-1.1.0-x64.nsis.7z",
+    },
+  ],
+}
 `;
 
 exports[`web installer (default github) 2`] = `
-Array [
-  Object {
-    "file": "TestApp-1.1.0-ia32.nsis.7z",
-    "safeArtifactName": undefined,
-  },
-  Object {
-    "file": "TestApp-1.1.0-x64.nsis.7z",
-    "safeArtifactName": undefined,
-  },
-  Object {
-    "file": "Test App ßW Web Setup 1.1.0.exe",
-    "safeArtifactName": "TestApp-WebSetup-1.1.0.exe",
-  },
-]
-`;
-
-exports[`web installer (default github) 3`] = `
 Object {
   "githubArtifactName": "TestApp-WebSetup-1.1.0.exe",
   "path": "Test App ßW Web Setup 1.1.0.exe",
@@ -116,17 +109,18 @@ Object {
 `;
 
 exports[`web installer 1`] = `
-Array [
-  Object {
-    "file": "latest.yml",
-  },
-  Object {
-    "file": "TestApp-1.1.0-x64.nsis.7z",
-    "safeArtifactName": undefined,
-  },
-  Object {
-    "file": "Test App ßW Web Setup 1.1.0.exe",
-    "safeArtifactName": "TestApp-WebSetup-1.1.0.exe",
-  },
-]
+Object {
+  "win": Array [
+    Object {
+      "file": "latest.yml",
+    },
+    Object {
+      "file": "Test App ßW Web Setup 1.1.0.exe",
+      "safeArtifactName": "TestApp-WebSetup-1.1.0.exe",
+    },
+    Object {
+      "file": "TestApp-1.1.0-x64.nsis.7z",
+    },
+  ],
+}
 `;
diff --git a/test/out/windows/__snapshots__/squirrelWindowsTest.js.snap b/test/out/windows/__snapshots__/squirrelWindowsTest.js.snap
index 27cda917aeb..9484704a796 100644
--- a/test/out/windows/__snapshots__/squirrelWindowsTest.js.snap
+++ b/test/out/windows/__snapshots__/squirrelWindowsTest.js.snap
@@ -1,22 +1,22 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`Squirrel.Windows 1`] = `
-Array [
-  Object {
-    "file": "Test App ßW Setup 1.1.0.exe",
-    "safeArtifactName": "TestApp-Setup-1.1.0.exe",
-  },
-  Object {
-    "file": "TestApp-1.1.0-full.nupkg",
-    "safeArtifactName": undefined,
-  },
-  Object {
-    "file": "RELEASES",
-    "safeArtifactName": undefined,
-  },
-  Object {
-    "file": "Test App ßW-1.1.0-win.zip",
-    "safeArtifactName": "TestApp-1.1.0-win.zip",
-  },
-]
+Object {
+  "win": Array [
+    Object {
+      "file": "RELEASES",
+    },
+    Object {
+      "file": "Test App ßW Setup 1.1.0.exe",
+      "safeArtifactName": "TestApp-Setup-1.1.0.exe",
+    },
+    Object {
+      "file": "TestApp-1.1.0-full.nupkg",
+    },
+    Object {
+      "file": "Test App ßW-1.1.0-win.zip",
+      "safeArtifactName": "TestApp-1.1.0-win.zip",
+    },
+  ],
+}
 `;
diff --git a/test/src/BuildTest.ts b/test/src/BuildTest.ts
index 193439d0b2a..69c41093968 100644
--- a/test/src/BuildTest.ts
+++ b/test/src/BuildTest.ts
@@ -1,14 +1,13 @@
 import BluebirdPromise from "bluebird-lst"
-import { Arch, BuildOptions, DIR_TARGET, Platform } from "electron-builder"
+import { Arch, BuildOptions, createTargets, DIR_TARGET, Platform } from "electron-builder"
 import { readAsarJson } from "electron-builder/out/asar"
 import { normalizeOptions } from "electron-builder/out/builder"
 import { createYargs } from "electron-builder/out/cli/cliOptions"
 import { checkWineVersion } from "electron-builder/out/packager"
 import { move, outputJson } from "fs-extra-p"
-import isCi from "is-ci"
 import * as path from "path"
 import { ELECTRON_VERSION } from "./helpers/config"
-import { allPlatforms, app, appTwo, appTwoThrows, assertPack, getPossiblePlatforms, modifyPackageJson, packageJson } from "./helpers/packTester"
+import { app, appTwo, appTwoThrows, assertPack, modifyPackageJson, packageJson } from "./helpers/packTester"
 
 const linuxDirTarget = Platform.LINUX.createTarget(DIR_TARGET)
 
@@ -35,7 +34,7 @@ test("cli", async () => {
 
   expect(parse("--dir")).toMatchObject(expected({targets: Platform.current().createTarget(DIR_TARGET)}))
   expect(parse("--mac --dir")).toMatchSnapshot()
-  expect(parse("--ia32 --dir")).toMatchObject(expected({targets: Platform.current().createTarget(DIR_TARGET, Arch.ia32)}))
+  expect(parse("--x64 --dir")).toMatchObject(expected({targets: Platform.current().createTarget(DIR_TARGET, Arch.x64)}))
   expect(parse("--platform linux --dir")).toMatchSnapshot()
 
   expect(parse("--arch x64")).toMatchObject(expected({targets: Platform.current().createTarget(null, Arch.x64)}))
@@ -65,7 +64,9 @@ test("build in the app package.json", appTwoThrows(linuxDirTarget, {
   }, true)
 }))
 
-test("relative index", appTwo(allPlatforms(false), {
+test("relative index", appTwo({
+  targets: linuxDirTarget,
+}, {
   projectDirCreated: projectDir => modifyPackageJson(projectDir, data => {
     data.main = "./index.js"
   }, true)
@@ -109,16 +110,15 @@ test.ifDevOrLinuxCi("electron version from build", app({
 }))
 
 test("www as default dir", appTwo({
-  targets: Platform.current().createTarget(DIR_TARGET),
+  targets: Platform.LINUX.createTarget(DIR_TARGET),
 }, {
   projectDirCreated: projectDir => move(path.join(projectDir, "app"), path.join(projectDir, "www"))
 }))
 
-test("afterPack", () => {
-  const targets = isCi ? Platform.current().createTarget(DIR_TARGET) : getPossiblePlatforms(DIR_TARGET)
+test.ifLinuxOrDevMac("afterPack", () => {
   let called = 0
   return assertPack("test-app-one", {
-    targets: targets,
+    targets: createTargets([Platform.LINUX, Platform.MAC], DIR_TARGET),
     config: {
       afterPack: () => {
         called++
@@ -127,26 +127,24 @@ test("afterPack", () => {
     }
   }, {
     packed: async () => {
-      expect(called).toEqual(targets.size)
+      expect(called).toEqual(2)
     }
   })
 })
 
-test("beforeBuild", () => {
-  const targets = isCi ? Platform.current().createTarget(DIR_TARGET) : getPossiblePlatforms(DIR_TARGET)
+test.ifLinuxOrDevMac("beforeBuild", () => {
   let called = 0
   return assertPack("test-app-one", {
-    targets: targets,
+    targets: createTargets([Platform.LINUX, Platform.MAC], DIR_TARGET),
     config: {
       npmRebuild: true,
-      beforeBuild: () => {
+      beforeBuild: async () => {
         called++
-        return BluebirdPromise.resolve()
       }
     }
   }, {
     packed: async () => {
-      expect(called).toEqual(targets.size)
+      expect(called).toEqual(2)
     }
   })
 })
diff --git a/test/src/ExtraBuildTest.ts b/test/src/ExtraBuildTest.ts
index bf2c7d62022..692b3c3f053 100644
--- a/test/src/ExtraBuildTest.ts
+++ b/test/src/ExtraBuildTest.ts
@@ -1,5 +1,5 @@
 import { DIR_TARGET, Platform } from "electron-builder"
-import { build, normalizeOptions } from "electron-builder/out/builder"
+import { build } from "electron-builder/out/builder"
 import { move } from "fs-extra-p"
 import * as path from "path"
 import { assertThat } from "./helpers/fileAssert"
@@ -31,19 +31,26 @@ test.ifAll.ifNotWindows("custom buildResources and output dirs: mac", createBuil
 test.ifAll.ifNotCiMac("custom buildResources and output dirs: win", createBuildResourcesTest(Platform.WINDOWS))
 test.ifAll.ifNotWindows("custom buildResources and output dirs: linux", createBuildResourcesTest(Platform.LINUX))
 
-test.ifAll.ifDevOrLinuxCi("prepackaged", app({
+test.ifAll.ifLinuxOrDevMac("prepackaged", app({
   targets: linuxDirTarget,
 }, {
   packed: async (context) => {
-    await build(normalizeOptions({
+    await build({
       prepackaged: path.join(context.outDir, "linux-unpacked"),
       project: context.projectDir,
-      linux: ["deb"],
+      linux: [],
       config: {
+        // test target
+        linux: {
+          target: {
+            target: "deb",
+            arch: "ia32",
+          }
+        },
         compression: "store"
       }
-    }))
-    await assertThat(path.join(context.projectDir, "dist", "TestApp_1.1.0_amd64.deb")).isFile()
+    })
+    await assertThat(path.join(context.projectDir, "dist", "TestApp_1.1.0_i386.deb")).isFile()
   }
 }))
 
@@ -66,8 +73,11 @@ test.ifAll.ifDevOrLinuxCi("scheme validation 2", appThrows({
 
 // https://github.com/electron-userland/electron-builder/issues/1302
 test.ifAll.ifDevOrLinuxCi("scheme validation extraFiles", app({
-  targets: linuxDirTarget,
-  config: <any>{
+  targets: Platform.LINUX.createTarget([]),
+  config: {
+    linux: {
+      target: "zip:ia32",
+    },
     "extraFiles": [
       "lib/*.jar",
       "lib/Proguard/**/*",
diff --git a/test/src/helpers/packTester.ts b/test/src/helpers/packTester.ts
index ce5d8ba0917..72370405767 100755
--- a/test/src/helpers/packTester.ts
+++ b/test/src/helpers/packTester.ts
@@ -1,12 +1,12 @@
 import DecompressZip from "decompress-zip"
-import { Arch, ArtifactCreated, Config, createTargets, DIR_TARGET, getArchSuffix, MacOsTargetName, Packager, PackagerOptions, Platform, Target } from "electron-builder"
+import { Arch, ArtifactCreated, DIR_TARGET, getArchSuffix, MacOsTargetName, Packager, PackagerOptions, Platform, Target } from "electron-builder"
 import { CancellationToken } from "electron-builder-http/out/CancellationToken"
 import { convertVersion } from "electron-builder-squirrel-windows/out/squirrelPack"
-import { exec, getTempName, spawn } from "electron-builder-util"
-import { deepAssign } from "electron-builder-util/out/deepAssign"
+import { addValue, exec, getTempName, spawn } from "electron-builder-util"
 import { copyDir, FileCopier } from "electron-builder-util/out/fs"
 import { log, warn } from "electron-builder-util/out/log"
 import { PublishManager } from "electron-builder/out/publish/PublishManager"
+import { computeArchToTargetNamesMap } from "electron-builder/out/targets/targetFactory"
 import { emptyDir, mkdir, readFile, readJson, remove, writeJson } from "fs-extra-p"
 import * as path from "path"
 import pathSorter from "path-sort"
@@ -76,28 +76,24 @@ export async function assertPack(fixtureName: string, packagerOptions: PackagerO
   }
 
   const projectDirCreated = checkOptions.projectDirCreated
-  const useTempDir = process.env.TEST_APP_TMP_DIR != null || (checkOptions.useTempDir !== false && (checkOptions.useTempDir || projectDirCreated != null || packagerOptions.config != null || checkOptions.npmInstallBefore))
-
   let projectDir = path.join(__dirname, "..", "..", "fixtures", fixtureName)
   // const isDoNotUseTempDir = platform === "darwin"
   const customTmpDir = process.env.TEST_APP_TMP_DIR
   let dirToDelete: string | null = null
-  if (useTempDir) {
-    // non-macOS test uses the same dir as macOS test, but we cannot share node_modules (because tests executed in parallel)
-    const dir = customTmpDir == null ? getTempFile() : path.resolve(customTmpDir)
-    if (customTmpDir == null) {
-      dirToDelete = dir
-    }
-    else {
-      log(`Custom temp dir used: ${customTmpDir}`)
-    }
-    await emptyDir(dir)
-    await copyDir(projectDir, dir, it => {
-      const basename = path.basename(it)
-      return basename !== OUT_DIR_NAME && basename !== "node_modules" && !basename.startsWith(".")
-    }, it => path.basename(it) != "package.json")
-    projectDir = dir
+  // non-macOS test uses the same dir as macOS test, but we cannot share node_modules (because tests executed in parallel)
+  const dir = customTmpDir == null ? getTempFile() : path.resolve(customTmpDir)
+  if (customTmpDir == null) {
+    dirToDelete = dir
   }
+  else {
+    log(`Custom temp dir used: ${customTmpDir}`)
+  }
+  await emptyDir(dir)
+  await copyDir(projectDir, dir, it => {
+    const basename = path.basename(it)
+    return basename !== OUT_DIR_NAME && basename !== "node_modules" && !basename.startsWith(".")
+  }, it => path.basename(it) != "package.json")
+  projectDir = dir
 
   try {
     if (projectDirCreated != null) {
@@ -109,18 +105,7 @@ export async function assertPack(fixtureName: string, packagerOptions: PackagerO
       }
     }
 
-    // never output to test fixture app
-    if (!useTempDir) {
-      dirToDelete = path.join(testDir, `${(tmpDirCounter++).toString(16)}`)
-      const config = <Config>packagerOptions.config
-      if (config != null && config.directories != null) {
-        throw new Error("unsupported")
-      }
-      packagerOptions = deepAssign({}, packagerOptions, {config: {directories: {output: dirToDelete}}})
-    }
-
-    const outDir = useTempDir ? path.join(projectDir, OUT_DIR_NAME) : dirToDelete
-    const packager = await packAndCheck(outDir, Object.assign({
+    const {packager, outDir} = await packAndCheck(Object.assign({
       projectDir: projectDir,
     }, packagerOptions), checkOptions)
 
@@ -160,7 +145,7 @@ export function getFixtureDir() {
   return path.join(__dirname, "..", "..", "fixtures")
 }
 
-async function packAndCheck(outDir: string, packagerOptions: PackagerOptions, checkOptions: AssertPackOptions): Promise<Packager> {
+async function packAndCheck(packagerOptions: PackagerOptions, checkOptions: AssertPackOptions) {
   const cancellationToken = new CancellationToken()
   const packager = new Packager(packagerOptions, cancellationToken)
   const publishManager = new PublishManager(packager, {publish: "never"}, cancellationToken)
@@ -172,46 +157,52 @@ async function packAndCheck(outDir: string, packagerOptions: PackagerOptions, ch
     }
 
     assertThat(event.file).isAbsolute()
-    let list = artifacts.get(event.packager.platform)
-    if (list == null) {
-      list = []
-      artifacts.set(event.packager.platform, list)
-    }
-    list.push(event)
+    addValue(artifacts, event.packager.platform, event)
   })
 
-  const platformToTarget = await packager.build()
+  const {outDir, platformToTargets} = await packager.build()
   await publishManager.awaitTasks()
 
   if (packagerOptions.platformPackagerFactory != null || packagerOptions.effectiveOptionComputed != null) {
-    return packager
+    return {packager, outDir}
+  }
+
+  function sortKey(a: ArtifactCreated) {
+    return `${a.target == null ? "no-target" : a.target.name}:${a.file == null ? a.data.toString("hex") : path.basename(a.file)}`
   }
 
+  const objectToCompare: any = {}
+  for (const platform of packagerOptions.targets.keys()) {
+    objectToCompare[platform.buildConfigurationKey] = (artifacts.get(platform) || [])
+      .sort((a, b) => sortKey(a).localeCompare(sortKey(b)))
+      .map(it => {
+        const result: any = Object.assign({}, it)
+        if (result.file != null) {
+          result.file = path.basename(result.file)
+        }
+
+        // reduce snapshot - avoid noise
+        if (result.safeArtifactName == null) {
+          delete result.safeArtifactName
+        }
+
+        delete result.packager
+        delete result.target
+        delete result.publishConfig
+        return result
+      })
+  }
+
+  expect(objectToCompare).toMatchSnapshot()
+
   c: for (const [platform, archToType] of packagerOptions.targets) {
-    for (const [arch, targets] of archToType) {
+    for (const [arch, targets] of computeArchToTargetNamesMap(archToType, (<any>packagerOptions)[platform.buildConfigurationKey] || {}, platform)) {
       if (targets.length === 1 && targets[0] === DIR_TARGET) {
         continue c
       }
 
-      const nameToTarget = platformToTarget.get(platform)
-      const platformArtifacts = artifacts.get(platform)
-
-      const emptyTarget = {name: ""}
-      expect(platformArtifacts
-        .sort((a, b) => (a.target || emptyTarget).name.localeCompare((b.target || emptyTarget).name))
-        .map(it => {
-          const result: any = Object.assign({}, it)
-          if (result.file != null) {
-            result.file = path.basename(result.file)
-          }
-          delete result.packager
-          delete result.target
-          delete result.publishConfig
-          return result
-        })).toMatchSnapshot()
-
+      const nameToTarget = platformToTargets.get(platform)
       if (platform === Platform.MAC) {
-        const outDir = path.resolve(packager.projectDir, path.join((packager.config.directories == null ? null : packager.config.directories!.output) || "dist"))
         const packedAppDir = path.join(outDir, nameToTarget.has("mas") ? "mas" : "mac", `${packager.appInfo.productFilename}.app`)
         await checkMacResult(packager, packagerOptions, checkOptions, packedAppDir)
       }
@@ -219,12 +210,12 @@ async function packAndCheck(outDir: string, packagerOptions: PackagerOptions, ch
         await checkLinuxResult(outDir, packager, checkOptions, arch, nameToTarget)
       }
       else if (platform === Platform.WINDOWS) {
-        await checkWindowsResult(packager, checkOptions, platformArtifacts, nameToTarget)
+        await checkWindowsResult(packager, checkOptions, artifacts.get(platform), nameToTarget)
       }
     }
   }
 
-  return packager
+  return {packager, outDir}
 }
 
 async function checkLinuxResult(outDir: string, packager: Packager, checkOptions: AssertPackOptions, arch: Arch, nameToTarget: Map<String, Target>) {
@@ -413,18 +404,6 @@ export function signed(packagerOptions: PackagerOptions): PackagerOptions {
   return packagerOptions
 }
 
-export function getPossiblePlatforms(type?: string): Map<Platform, Map<Arch, string[]>> {
-  const platforms = [Platform.fromString(process.platform)]
-  if (process.platform === Platform.MAC.nodeName) {
-    platforms.push(Platform.LINUX)
-    platforms.push(Platform.WINDOWS)
-  }
-  else if (process.platform === Platform.LINUX.nodeName) {
-    platforms.push(Platform.WINDOWS)
-  }
-  return createTargets(platforms, type)
-}
-
 export function createMacTargetTest(target: Array<MacOsTargetName>) {
   return app({
     targets: Platform.MAC.createTarget(),
@@ -437,7 +416,6 @@ export function createMacTargetTest(target: Array<MacOsTargetName>) {
       }
     }
   }, {
-    useTempDir: true,
     signed: target.includes("mas") || target.includes("pkg"),
     packed: async (context) => {
       if (!target.includes("tar.gz")) {
@@ -452,12 +430,6 @@ export function createMacTargetTest(target: Array<MacOsTargetName>) {
   })
 }
 
-export function allPlatforms(dist = true): PackagerOptions {
-  return {
-    targets: getPossiblePlatforms(dist ? null : DIR_TARGET),
-  }
-}
-
 export function convertUpdateInfo(info: any) {
   if (info.releaseDate != null) {
     info.releaseDate = "1970-01-01T00:00:00.000Z"
diff --git a/test/src/helpers/runTests.ts b/test/src/helpers/runTests.ts
index 95368952371..6959badb4ba 100755
--- a/test/src/helpers/runTests.ts
+++ b/test/src/helpers/runTests.ts
@@ -176,4 +176,4 @@ async function runTests() {
       return process.exit(code)
     })
   })
-}
+}
\ No newline at end of file
diff --git a/test/src/linux/linuxPackagerTest.ts b/test/src/linux/linuxPackagerTest.ts
index e3316c91df6..78de4e8ef90 100755
--- a/test/src/linux/linuxPackagerTest.ts
+++ b/test/src/linux/linuxPackagerTest.ts
@@ -32,7 +32,9 @@ test.ifDevOrLinuxCi("AppImage - default icon, custom executable and custom deskt
 }))
 
 // test prepacked asar also https://github.com/electron-userland/electron-builder/issues/1102
-test.ifNotWindows("icons from ICNS", app({targets: Platform.LINUX.createTarget()}, {
+test.ifNotWindows("icons from ICNS", app({
+  targets: Platform.LINUX.createTarget()
+}, {
   projectDirCreated: it => remove(path.join(it, "build", "icons")),
   packed: async context => {
     const projectDir = context.getResources(Platform.LINUX)
diff --git a/test/src/mac/macArchiveTest.ts b/test/src/mac/macArchiveTest.ts
index ed1d4195374..5d13c6b446d 100644
--- a/test/src/mac/macArchiveTest.ts
+++ b/test/src/mac/macArchiveTest.ts
@@ -20,7 +20,6 @@ it("pkg", createMacTargetTest(["pkg"]))
 test.ifMac("pkg scripts", app({
   targets: Platform.MAC.createTarget("pkg"),
 }, {
-  useTempDir: true,
   signed: false,
   projectDirCreated: async (projectDir) => {
     await symlink(path.join(getFixtureDir(), "pkg-scripts"), path.join(projectDir, "build", "pkg-scripts"))
diff --git a/test/src/mac/macPackagerTest.ts b/test/src/mac/macPackagerTest.ts
index 3bd514d3f8b..7dd2ea918f0 100644
--- a/test/src/mac/macPackagerTest.ts
+++ b/test/src/mac/macPackagerTest.ts
@@ -1,7 +1,6 @@
 import BluebirdPromise from "bluebird-lst"
-import { createTargets, Platform } from "electron-builder"
+import { createTargets, DIR_TARGET, Platform } from "electron-builder"
 import { copyFile } from "electron-builder-util/out/fs"
-import { DIR_TARGET } from "electron-builder/out/targets/targetFactory"
 import { readJson } from "fs-extra-p"
 import * as path from "path"
 import { assertThat } from "../helpers/fileAssert"
@@ -14,7 +13,6 @@ test.ifMac("two-package", () => assertPack("test-app", {
   },
 }, {
   signed: true,
-  useTempDir: true,
 }))
 
 test.ifMac("one-package", app({
diff --git a/test/src/mainEntryTest.ts b/test/src/mainEntryTest.ts
index 1eece9923db..45213389433 100644
--- a/test/src/mainEntryTest.ts
+++ b/test/src/mainEntryTest.ts
@@ -1,15 +1,20 @@
 import BluebirdPromise from "bluebird-lst"
+import { createTargets, DIR_TARGET, Platform } from "electron-builder"
 import { move } from "fs-extra-p"
 import * as path from "path"
-import { allPlatforms, appTwoThrows, assertPack, modifyPackageJson } from "./helpers/packTester"
+import { appTwoThrows, assertPack, modifyPackageJson } from "./helpers/packTester"
 
-test("invalid main in the app package.json", appTwoThrows(allPlatforms(false), {
+const packagerOptions = {
+  targets: createTargets([Platform.LINUX, Platform.MAC], DIR_TARGET)
+}
+
+test.ifLinuxOrDevMac("invalid main in the app package.json", appTwoThrows(packagerOptions, {
   projectDirCreated: projectDir => modifyPackageJson(projectDir, data => {
     data.main = "main.js"
   }, true)
 }))
 
-test("invalid main in the app package.json (no asar)", appTwoThrows(allPlatforms(false), {
+test.ifLinuxOrDevMac("invalid main in the app package.json (no asar)", appTwoThrows(packagerOptions, {
   projectDirCreated: projectDir => {
     return BluebirdPromise.all([
       modifyPackageJson(projectDir, data => {
@@ -22,7 +27,7 @@ test("invalid main in the app package.json (no asar)", appTwoThrows(allPlatforms
   }
 }))
 
-test("invalid main in the app package.json (custom asar)", appTwoThrows(allPlatforms(false), {
+test.ifLinuxOrDevMac("invalid main in the app package.json (custom asar)", appTwoThrows(packagerOptions, {
   projectDirCreated: projectDir => {
     return BluebirdPromise.all([
       modifyPackageJson(projectDir, data => {
@@ -35,7 +40,7 @@ test("invalid main in the app package.json (custom asar)", appTwoThrows(allPlatf
   }
 }))
 
-test("main in the app package.json (no asar)", () => assertPack("test-app", allPlatforms(false), {
+test.ifLinuxOrDevMac("main in the app package.json (no asar)", () => assertPack("test-app", packagerOptions, {
   projectDirCreated: projectDir => {
     return BluebirdPromise.all([
       move(path.join(projectDir, "app", "index.js"), path.join(projectDir, "app", "main.js")),
@@ -49,7 +54,7 @@ test("main in the app package.json (no asar)", () => assertPack("test-app", allP
   }
 }))
 
-test("main in the app package.json (custom asar)", () => assertPack("test-app", allPlatforms(false), {
+test.ifLinuxOrDevMac("main in the app package.json (custom asar)", () => assertPack("test-app", packagerOptions, {
   projectDirCreated: projectDir => {
     return BluebirdPromise.all([
       modifyPackageJson(projectDir, data => {
diff --git a/test/src/windows/oneClickInstallerTest.ts b/test/src/windows/oneClickInstallerTest.ts
index c6069724d8c..82f8a80244e 100644
--- a/test/src/windows/oneClickInstallerTest.ts
+++ b/test/src/windows/oneClickInstallerTest.ts
@@ -23,7 +23,6 @@ test("one-click", app({
     },
   }
 }, {
-  useTempDir: true,
   signed: true,
   packed: async (context) => {
     await doTest(context.outDir, true)
diff --git a/yarn.lock b/yarn.lock
index 3e3329657b7..7fa03532e65 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -22,10 +22,6 @@
     "7zip-bin-mac" "^1.0.1"
     "7zip-bin-win" "^2.0.2"
 
-"@types/doctrine@^0.0.3":
-  version "0.0.3"
-  resolved "https://registry.yarnpkg.com/@types/doctrine/-/doctrine-0.0.3.tgz#e892d293c92c9c1d3f9af72c15a554fbc7e0895a"
-
 "@types/electron@^1.4.33":
   version "1.4.33"
   resolved "https://registry.yarnpkg.com/@types/electron/-/electron-1.4.33.tgz#10b82bb065115e19a5ef0848e142cf5949435979"
@@ -44,9 +40,9 @@
   version "3.5.29"
   resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.5.29.tgz#29f4dd9314fbccb080d8bd84b9c23811ec5090c2"
 
-"@types/node-forge@^0.6.5":
-  version "0.6.5"
-  resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-0.6.5.tgz#4ed3ea29b20ccca4e7cd778de0e039b01ddb3239"
+"@types/node-forge@^0.6.6":
+  version "0.6.6"
+  resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-0.6.6.tgz#e9707d36cc4b50bd7147b9747323d461a1089613"
 
 "@types/node@*":
   version "7.0.5"
@@ -240,9 +236,9 @@ asynckit@^0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
 
-aws-sdk@^2.22.0:
-  version "2.22.0"
-  resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.22.0.tgz#f7b67d5ece7e67c36f9d3d55e137872572e5c998"
+aws-sdk@^2.24.0:
+  version "2.24.0"
+  resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.24.0.tgz#9d811e639b9aa6422e10d215523a2b9f899c0ea8"
   dependencies:
     buffer "4.9.1"
     crypto-browserify "1.0.9"
@@ -1662,9 +1658,9 @@ jest-jasmine2@^19.0.2:
     jest-message-util "^19.0.0"
     jest-snapshot "^19.0.2"
 
-jest-junit@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/jest-junit/-/jest-junit-1.2.0.tgz#5894bab45a5a13a7e1380cc7c63e7aae260064f4"
+jest-junit@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/jest-junit/-/jest-junit-1.3.0.tgz#e0c792a44f0adbfaa912bda586d5542a0b562fb9"
   dependencies:
     mkdirp "^0.5.1"
     xml "^1.0.1"
@@ -2000,9 +1996,9 @@ map-obj@^1.0.0, map-obj@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
 
-markdown-it@^8.3.0:
-  version "8.3.0"
-  resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.3.0.tgz#3d7a727a100cd24e276419c66da20ffbe28c3602"
+markdown-it@^8.3.1:
+  version "8.3.1"
+  resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.3.1.tgz#2f4b622948ccdc193d66f3ca2d43125ac4ac7323"
   dependencies:
     argparse "^1.0.7"
     entities "~1.1.1"
@@ -2136,9 +2132,9 @@ nopt@~1.0.10:
   dependencies:
     abbrev "1"
 
-normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5:
-  version "2.3.5"
-  resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.5.tgz#8d924f142960e1777e7ffe170543631cc7cb02df"
+normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.6:
+  version "2.3.6"
+  resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.6.tgz#498fa420c96401f787402ba21e600def9f981fff"
   dependencies:
     hosted-git-info "^2.1.4"
     is-builtin-module "^1.0.0"
@@ -2407,8 +2403,8 @@ q@^1.1.2:
   resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e"
 
 qs@~6.3.0:
-  version "6.3.1"
-  resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.1.tgz#918c0b3bcd36679772baf135b1acb4c1651ed79d"
+  version "6.3.2"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c"
 
 querystring@0.2.0:
   version "0.2.0"
@@ -2884,17 +2880,25 @@ truncate-utf8-bytes@^1.0.0:
   dependencies:
     utf8-byte-length "^1.0.1"
 
-ts-babel@^1.4.4:
-  version "1.4.4"
-  resolved "https://registry.yarnpkg.com/ts-babel/-/ts-babel-1.4.4.tgz#af116d2ba3f57c5f5342ba54d951baf1313ac748"
+ts-babel@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ts-babel/-/ts-babel-2.0.0.tgz#1681e8d70d242adf3d705d432ddd3459f1564c26"
   dependencies:
-    "@types/doctrine" "^0.0.3"
     babel-core "^6.23.1"
+    bluebird-lst "^1.0.1"
+    chalk "^1.1.3"
+    fs-extra-p "^4.0.2"
+    markdown-it "^8.3.1"
+    source-map-support "^0.4.11"
+
+ts-jsdoc@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/ts-jsdoc/-/ts-jsdoc-1.0.0.tgz#455a9d3fc7e20974669ce9e2b12c64703b4e9a7b"
+  dependencies:
     bluebird-lst "^1.0.1"
     chalk "^1.1.3"
     doctrine "^2.0.0"
     fs-extra-p "^4.0.2"
-    markdown-it "^8.3.0"
     source-map-support "^0.4.11"
 
 tslint@^4.5.1:
@@ -2912,8 +2916,8 @@ tslint@^4.5.1:
     update-notifier "^2.0.0"
 
 tsutils@^1.1.0:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.2.1.tgz#74101a75dbf435800614ccafa4cd89a8d41ea03e"
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.2.2.tgz#7e165c601367b9f89200b97ff47d9e38d1a6e4c8"
 
 tunnel-agent@^0.6.0:
   version "0.6.0"
@@ -2957,8 +2961,8 @@ uc.micro@^1.0.1, uc.micro@^1.0.3:
   resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192"
 
 uglify-js@^2.6:
-  version "2.8.7"
-  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.7.tgz#e0391911507b6d2e05697a528f1686e90a11b160"
+  version "2.8.8"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.8.tgz#1a5cd145eb528b606fa2b86e578885272b597cd7"
   dependencies:
     source-map "~0.5.1"
     uglify-to-browserify "~1.0.0"