Skip to content

Commit 82da9d9

Browse files
authored
fix: replacing macro {napi_build_version} in binary filename (#1078)
* fix: replacing macro {napi_build_versions} in binary filename by using `binary.napi_build_versions` in package.json. Fixes: #554 * cleanup * move napi_build_version to separate test fixture refactored rebuild helper * whoops. missed an unused import * log all files? * log upper dir? something is missing on linux builds * fix linux builds by detecting libc family * cleanup * refactor due to new file location (tsc now runs first) * fix test? * fix test? * revert yarnworkspace changes to check against master * add fixtureName to tmp dir * cleanup and simplify * switch back to use detect-libc and see if test passes
1 parent 02d7c66 commit 82da9d9

File tree

8 files changed

+81
-39
lines changed

8 files changed

+81
-39
lines changed

src/module-type/node-gyp/node-gyp.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ export class NodeGyp extends NativeModule {
4949

5050
async buildArgsFromBinaryField(): Promise<string[]> {
5151
const binary = await this.packageJSONFieldWithDefault('binary', {}) as Record<string, string>;
52+
let napiBuildVersion: number | undefined = undefined
53+
if (Array.isArray(binary.napi_versions)) {
54+
napiBuildVersion = this.nodeAPI.getNapiVersion(binary.napi_versions.map(str => Number(str)))
55+
}
5256
const flags = await Promise.all(Object.entries(binary).map(async ([binaryKey, binaryValue]) => {
5357
if (binaryKey === 'napi_versions') {
5458
return;
@@ -66,7 +70,9 @@ export class NodeGyp extends NativeModule {
6670
.replace('{arch}', this.rebuilder.arch)
6771
.replace('{version}', await this.packageJSONField('version') as string)
6872
.replace('{libc}', await detectLibc.family() || 'unknown');
69-
73+
if (napiBuildVersion !== undefined) {
74+
value = value.replace('{napi_build_version}', napiBuildVersion.toString())
75+
}
7076
for (const [replaceKey, replaceValue] of Object.entries(binary)) {
7177
value = value.replace(`{${replaceKey}}`, replaceValue);
7278
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "workspace-app",
3+
"productName": "Workspace App",
4+
"version": "1.0.0",
5+
"description": "",
6+
"main": "src/index.js",
7+
"keywords": [],
8+
"author": "",
9+
"license": "MIT",
10+
"dependencies": {
11+
"sqlite3": "5.1.6"
12+
}
13+
}

test/helpers/module-setup.ts

+5-6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const TIMEOUT_IN_MINUTES = process.platform === 'win32' ? 5 : 2;
1010
export const MINUTES_IN_MILLISECONDS = 60 * 1000;
1111
export const TIMEOUT_IN_MILLISECONDS = TIMEOUT_IN_MINUTES * MINUTES_IN_MILLISECONDS;
1212

13+
export const TEST_MODULE_PATH = path.resolve(os.tmpdir(), 'electron-rebuild-test');
14+
1315
export function resetMSVSVersion(): void {
1416
if (originalGypMSVSVersion) {
1517
process.env.GYP_MSVS_VERSION = originalGypMSVSVersion;
@@ -18,14 +20,11 @@ export function resetMSVSVersion(): void {
1820

1921
const testModuleTmpPath = fs.mkdtempSync(path.resolve(os.tmpdir(), 'e-r-test-module-'));
2022

21-
export async function resetTestModule(testModulePath: string, installModules = true): Promise<void> {
22-
const oneTimeModulePath = path.resolve(testModuleTmpPath, `${crypto.createHash('SHA1').update(testModulePath).digest('hex')}-${installModules}`);
23+
export async function resetTestModule(testModulePath: string, installModules = true, fixtureName = 'native-app1'): Promise<void> {
24+
const oneTimeModulePath = path.resolve(testModuleTmpPath, `${crypto.createHash('SHA1').update(testModulePath).digest('hex')}-${fixtureName}-${installModules}`);
2325
if (!await fs.pathExists(oneTimeModulePath)) {
2426
await fs.mkdir(oneTimeModulePath, { recursive: true });
25-
await fs.copyFile(
26-
path.resolve(__dirname, '../../test/fixture/native-app1/package.json'),
27-
path.resolve(oneTimeModulePath, 'package.json')
28-
);
27+
await fs.copy(path.resolve(__dirname, `../../test/fixture/${ fixtureName }`), oneTimeModulePath);
2928
if (installModules) {
3029
await spawn('yarn', ['install'], { cwd: oneTimeModulePath });
3130
}

test/module-type-node-gyp.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
import { EventEmitter } from 'events';
22
import { expect } from 'chai';
3-
import os from 'os';
4-
import path from 'path';
53

6-
import { cleanupTestModule, resetTestModule } from './helpers/module-setup';
4+
import { cleanupTestModule, resetTestModule, TEST_MODULE_PATH as testModulePath } from './helpers/module-setup';
75
import { NodeGyp } from '../lib/module-type/node-gyp/node-gyp';
86
import { Rebuilder } from '../lib/rebuild';
97

108
describe('node-gyp', () => {
119
describe('buildArgs', () => {
12-
const testModulePath = path.resolve(os.tmpdir(), 'electron-rebuild-test');
1310

1411
before(async () => await resetTestModule(testModulePath, false));
1512
after(async () => await cleanupTestModule(testModulePath));

test/module-type-prebuild-install.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
import chai, { expect } from 'chai';
22
import chaiAsPromised from 'chai-as-promised';
33
import { EventEmitter } from 'events';
4-
import os from 'os';
54
import path from 'path';
65

7-
import { cleanupTestModule, resetTestModule, TIMEOUT_IN_MILLISECONDS } from './helpers/module-setup';
6+
import { cleanupTestModule, resetTestModule, TIMEOUT_IN_MILLISECONDS, TEST_MODULE_PATH as testModulePath } from './helpers/module-setup';
87
import { PrebuildInstall } from '../lib/module-type/prebuild-install';
98
import { Rebuilder } from '../lib/rebuild';
109

1110
chai.use(chaiAsPromised);
1211

13-
const testModulePath = path.resolve(os.tmpdir(), 'electron-rebuild-test');
14-
1512
describe('prebuild-install', () => {
1613
const modulePath = path.join(testModulePath, 'node_modules', 'farmhash');
1714
const rebuilderArgs = {

test/rebuild-napibuildversion.ts

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import * as fs from 'fs-extra';
2+
import * as path from 'path';
3+
4+
import { expect } from 'chai';
5+
import { rebuild } from '../lib/rebuild';
6+
import { getExactElectronVersionSync } from './helpers/electron-version';
7+
import { TIMEOUT_IN_MILLISECONDS, TEST_MODULE_PATH as testModulePath, cleanupTestModule, resetTestModule } from './helpers/module-setup';
8+
import { expectNativeModuleToBeRebuilt } from './helpers/rebuild';
9+
import detectLibc from 'detect-libc';
10+
11+
const testElectronVersion = getExactElectronVersionSync();
12+
13+
describe('rebuild with napi_build_versions in binary config', async function () {
14+
this.timeout(TIMEOUT_IN_MILLISECONDS);
15+
16+
const napiBuildVersion = 6;
17+
const napiBuildVersionSpecificPath = (arch: string, libc: string) => path.resolve(testModulePath, `node_modules/sqlite3/lib/binding/napi-v${ napiBuildVersion }-${ process.platform }-${ libc }-${ arch }/node_sqlite3.node`);
18+
19+
before(async () => {
20+
await resetTestModule(testModulePath, true, 'napi-build-version')
21+
// Forcing `msvs_version` needed in order for `arm64` `win32` binary to be built
22+
process.env.GYP_MSVS_VERSION = "2019"
23+
});
24+
after(() => cleanupTestModule(testModulePath));
25+
26+
// https://github.com/electron/rebuild/issues/554
27+
const archs = ['x64', 'arm64']
28+
for (const arch of archs) {
29+
it(`${ arch } arch should have rebuilt bianry with 'napi_build_versions' array and 'libc' provided`, async () => {
30+
const libc = await detectLibc.family() || 'unknown'
31+
const binaryPath = napiBuildVersionSpecificPath(arch, libc)
32+
33+
if (await fs.pathExists(binaryPath)) {
34+
fs.removeSync(binaryPath)
35+
}
36+
expect(await fs.pathExists(binaryPath)).to.be.false;
37+
38+
await rebuild({
39+
buildPath: testModulePath,
40+
electronVersion: testElectronVersion,
41+
arch
42+
});
43+
44+
await expectNativeModuleToBeRebuilt(testModulePath, 'sqlite3');
45+
expect(await fs.pathExists(binaryPath)).to.be.true;
46+
});
47+
}
48+
49+
});

test/rebuild-yarnworkspace.ts

+4-21
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,19 @@
1-
import * as fs from 'fs-extra';
21
import * as path from 'path';
3-
import * as os from 'os';
4-
import { spawn } from '@malept/cross-spawn-promise';
52

63
import { expectNativeModuleToBeRebuilt, expectNativeModuleToNotBeRebuilt } from './helpers/rebuild';
74
import { getExactElectronVersionSync } from './helpers/electron-version';
85
import { getProjectRootPath } from '../lib/search-module';
96
import { rebuild } from '../lib/rebuild';
7+
import { TIMEOUT_IN_MILLISECONDS, TEST_MODULE_PATH as testModulePath, cleanupTestModule, resetTestModule } from './helpers/module-setup';
108

119
const testElectronVersion = getExactElectronVersionSync();
1210

1311
describe('rebuild for yarn workspace', function() {
14-
this.timeout(2 * 60 * 1000);
15-
const testModulePath = path.resolve(os.tmpdir(), 'electron-rebuild-test');
16-
const msvs_version: string | undefined = process.env.GYP_MSVS_VERSION;
12+
this.timeout(TIMEOUT_IN_MILLISECONDS);
1713

1814
describe('core behavior', () => {
1915
before(async () => {
20-
await fs.remove(testModulePath);
21-
await fs.copy(path.resolve(__dirname, 'fixture/workspace-test'), testModulePath);
22-
23-
await spawn('yarn', [], { cwd: testModulePath });
24-
if (msvs_version) {
25-
process.env.GYP_MSVS_VERSION = msvs_version;
26-
}
27-
16+
await resetTestModule(testModulePath, true, 'workspace-test')
2817
const projectRootPath = await getProjectRootPath(path.join(testModulePath, 'workspace-test', 'child-workspace'));
2918

3019
await rebuild({
@@ -34,6 +23,7 @@ describe('rebuild for yarn workspace', function() {
3423
projectRootPath
3524
});
3625
});
26+
after(() => cleanupTestModule(testModulePath));
3727

3828
it('should have rebuilt top level prod dependencies', async () => {
3929
await expectNativeModuleToBeRebuilt(testModulePath, 'snappy');
@@ -42,12 +32,5 @@ describe('rebuild for yarn workspace', function() {
4232
it('should not have rebuilt top level devDependencies', async () => {
4333
await expectNativeModuleToNotBeRebuilt(testModulePath, 'sleep');
4434
});
45-
46-
after(async () => {
47-
await fs.remove(testModulePath);
48-
if (msvs_version) {
49-
process.env.GYP_MSVS_VERSION = msvs_version;
50-
}
51-
});
5235
});
5336
});

test/rebuild.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
import { expect } from 'chai';
22
import * as fs from 'fs-extra';
33
import * as path from 'path';
4-
import * as os from 'os';
54

6-
import { cleanupTestModule, MINUTES_IN_MILLISECONDS, resetMSVSVersion, resetTestModule, TIMEOUT_IN_MILLISECONDS } from './helpers/module-setup';
5+
import { cleanupTestModule, MINUTES_IN_MILLISECONDS, TEST_MODULE_PATH as testModulePath, resetMSVSVersion, resetTestModule, TIMEOUT_IN_MILLISECONDS } from './helpers/module-setup';
76
import { expectNativeModuleToBeRebuilt, expectNativeModuleToNotBeRebuilt } from './helpers/rebuild';
87
import { getExactElectronVersionSync } from './helpers/electron-version';
98
import { rebuild } from '../lib/rebuild';
109

1110
const testElectronVersion = getExactElectronVersionSync();
1211

1312
describe('rebuilder', () => {
14-
const testModulePath = path.resolve(os.tmpdir(), 'electron-rebuild-test');
1513

1614
describe('core behavior', function() {
1715
this.timeout(TIMEOUT_IN_MILLISECONDS);

0 commit comments

Comments
 (0)