-
-
Notifications
You must be signed in to change notification settings - Fork 487
/
make.js
177 lines (152 loc) · 5.97 KB
/
make.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import 'colors';
import fs from 'fs-extra';
import path from 'path';
import { hostArch } from 'electron-packager/targets';
import asyncOra from '../util/ora-handler';
import getForgeConfig from '../util/forge-config';
import runHook from '../util/hook';
import { info, warn } from '../util/messages';
import parseArchs from '../util/parse-archs';
import readPackageJSON from '../util/read-package-json';
import { requireSearchRaw } from '../util/require-search';
import resolveDir from '../util/resolve-dir';
import packager from './package';
/**
* @typedef {Object} MakeOptions
* @property {string} [dir=process.cwd()] The path to the app from which distributables are generated
* @property {boolean} [interactive=false] Whether to use sensible defaults or prompt the user visually
* @property {boolean} [skipPackage=false] Whether to skip the pre-make packaging step
* @property {Array<string>} [overrideTargets] An array of make targets to override your forge config
* @property {string} [arch=host architecture] The target architecture
* @property {string} [platform=process.platform] The target platform.
* @property {string} [outDir=`${dir}/out`] The path to the directory containing generated distributables
*/
/**
* @typedef {Object} MakeResult
* @property {Array<string>} artifacts An array of paths to artifacts generated for this make run
* @property {Object} packageJSON The state of the package.json file when the make happened
* @property {string} platform The platform this make run was for
* @property {string} arch The arch this make run was for
*/
/**
* Make distributables for an Electron application.
*
* @param {MakeOptions} providedOptions - Options for the make method
* @return {Promise<Array<MakeResult>>} Will resolve when the make process is complete
*/
export default async (providedOptions = {}) => {
// eslint-disable-next-line prefer-const, no-unused-vars
let { dir, interactive, skipPackage, overrideTargets, arch, platform } = Object.assign({
dir: process.cwd(),
interactive: false,
skipPackage: false,
arch: hostArch(),
platform: process.platform,
}, providedOptions);
const outDir = providedOptions.outDir || path.resolve(dir, 'out');
asyncOra.interactive = interactive;
let forgeConfig;
await asyncOra('Resolving Forge Config', async () => {
dir = await resolveDir(dir);
if (!dir) {
throw 'Failed to locate makeable Electron application';
}
forgeConfig = await getForgeConfig(dir);
});
if (!['darwin', 'win32', 'linux'].includes(platform)) {
throw new Error(`'${platform}' is an invalid platform. Choices are 'darwin', 'win32' or 'linux'`);
}
const makers = {};
const targets = overrideTargets || forgeConfig.make_targets[platform];
for (const target of targets) {
const maker = requireSearchRaw(__dirname, [
`../makers/${platform}/${target}.js`,
`../makers/generic/${target}.js`,
`electron-forge-maker-${target}`,
target,
path.resolve(dir, target),
path.resolve(dir, 'node_modules', target),
]);
if (!maker) {
throw new Error([
'Could not find a build target with the name: ',
`${target} for the platform: ${platform}`,
].join(''));
}
if (!maker.isSupportedOnCurrentPlatform) {
throw new Error([
`Maker for target ${target} is incompatible with this version of `,
'electron-forge, please upgrade or contact the maintainer ',
'(needs to implement \'isSupportedOnCurrentPlatform)\')',
].join(''));
}
if (!await maker.isSupportedOnCurrentPlatform()) {
throw new Error([
`Cannot build for ${platform} target ${target}: the maker declared `,
`that it cannot run on ${process.platform}`,
].join(''));
}
makers[target] = maker.default || maker;
}
if (!skipPackage) {
info(interactive, 'We need to package your application before we can make it'.green);
await packager({
dir,
interactive,
arch,
platform,
outDir,
});
} else {
warn(interactive, 'WARNING: Skipping the packaging step, this could result in an out of date build'.red);
}
info(interactive, 'Making for the following targets:', `${targets.join(', ')}`.cyan);
const packageJSON = await readPackageJSON(dir);
const appName = forgeConfig.electronPackagerConfig.name || packageJSON.productName || packageJSON.name;
let outputs = [];
await runHook(forgeConfig, 'preMake');
for (const targetArch of parseArchs(platform, arch, packageJSON.devDependencies['electron-prebuilt-compile'])) {
const packageDir = path.resolve(outDir, `${appName}-${platform}-${targetArch}`);
if (!(await fs.pathExists(packageDir))) {
throw new Error(`Couldn't find packaged app at: ${packageDir}`);
}
for (const target of targets) {
const maker = makers[target];
// eslint-disable-next-line no-loop-func
await asyncOra(`Making for target: ${target.cyan} - On platform: ${platform.cyan} - For arch: ${targetArch.cyan}`, async () => {
try {
const artifacts = await maker({
dir: packageDir,
appName,
targetPlatform: platform,
targetArch,
forgeConfig,
packageJSON,
});
outputs.push({
artifacts,
packageJSON,
platform,
arch: targetArch,
});
} catch (err) {
if (err) {
throw {
message: `An error occured while making for target: ${target}`,
stack: `${err.message}\n${err.stack}`,
};
} else {
throw new Error(`An unknown error occured while making for target: ${target}`);
}
}
});
}
}
const result = await runHook(forgeConfig, 'postMake', outputs);
// If the postMake hooks modifies the locations / names of the outputs it must return
// the new locations so that the publish step knows where to look
if (Array.isArray(result)) {
outputs = result;
}
return outputs;
};