Skip to content

Commit

Permalink
feat: proton support (part 1)
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed Mar 19, 2018
1 parent 504d161 commit f20d7cc
Show file tree
Hide file tree
Showing 24 changed files with 286 additions and 76 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"////": "All typings are added into root `package.json` to avoid duplication errors in the IDE compiler (several `node.d.ts` files).",
"dependencies": {
"7zip-bin": "~3.1.0",
"app-builder-bin": "1.7.2",
"app-builder-bin": "1.7.3",
"archiver": "^2.1.1",
"async-exit-hook": "^2.0.1",
"aws-sdk": "^2.211.0",
Expand All @@ -55,7 +55,7 @@
"minimatch": "^3.0.4",
"normalize-package-data": "^2.4.0",
"parse-color": "^1.0.0",
"plist": "^2.1.0",
"plist": "^3.0.0",
"read-config-file": "3.0.0",
"sanitize-filename": "^1.6.1",
"sax": "^1.2.4",
Expand Down
2 changes: 1 addition & 1 deletion packages/builder-util/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"out"
],
"dependencies": {
"app-builder-bin": "1.7.2",
"app-builder-bin": "1.7.3",
"temp-file": "^3.1.1",
"fs-extra-p": "^4.5.2",
"is-ci": "^1.1.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/builder-util/src/binDownload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function getBinFromGithub(name: string, version: string, checksum: string
return getBin(dirName, `https://github.com/electron-userland/electron-builder-binaries/releases/download/${dirName}/${dirName}.7z`, checksum)
}

export function getBin(name: string, url: string, checksum: string): Promise<string> {
export function getBin(name: string, url: string, checksum: string | null): Promise<string> {
let promise = versionToPromise.get(name)
// if rejected, we will try to download again
if (promise != null) {
Expand All @@ -27,7 +27,7 @@ export function getBin(name: string, url: string, checksum: string): Promise<str
return promise
}

function doGetBin(name: string, url: string, checksum: string): Promise<string> {
function doGetBin(name: string, url: string, checksum: string | null): Promise<string> {
const args = ["download-artifact", "--url", url, "--name", name]
if (checksum != null) {
args.push("--sha512", checksum)
Expand Down
4 changes: 2 additions & 2 deletions packages/electron-builder-lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"homepage": "https://github.com/electron-userland/electron-builder",
"dependencies": {
"7zip-bin": "~3.1.0",
"app-builder-bin": "1.7.2",
"app-builder-bin": "1.7.3",
"async-exit-hook": "^2.0.1",
"bluebird-lst": "^1.0.5",
"chromium-pickle-js": "^0.2.0",
Expand All @@ -58,7 +58,7 @@
"read-config-file": "3.0.0",
"minimatch": "^3.0.4",
"normalize-package-data": "^2.4.0",
"plist": "^2.1.0",
"plist": "^3.0.0",
"sanitize-filename": "^1.6.1",
"semver": "^5.5.0",
"debug": "^3.1.0",
Expand Down
19 changes: 19 additions & 0 deletions packages/electron-builder-lib/src/Framework.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { PlatformPackager } from "./platformPackager"

export interface Framework {
readonly name: string
readonly version: string
readonly distMacOsAppName: string

readonly isNpmRebuildRequired: boolean

unpackFramework(options: UnpackFrameworkTaskOptions): Promise<any>
}

export interface UnpackFrameworkTaskOptions {
readonly packager: PlatformPackager<any>
readonly appOutDir: string
readonly platformName: string
readonly arch: string
readonly version: string
}
53 changes: 53 additions & 0 deletions packages/electron-builder-lib/src/ProtonFramework.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { chmod, copyFile, ensureDir, writeFile } from "fs-extra-p"
import { getBin } from "builder-util/out/binDownload"
import { Framework } from "./Framework"
import * as path from "path"
import MacPackager from "./macPackager"

export function createProtonFrameworkSupport(nodeVersion: string): Framework {
return {
name: "proton",
version: nodeVersion,
distMacOsAppName: "Proton.app",
isNpmRebuildRequired: false,
unpackFramework: async options => {
const appContentsDir = path.join(options.appOutDir, "Proton.app/Contents")
await ensureDir(path.join(appContentsDir, "Resources"))
await ensureDir(path.join(appContentsDir, "MacOS"))
await copyFile(path.join(await getBin("node", `${nodeVersion}-darwin-x64`, null), "node"), path.join(appContentsDir, "MacOS", "node"))

// todo rename
const appName = "Proton.app"

// todo icon
const appInfo = options.packager.appInfo
await writeFile(path.join(appContentsDir, "Info.plist"), `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>${appName}</string>
<key>CFBundleExecutable</key>
<string>main</string>
<key>CFBundleIconFile</key>
<string>Icon</string>
<key>CFBundleIdentifier</key>
<string>${appInfo.macBundleIdentifier}</string>
<key>CFBundleVersion</key>
<string>${appInfo.version}</string>
<key>CFBundleGetInfoString</key>
<string>0.1 built by me</string>
<key>CFBundleShortVersionString</key>
<string>${(options.packager as MacPackager).platformSpecificBuildOptions.bundleShortVersion || appInfo.version}</string>
</dict>
</plist>
`)
const appMain = ""
await writeFile(path.join(appContentsDir, "MacOS", "main"), `#!/bin/sh
DIR=$(dirname "$0")
"$DIR/node" "$DIR/../Resources/app/${appMain}"
`, {mode: 0o755})
await chmod(path.join(appContentsDir, "MacOS", "main"), 0o755)
},
}
}
11 changes: 11 additions & 0 deletions packages/electron-builder-lib/src/appInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ export class AppInfo {
return appId == null ? generateDefaultAppId() : appId
}

get macBundleIdentifier(): string {
return filterCFBundleIdentifier(this.id)
}

get name(): string {
return this.info.metadata.name!
}
Expand All @@ -105,3 +109,10 @@ export class AppInfo {
return info == null || info.type !== "github" ? null : `https://${info.domain}/${info.user}/${info.project}`
}
}

/** @internal */
export function filterCFBundleIdentifier(identifier: string) {
// Remove special characters and allow only alphanumeric (A-Z,a-z,0-9), hyphen (-), and period (.)
// Apple documentation: https://developer.apple.com/library/mac/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102070
return identifier.replace(/ /g, "-").replace(/[^a-zA-Z0-9.-]/g, "")
}
5 changes: 5 additions & 0 deletions packages/electron-builder-lib/src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@ export interface Configuration extends PlatformSpecificBuildOptions {
*/
readonly muonVersion?: string | null

/**
* The version of NodeJS that will be used for Proton you are packaging for.
*/
readonly protonNodeVersion?: string | null

/**
* The function (or path to file or module id) to be run after pack (but before pack into distributable format and sign).
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import BluebirdPromise from "bluebird-lst"
import { debug7zArgs, exec, isEnvTrue, log, spawn } from "builder-util"
import { copyDir, DO_NOT_USE_HARD_LINKS, statOrNull } from "builder-util/out/fs"
import { chmod, emptyDir } from "fs-extra-p"
import { Lazy } from "lazy-val"
import * as path from "path"
import { Configuration, ElectronDownloadOptions } from "../configuration"
import { Framework, UnpackFrameworkTaskOptions } from "../Framework"
import { Packager } from "../packager"
import { PlatformPackager } from "../platformPackager"
import { computeElectronVersion, getElectronVersionFromInstalled } from "./electronVersion"

interface InternalElectronDownloadOptions extends ElectronDownloadOptions {
version: string
Expand All @@ -22,18 +26,38 @@ function createDownloadOpts(opts: Configuration, platform: string, arch: string,
}
}

/** @internal */
export function unpackElectron(packager: PlatformPackager<any>, out: string, platform: string, arch: string, version: string) {
return unpack(packager, out, platform, createDownloadOpts(packager.config, platform, arch, version))
export async function createElectronFrameworkSupport(configuration: Configuration, packager: Packager): Promise<Framework> {
let version = configuration.electronVersion
if (version == null) {
// for prepacked app asar no dev deps in the app.asar
if (packager.isPrepackedAppAsar) {
version = await getElectronVersionFromInstalled(packager.projectDir)
if (version == null) {
throw new Error(`Cannot compute electron version for prepacked asar`)
}
}
else {
version = await computeElectronVersion(packager.projectDir, new Lazy(() => Promise.resolve(packager.metadata)))
}
configuration.electronVersion = version
}

return {
name: "electron",
version,
distMacOsAppName: "Electron.app",
isNpmRebuildRequired: true,
unpackFramework: options => unpack(options.packager, options.appOutDir, options.platformName, createDownloadOpts(options.packager.config, options.platformName, options.arch, version!!)),
}
}

/** @internal */
export function unpackMuon(packager: PlatformPackager<any>, out: string, platform: string, arch: string, version: string) {
return unpack(packager, out, platform, {
export function unpackMuon(options: UnpackFrameworkTaskOptions) {
return unpack(options.packager, options.appOutDir, options.platformName, {
mirror: "https://github.com/brave/muon/releases/download/v",
customFilename: `brave-v${version}-${platform}-${arch}.zip`,
customFilename: `brave-v${options.version}-${options.platformName}-${options.arch}.zip`,
verifyChecksum: false,
...createDownloadOpts(packager.config, platform, arch, version),
...createDownloadOpts(options.packager.config, options.platformName, options.arch, options.version),
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { Lazy } from "lazy-val"
import * as path from "path"
import { orNullIfFileNotExist } from "read-config-file"
import { Configuration } from "../configuration"
import { getConfig } from "./config"
import { versionFromDependencyRange } from "./packageMetadata"
import { getConfig } from "../util/config"
import { versionFromDependencyRange } from "../util/packageMetadata"

export type MetadataValue = Lazy<{ [key: string]: any } | null>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { copyFile, copyOrLinkFile, unlinkIfExists } from "builder-util/out/fs"
import { readFile, rename, utimes, writeFile } from "fs-extra-p"
import * as path from "path"
import { build as buildPlist, parse as parsePlist } from "plist"
import { filterCFBundleIdentifier } from "../appInfo"
import { AsarIntegrity } from "../asar/integrity"
import { normalizeExt, PlatformPackager } from "../platformPackager"

Expand All @@ -19,13 +20,6 @@ function moveHelpers(frameworksPath: string, appName: string, prefix: string): P
})
}

/** @internal */
export function filterCFBundleIdentifier(identifier: string) {
// Remove special characters and allow only alphanumeric (A-Z,a-z,0-9), hyphen (-), and period (.)
// Apple documentation: https://developer.apple.com/library/mac/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102070
return identifier.replace(/ /g, "-").replace(/[^a-zA-Z0-9.-]/g, "")
}

/** @internal */
export async function createMacApp(packager: PlatformPackager<any>, appOutDir: string, asarIntegrity: AsarIntegrity | null) {
const appInfo = packager.appInfo
Expand Down Expand Up @@ -56,7 +50,7 @@ export async function createMacApp(packager: PlatformPackager<any>, appOutDir: s
Object.assign(appPlist, macOptions.extendInfo)
}

const appBundleIdentifier = filterCFBundleIdentifier(appInfo.id)
const appBundleIdentifier = appInfo.macBundleIdentifier

const oldHelperBundleId = (buildMetadata as any)["helper-bundle-id"]
if (oldHelperBundleId != null) {
Expand Down
2 changes: 1 addition & 1 deletion packages/electron-builder-lib/src/macPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { appleCertificatePrefixes, CertType, CodeSigningInfo, createKeychain, fi
import { DIR_TARGET, Platform, Target } from "./core"
import { MacConfiguration, MasConfiguration } from "./options/macOptions"
import { Packager } from "./packager"
import { createMacApp } from "./packager/mac"
import { createMacApp } from "./electron/mac"
import { chooseNotNull, PlatformPackager } from "./platformPackager"
import { ArchiveTarget } from "./targets/ArchiveTarget"
import { PkgTarget, prepareProductBuildArgs } from "./targets/pkg"
Expand Down
43 changes: 29 additions & 14 deletions packages/electron-builder-lib/src/packager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ import { AppInfo } from "./appInfo"
import { readAsarJson } from "./asar/asar"
import { AfterPackContext, Configuration } from "./configuration"
import { Platform, SourceRepositoryInfo, Target } from "./core"
import { Framework } from "./Framework"
import MacPackager from "./macPackager"
import { Metadata } from "./options/metadata"
import { createElectronFrameworkSupport, unpackMuon } from "./electron/ElectronFramework"
import { ArtifactCreated, PackagerOptions } from "./packagerApi"
import { PlatformPackager, resolveFunction } from "./platformPackager"
import { createProtonFrameworkSupport } from "./ProtonFramework"
import { computeArchToTargetNamesMap, createTargets, NoOpTarget } from "./targets/targetFactory"
import { computeDefaultAppDirectory, getConfig, validateConfig } from "./util/config"
import { computeElectronVersion, getElectronVersionFromInstalled } from "./util/electronVersion"
import { Dependency, getProductionDependencies } from "./util/packageDependencies"
import { checkMetadata, readPackageJson } from "./util/packageMetadata"
import { getRepositoryInfo } from "./util/repositoryInfo"
Expand All @@ -32,6 +34,24 @@ function addHandler(emitter: EventEmitter, event: string, handler: (...args: Arr

declare const PACKAGE_VERSION: string

async function createFrameworkInfo(configuration: Configuration, packager: Packager): Promise<Framework> {
if (configuration.muonVersion != null) {
return {
name: "muon",
version: configuration.muonVersion!!,
distMacOsAppName: "Brave.app",
unpackFramework: unpackMuon,
isNpmRebuildRequired: true,
}
}
else if (configuration.protonNodeVersion != null) {
return createProtonFrameworkSupport(configuration.protonNodeVersion!!)
}
else {
return await createElectronFrameworkSupport(configuration, packager)
}
}

export class Packager {
readonly projectDir: string

Expand Down Expand Up @@ -133,6 +153,11 @@ export class Packager {
return this.config.directories!!.buildResources!!
}

private _framework: Framework | null = null
get framework(): Framework {
return this._framework!!
}

//noinspection JSUnusedGlobalSymbols
constructor(options: PackagerOptions, readonly cancellationToken = new CancellationToken()) {
if ("devMetadata" in options) {
Expand Down Expand Up @@ -284,17 +309,7 @@ export class Packager {
this._repositoryInfo.value = Promise.resolve(repositoryInfo)
}

const projectDir = this.projectDir
if (configuration.electronVersion == null) {
// for prepacked app asar no dev deps in the app.asar
if (this.isPrepackedAppAsar) {
configuration.electronVersion = await getElectronVersionFromInstalled(projectDir)
if (configuration.electronVersion == null) {
throw new Error(`Cannot compute electron version for prepacked asar`)
}
}
configuration.electronVersion = await computeElectronVersion(projectDir, new Lazy(() => Promise.resolve(this.metadata)))
}
this._framework = await createFrameworkInfo(this.config, this)
this._appInfo = new AppInfo(this)

const outDir = path.resolve(this.projectDir, configuration.directories!!.output!!)
Expand Down Expand Up @@ -407,11 +422,11 @@ export class Packager {
}

private async installAppDependencies(platform: Platform, arch: Arch): Promise<any> {
if (this.options.prepackaged != null) {
if (this.options.prepackaged != null || this.framework.isNpmRebuildRequired !== true) {
return
}

const frameworkInfo = {version: this.config.muonVersion || this.config.electronVersion!, useCustomDist: this.config.muonVersion == null}
const frameworkInfo = {version: this.framework.version, useCustomDist: this.config.muonVersion == null}
const config = this.config
if (config.nodeGypRebuild === true) {
log.info({arch: Arch[arch]}, "executing node-gyp rebuild")
Expand Down
Loading

0 comments on commit f20d7cc

Please sign in to comment.