Skip to content

Commit c46e1f5

Browse files
committed
feat: build mas + other targets, osx 7z
1 parent 955507f commit c46e1f5

File tree

16 files changed

+209
-197
lines changed

16 files changed

+209
-197
lines changed

.idea/dictionaries/develar.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/runConfigurations/BuildTest.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/runConfigurations/osxPackagerTest.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/Options.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ See all [appdmg options](https://www.npmjs.com/package/appdmg#json-specification
7070
| --- | ---
7171
| icon | <a name="OsXBuildOptions-icon"></a>The path to icon, which will be shown when mounted (default: `build/icon.icns`).
7272
| background | <a name="OsXBuildOptions-background"></a>The path to background (default: `build/background.png`). The resolution of this file determines the resolution of the installer window.
73-
| target | <a name="OsXBuildOptions-target"></a>Target package type: list of `default`, `dmg`, `zip`, `mas`.
73+
| target | <a name="OsXBuildOptions-target"></a>Target package type: list of `default`, `dmg`, `zip`, `mas`, `7z`.
7474

7575
<a name="WinBuildOptions"></a>
7676
### `.build.win`

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
"electron-osx-sign-tf": "^0.4.0-beta.0",
6464
"electron-packager-tf": "^7.0.2-beta.0",
6565
"electron-winstaller-fixed": "~2.4.0-beta.0",
66-
"fs-extra-p": "^0.3.0",
66+
"fs-extra-p": "^0.4.0",
6767
"globby": "^4.0.0",
6868
"hosted-git-info": "^2.1.4",
6969
"image-size": "^0.5.0",

src/metadata.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ export interface OsXBuildOptions extends PlatformSpecificBuildOptions {
160160
readonly background?: string
161161

162162
/*
163-
Target package type: list of `default`, `dmg`, `zip`, `mas`.
163+
Target package type: list of `default`, `dmg`, `zip`, `mas`, `7z`.
164164
*/
165165
readonly target?: Array<string>
166166
}

src/osxPackager.ts

Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { PlatformPackager, BuildInfo } from "./platformPackager"
1+
import { PlatformPackager, BuildInfo, normalizeTargets } from "./platformPackager"
22
import { Platform, OsXBuildOptions } from "./metadata"
33
import * as path from "path"
44
import { Promise as BluebirdPromise } from "bluebird"
@@ -14,7 +14,7 @@ const __awaiter = require("./awaiter")
1414
export default class OsXPackager extends PlatformPackager<OsXBuildOptions> {
1515
codeSigningInfo: Promise<CodeSigningInfo>
1616

17-
readonly target: Array<string>
17+
readonly targets: Array<string>
1818

1919
constructor(info: BuildInfo, cleanupTasks: Array<() => Promise<any>>) {
2020
super(info)
@@ -28,41 +28,45 @@ export default class OsXPackager extends PlatformPackager<OsXBuildOptions> {
2828
this.codeSigningInfo = BluebirdPromise.resolve(null)
2929
}
3030

31-
let target = this.customBuildOptions == null ? null : this.customBuildOptions.target
32-
if (target != null) {
33-
target = Array.isArray(target) ? target : [target]
34-
target = target.map(it => it.toLowerCase().trim())
35-
for (let t of target) {
36-
if (t !== "default" && t !== "dmg" && t !== "zip" && t !== "mas") {
37-
throw new Error("Unknown target: " + t)
31+
const targets = normalizeTargets(this.customBuildOptions == null ? null : this.customBuildOptions.target)
32+
if (targets != null) {
33+
for (let target of targets) {
34+
if (target !== "default" && target !== "dmg" && target !== "zip" && target !== "mas" && target !== "7z") {
35+
throw new Error("Unknown target: " + target)
3836
}
3937
}
4038
}
41-
this.target = target == null ? ["default"] : target
39+
this.targets = targets == null ? ["default"] : targets
4240
}
4341

4442
get platform() {
4543
return Platform.OSX
4644
}
4745

48-
protected computeAppOutDir(outDir: string, arch: string): string {
49-
return this.target.includes("mas") ? path.join(outDir, `${this.appName}-mas-${arch}`) : super.computeAppOutDir(outDir, arch)
50-
}
46+
async pack(outDir: string, arch: string, postAsyncTasks: Array<Promise<any>>): Promise<any> {
47+
const packOptions = this.computePackOptions(outDir, arch)
48+
let nonMasPromise: Promise<any> = null
49+
if (this.targets.length > 1 || this.targets[0] !== "mas") {
50+
const appOutDir = this.computeAppOutDir(outDir, arch)
51+
nonMasPromise = this.doPack(packOptions, outDir, appOutDir, arch)
52+
.then(() => this.sign(appOutDir, false))
53+
.then(() => postAsyncTasks.push(this.packageInDistributableFormat(outDir, appOutDir, arch)))
54+
}
5155

52-
async doPack(outDir: string, appOutDir: string, arch: string): Promise<any> {
53-
await super.doPack(outDir, appOutDir, arch)
54-
await this.sign(appOutDir, await this.codeSigningInfo)
55-
}
56+
if (this.targets.includes("mas")) {
57+
// osx-sign - disable warning
58+
const appOutDir = path.join(outDir, `${this.appName}-mas-${arch}`)
59+
await this.doPack(Object.assign({}, packOptions, {platform: "mas", "osx-sign": false}), outDir, appOutDir, arch)
60+
await this.sign(appOutDir, true)
61+
}
5662

57-
protected beforePack(options: any): void {
58-
if (this.target.includes("mas")) {
59-
options.platform = "mas"
63+
if (nonMasPromise != null) {
64+
await nonMasPromise
6065
}
61-
// disable warning
62-
options["osx-sign"] = false
6366
}
6467

65-
private async sign(appOutDir: string, codeSigningInfo: CodeSigningInfo): Promise<any> {
68+
private async sign(appOutDir: string, isMas: boolean): Promise<any> {
69+
let codeSigningInfo = await this.codeSigningInfo
6670
if (codeSigningInfo == null) {
6771
codeSigningInfo = {
6872
name: this.options.sign || process.env.CSC_NAME,
@@ -77,7 +81,6 @@ export default class OsXPackager extends PlatformPackager<OsXBuildOptions> {
7781

7882
log("Signing app")
7983

80-
const isMas = this.target.includes("mas")
8184
const baseSignOptions: BaseSignOptions = {
8285
app: path.join(appOutDir, this.appName + ".app"),
8386
platform: isMas ? "mas" : "darwin"
@@ -133,10 +136,10 @@ export default class OsXPackager extends PlatformPackager<OsXBuildOptions> {
133136
}
134137

135138
packageInDistributableFormat(outDir: string, appOutDir: string, arch: string): Promise<any> {
136-
const artifactPath = path.join(appOutDir, `${this.appName}-${this.metadata.version}.dmg`)
137139
const promises: Array<Promise<any>> = []
138140

139-
if (this.target.includes("dmg") || this.target.includes("default")) {
141+
if (this.targets.includes("dmg") || this.targets.includes("default")) {
142+
const artifactPath = path.join(appOutDir, `${this.appName}-${this.metadata.version}.dmg`)
140143
promises.push(new BluebirdPromise<any>(async(resolve, reject) => {
141144
log("Creating DMG")
142145
const dmgOptions = {
@@ -164,24 +167,34 @@ export default class OsXPackager extends PlatformPackager<OsXBuildOptions> {
164167
.then(() => this.dispatchArtifactCreated(artifactPath, `${this.metadata.name}-${this.metadata.version}.dmg`)))
165168
}
166169

167-
if (this.target.includes("zip") || this.target.includes("default")) {
168-
promises.push(this.zipMacApp(appOutDir)
169-
.then(it => this.dispatchArtifactCreated(it, `${this.metadata.name}-${this.metadata.version}-mac.zip`)))
170+
for (let target of this.targets) {
171+
if (target !== "mas" && target !== "dmg") {
172+
const format = target === "default" ? "zip" : target
173+
log("Creating OS X " + format)
174+
// for default we use mac to be compatible with Squirrel.Mac
175+
const classifier = target === "default" ? "mac" : "osx"
176+
promises.push(this.archiveApp(appOutDir, format, classifier)
177+
.then(it => this.dispatchArtifactCreated(it, `${this.metadata.name}-${this.metadata.version}-${classifier}.${format}`)))
178+
}
170179
}
171-
172180
return BluebirdPromise.all(promises)
173181
}
174182

175-
private zipMacApp(outDir: string): Promise<string> {
176-
log("Creating ZIP for Squirrel.Mac")
177-
// we use app name here - see https://github.com/electron-userland/electron-builder/pull/204
178-
const resultPath = `${this.appName}-${this.metadata.version}-mac.zip`
179-
const args = ["a", "-mm=" + (this.devMetadata.build.compression === "store" ? "Copy" : "Deflate"), "-bb" + (debug.enabled ? "3" : "0"), "-bd"]
180-
if (this.devMetadata.build.compression === "maximum") {
183+
private archiveApp(outDir: string, format: string, classifier: string): Promise<string> {
184+
const args = ["a", "-bb" + (debug.enabled ? "3" : "0"), "-bd"]
185+
const compression = this.devMetadata.build.compression
186+
const storeOnly = compression === "store"
187+
if (format === "zip" || storeOnly) {
188+
args.push("-mm=" + (storeOnly ? "Copy" : "Deflate"))
189+
}
190+
if (compression === "maximum") {
181191
// http://superuser.com/a/742034
182192
//noinspection SpellCheckingInspection
183193
args.push("-mfb=258", "-mpass=15")
184194
}
195+
196+
// we use app name here - see https://github.com/electron-userland/electron-builder/pull/204
197+
const resultPath = `${this.appName}-${this.metadata.version}-${classifier}.${format}`
185198
args.push(resultPath, this.appName + ".app")
186199

187200
return spawn(path7za, args, {

src/packager.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export class Packager implements BuildInfo {
5858
const appPackageFile = this.projectDir === this.appDir ? devPackageFile : path.join(this.appDir, "package.json")
5959
this.metadata = appPackageFile === devPackageFile ? this.devMetadata : await readPackageJson(appPackageFile)
6060
this.checkMetadata(appPackageFile, devPackageFile, platforms)
61+
checkConflictingOptions(this.devMetadata.build)
6162

6263
this.electronVersion = await getElectronVersion(this.devMetadata, devPackageFile)
6364

@@ -74,11 +75,7 @@ export class Packager implements BuildInfo {
7475
for (let arch of normalizeArchs(platform, this.options.arch)) {
7576
await this.installAppDependencies(platform, arch)
7677
// electron-packager uses productName in the directory name
77-
const appOutDir = await helper.pack(outDir, arch)
78-
if (this.options.dist) {
79-
distTasks.push(helper.packageInDistributableFormat(outDir, appOutDir, arch))
80-
}
81-
}
78+
await helper.pack(outDir, arch, distTasks)}
8279
}
8380

8481
return await BluebirdPromise.all(distTasks)
@@ -198,3 +195,11 @@ export function normalizePlatforms(platforms: Array<string | Platform>): Array<P
198195
return platforms.map(it => it instanceof Platform ? it : Platform.fromString(it))
199196
}
200197
}
198+
199+
function checkConflictingOptions(options: any) {
200+
for (let name of ["all", "out", "tmpdir", "version", "platform", "dir", "arch"]) {
201+
if (name in options) {
202+
throw new Error(`Option ${name} is ignored, do not specify it.`)
203+
}
204+
}
205+
}

src/platformPackager.ts

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { statOrNull, use } from "./util"
1010
import { Packager } from "./packager"
1111
import deepAssign = require("deep-assign")
1212
import { statFile } from "asar"
13+
import ElectronPackagerOptions = ElectronPackager.ElectronPackagerOptions
1314

1415
//noinspection JSUnusedLocalSymbols
1516
const __awaiter = require("./awaiter")
@@ -106,27 +107,27 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
106107
})
107108
}
108109

109-
async pack(outDir: string, arch: string): Promise<string> {
110+
pack(outDir: string, arch: string, postAsyncTasks: Array<Promise<any>>): Promise<any> {
110111
const appOutDir = this.computeAppOutDir(outDir, arch)
111-
await this.doPack(outDir, appOutDir, arch)
112-
await this.copyExtraResources(appOutDir, arch)
113-
return appOutDir
112+
return this.doPack(this.computePackOptions(outDir, arch), outDir, appOutDir, arch, postAsyncTasks)
114113
}
115114

116-
protected beforePack(options: any): void {
117-
// to override
115+
protected async doPack(options: ElectronPackagerOptions, outDir: string, appOutDir: string, arch: string, postAsyncTasks: Array<Promise<any>> = null) {
116+
await this.packApp(options, appOutDir)
117+
await this.copyExtraResources(appOutDir, arch)
118+
if (postAsyncTasks != null && this.options.dist) {
119+
postAsyncTasks.push(this.packageInDistributableFormat(outDir, appOutDir, arch))
120+
}
118121
}
119122

120-
protected async doPack(outDir: string, appOutDir: string, arch: string): Promise<any> {
123+
protected computePackOptions(outDir: string, arch: string): ElectronPackagerOptions {
121124
const version = this.metadata.version
122125
let buildVersion = version
123126
const buildNumber = this.computeBuildNumber()
124127
if (buildNumber != null) {
125128
buildVersion += "." + buildNumber
126129
}
127130

128-
checkConflictingOptions(this.devMetadata.build)
129-
130131
const options = deepAssign({
131132
dir: this.info.appDir,
132133
out: outDir,
@@ -153,8 +154,10 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
153154
delete options.linux
154155
// this option only for windows-installer
155156
delete options.iconUrl
157+
return options
158+
}
156159

157-
this.beforePack(options)
160+
protected async packApp(options: ElectronPackagerOptions, appOutDir: string): Promise<any> {
158161
await pack(options)
159162
await this.sanityCheckPackage(appOutDir, options.asar)
160163
}
@@ -186,7 +189,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
186189
return await BluebirdPromise.map(await this.getExtraResources(arch), it => copy(path.join(this.projectDir, it), path.join(resourcesDir, it)))
187190
}
188191

189-
abstract packageInDistributableFormat(outDir: string, appOutDir: string, arch: string): Promise<any>
192+
protected abstract packageInDistributableFormat(outDir: string, appOutDir: string, arch: string): Promise<any>
190193

191194
protected async computePackageUrl(): Promise<string> {
192195
const url = this.metadata.homepage || this.devMetadata.homepage
@@ -247,17 +250,18 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
247250
}
248251
}
249252

250-
function checkConflictingOptions(options: any) {
251-
for (let name of ["all", "out", "tmpdir", "version", "platform", "dir", "arch"]) {
252-
if (name in options) {
253-
throw new Error(`Option ${name} is ignored, do not specify it.`)
254-
}
255-
}
256-
}
257-
258253
export interface ArtifactCreated {
259254
readonly file: string
260255
readonly artifactName?: string
261256

262257
readonly platform: Platform
258+
}
259+
260+
export function normalizeTargets(targets: Array<string> | string): Array<string> {
261+
if (targets == null) {
262+
return null
263+
}
264+
else {
265+
return (Array.isArray(targets) ? targets : [targets]).map(it => it.toLowerCase().trim())
266+
}
263267
}

src/winPackager.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,19 +52,19 @@ export class WinPackager extends PlatformPackager<WinBuildOptions> {
5252
return iconPath
5353
}
5454

55-
async pack(outDir: string, arch: string): Promise<string> {
55+
async pack(outDir: string, arch: string, postAsyncTasks: Array<Promise<any>>): Promise<any> {
5656
// we must check icon before pack because electron-packager uses icon and it leads to cryptic error message "spawn wine ENOENT"
5757
await this.iconPath
5858

5959
if (!this.options.dist) {
60-
return await super.pack(outDir, arch)
60+
return await super.pack(outDir, arch, postAsyncTasks)
6161
}
6262

6363
const appOutDir = this.computeAppOutDir(outDir, arch)
6464
const installerOut = computeDistOut(outDir, arch)
6565
log("Removing %s", installerOut)
6666
await BluebirdPromise.all([
67-
this.doPack(outDir, appOutDir, arch),
67+
this.packApp(this.computePackOptions(outDir, arch), appOutDir),
6868
emptyDir(installerOut)
6969
])
7070

@@ -80,11 +80,13 @@ export class WinPackager extends PlatformPackager<WinBuildOptions> {
8080
})
8181
}
8282

83-
return appOutDir
83+
if (this.options.dist) {
84+
postAsyncTasks.push(this.packageInDistributableFormat(outDir, appOutDir, arch))
85+
}
8486
}
8587

86-
protected async doPack(outDir: string, appOutDir: string, arch: string) {
87-
await super.doPack(outDir, appOutDir, arch)
88+
protected async packApp(options: any, appOutDir: string) {
89+
await super.packApp(options, appOutDir)
8890

8991
if (process.platform === "darwin" && this.options.cscLink != null && this.options.cscKeyPassword != null) {
9092
const filename = this.appName + ".exe"

0 commit comments

Comments
 (0)