forked from electron/rebuild
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmodule-rebuilder.ts
131 lines (107 loc) · 4.26 KB
/
module-rebuilder.ts
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
import debug from 'debug';
import * as fs from 'fs-extra';
import * as path from 'path';
import { cacheModuleState } from './cache';
import { NodeGyp } from './module-type/node-gyp';
import { Prebuildify } from './module-type/prebuildify';
import { PrebuildInstall } from './module-type/prebuild-install';
import { IRebuilder } from './types';
const d = debug('electron-rebuild');
export class ModuleRebuilder {
private modulePath: string;
private nodeGyp: NodeGyp;
private rebuilder: IRebuilder;
private prebuildify: Prebuildify;
private prebuildInstall: PrebuildInstall;
constructor(rebuilder: IRebuilder, modulePath: string) {
this.modulePath = modulePath;
this.rebuilder = rebuilder;
this.nodeGyp = new NodeGyp(rebuilder, modulePath);
this.prebuildify = new Prebuildify(rebuilder, modulePath);
this.prebuildInstall = new PrebuildInstall(rebuilder, modulePath);
}
get metaPath(): string {
return path.resolve(this.modulePath, 'build', this.rebuilder.buildType, '.forge-meta');
}
get metaData(): string {
return `${this.rebuilder.arch}--${this.rebuilder.ABI}`;
}
async alreadyBuiltByRebuild(): Promise<boolean> {
if (await fs.pathExists(this.metaPath)) {
const meta = await fs.readFile(this.metaPath, 'utf8');
return meta === this.metaData;
}
return false;
}
async cacheModuleState(cacheKey: string): Promise<void> {
if (this.rebuilder.useCache) {
await cacheModuleState(this.modulePath, this.rebuilder.cachePath, cacheKey);
}
}
/**
* Whether a prebuild-install-generated native module exists.
*/
async prebuildInstallNativeModuleExists(): Promise<boolean> {
return this.prebuildInstall.prebuiltModuleExists();
}
/**
* If the native module uses prebuildify, check to see if it comes with a prebuilt module for
* the given platform and arch.
*/
async findPrebuildifyModule(cacheKey: string): Promise<boolean> {
if (await this.prebuildify.usesTool()) {
d(`assuming is prebuildify powered: ${this.prebuildify.moduleName}`);
if (await this.prebuildify.findPrebuiltModule()) {
await this.writeMetadata();
await this.cacheModuleState(cacheKey);
return true;
}
}
return false;
}
async findPrebuildInstallModule(cacheKey: string): Promise<boolean> {
if (await this.prebuildInstall.usesTool()) {
d(`assuming is prebuild-install powered: ${this.prebuildInstall.moduleName}`);
if (await this.prebuildInstall.findPrebuiltModule()) {
d('installed prebuilt module:', this.prebuildInstall.moduleName);
await this.writeMetadata();
await this.cacheModuleState(cacheKey);
return true;
}
}
return false;
}
async rebuildNodeGypModule(cacheKey: string): Promise<boolean> {
await this.nodeGyp.rebuildModule();
d('built via node-gyp:', this.nodeGyp.moduleName);
await this.writeMetadata();
await this.replaceExistingNativeModule();
await this.cacheModuleState(cacheKey);
return true;
}
async replaceExistingNativeModule(): Promise<void> {
const buildLocation = path.resolve(this.modulePath, 'build', this.rebuilder.buildType);
d('searching for .node file', buildLocation);
const buildLocationFiles = await fs.readdir(buildLocation);
d('testing files', buildLocationFiles);
const nodeFile = buildLocationFiles.find((file) => file !== '.node' && file.endsWith('.node'));
const nodePath = nodeFile ? path.resolve(buildLocation, nodeFile) : undefined;
if (nodePath && await fs.pathExists(nodePath)) {
d('found .node file', nodePath);
if (!this.rebuilder.disablePreGypCopy) {
const abiPath = path.resolve(this.modulePath, `bin/${this.rebuilder.platform}-${this.rebuilder.arch}-${this.rebuilder.ABI}`);
d('copying to prebuilt place:', abiPath);
await fs.mkdir(abiPath, { recursive: true });
await fs.copyFile(nodePath, path.join(abiPath, `${this.nodeGyp.moduleName}.node`));
}
}
}
async writeMetadata(): Promise<void> {
await fs.outputFile(this.metaPath, this.metaData);
}
async rebuild(cacheKey: string): Promise<boolean> {
return (await this.findPrebuildifyModule(cacheKey)) ||
(await this.findPrebuildInstallModule(cacheKey)) ||
(await this.rebuildNodeGypModule(cacheKey));
}
}