-
-
Notifications
You must be signed in to change notification settings - Fork 40
Expand file tree
/
Copy pathpostinstall.mjs
More file actions
93 lines (84 loc) · 2.97 KB
/
postinstall.mjs
File metadata and controls
93 lines (84 loc) · 2.97 KB
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
import child_process from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
import url from 'node:url';
import nodeGypBuild from 'node-gyp-build';
/**
* Unfortunately, there is a sticky situation with Node-API:
* - `prebuildify` can only build one target from a binding.gyp at a time
* - The `node-gyp-build` install script can build all targets from a binding.gyp because node-gyp
* can handle it, but it will only look for a single *.node prebuild file when code uses it
* to find prebuilds
* So we're stuck with this `npm install` script that will run `node-gyp-build` if necessary,
* separately for each distinct Node-API package.
*
* This wouldn't be a problem if we went full monorepo and published the sub-packages as scoped
* npm packages, but that's a lot of overhead for code that is so tightly coupled together and not
* meant for public reuse.
*/
let modulesParentDir = path.dirname(url.fileURLToPath(import.meta.url));
while (!fs.existsSync(path.join(modulesParentDir, 'node_modules'))) {
const nextParentDir = path.dirname(modulesParentDir);
if (nextParentDir === modulesParentDir) {
throw new Error('failed to find node_modules directory');
}
modulesParentDir = nextParentDir;
}
for (let napiPackage of [
path.join('packages', 'zlib-1.1.3'),
path.join('packages', 'zstd-1.5.5'),
]) {
try {
await fs.promises.stat('dist');
napiPackage = path.join('dist', napiPackage);
} catch {
/* ignored */
}
// Do nothing if `node-gyp-build` can find a prebuild or a full build
const addonDirectory = path.join(napiPackage, `addon-${path.basename(napiPackage)}`);
try {
nodeGypBuild(addonDirectory);
continue;
} catch {
/* ignored */
}
process.stdout.write(`\n${napiPackage}: building from source ...\n\n`);
// Run a build if no prebuild was found
await new Promise((resolve, reject) => {
const nodeGypBuild = path.join(modulesParentDir, 'node_modules', '.bin', 'node-gyp-build');
const proc =
process.platform === 'win32'
? child_process.spawn('cmd.exe', ['/c', `${nodeGypBuild}.cmd`], {
cwd: napiPackage,
windowsHide: true,
})
: child_process.spawn(nodeGypBuild, [], { cwd: napiPackage });
proc.stdout.on('data', (data) =>
process.stdout.write(
data
.toString()
.split('\n')
.map((line) => `${napiPackage}: ${line}`)
.join('\n'),
),
);
proc.stderr.on('data', (data) =>
process.stderr.write(
data
.toString()
.split('\n')
.map((line) => `${napiPackage}: ${line}`)
.join('\n'),
),
);
proc.on('close', resolve);
proc.on('error', reject);
});
// Relocate the build output to the addon directory
try {
await fs.promises.stat(addonDirectory);
} catch {
await fs.promises.mkdir(addonDirectory);
}
await fs.promises.rename(path.join(napiPackage, 'build'), path.join(addonDirectory, 'build'));
}