Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: replacing macro {napi_build_version} in binary filename #1078

Merged
merged 16 commits into from
Apr 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/module-type/node-gyp/node-gyp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ export class NodeGyp extends NativeModule {

async buildArgsFromBinaryField(): Promise<string[]> {
const binary = await this.packageJSONFieldWithDefault('binary', {}) as Record<string, string>;
let napiBuildVersion: number | undefined = undefined
if (Array.isArray(binary.napi_versions)) {
napiBuildVersion = this.nodeAPI.getNapiVersion(binary.napi_versions.map(str => Number(str)))
}
const flags = await Promise.all(Object.entries(binary).map(async ([binaryKey, binaryValue]) => {
if (binaryKey === 'napi_versions') {
return;
Expand All @@ -66,7 +70,9 @@ export class NodeGyp extends NativeModule {
.replace('{arch}', this.rebuilder.arch)
.replace('{version}', await this.packageJSONField('version') as string)
.replace('{libc}', await detectLibc.family() || 'unknown');

if (napiBuildVersion !== undefined) {
value = value.replace('{napi_build_version}', napiBuildVersion.toString())
}
for (const [replaceKey, replaceValue] of Object.entries(binary)) {
value = value.replace(`{${replaceKey}}`, replaceValue);
}
Expand Down
13 changes: 13 additions & 0 deletions test/fixture/napi-build-version/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "workspace-app",
"productName": "Workspace App",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"sqlite3": "5.1.6"
}
}
11 changes: 5 additions & 6 deletions test/helpers/module-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const TIMEOUT_IN_MINUTES = process.platform === 'win32' ? 5 : 2;
export const MINUTES_IN_MILLISECONDS = 60 * 1000;
export const TIMEOUT_IN_MILLISECONDS = TIMEOUT_IN_MINUTES * MINUTES_IN_MILLISECONDS;

export const TEST_MODULE_PATH = path.resolve(os.tmpdir(), 'electron-rebuild-test');

export function resetMSVSVersion(): void {
if (originalGypMSVSVersion) {
process.env.GYP_MSVS_VERSION = originalGypMSVSVersion;
Expand All @@ -18,14 +20,11 @@ export function resetMSVSVersion(): void {

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

export async function resetTestModule(testModulePath: string, installModules = true): Promise<void> {
const oneTimeModulePath = path.resolve(testModuleTmpPath, `${crypto.createHash('SHA1').update(testModulePath).digest('hex')}-${installModules}`);
export async function resetTestModule(testModulePath: string, installModules = true, fixtureName = 'native-app1'): Promise<void> {
const oneTimeModulePath = path.resolve(testModuleTmpPath, `${crypto.createHash('SHA1').update(testModulePath).digest('hex')}-${fixtureName}-${installModules}`);
if (!await fs.pathExists(oneTimeModulePath)) {
await fs.mkdir(oneTimeModulePath, { recursive: true });
await fs.copyFile(
path.resolve(__dirname, '../../test/fixture/native-app1/package.json'),
path.resolve(oneTimeModulePath, 'package.json')
);
await fs.copy(path.resolve(__dirname, `../../test/fixture/${ fixtureName }`), oneTimeModulePath);
if (installModules) {
await spawn('yarn', ['install'], { cwd: oneTimeModulePath });
}
Expand Down
5 changes: 1 addition & 4 deletions test/module-type-node-gyp.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { EventEmitter } from 'events';
import { expect } from 'chai';
import os from 'os';
import path from 'path';

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

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

before(async () => await resetTestModule(testModulePath, false));
after(async () => await cleanupTestModule(testModulePath));
Expand Down
5 changes: 1 addition & 4 deletions test/module-type-prebuild-install.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import chai, { expect } from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { EventEmitter } from 'events';
import os from 'os';
import path from 'path';

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

chai.use(chaiAsPromised);

const testModulePath = path.resolve(os.tmpdir(), 'electron-rebuild-test');

describe('prebuild-install', () => {
const modulePath = path.join(testModulePath, 'node_modules', 'farmhash');
const rebuilderArgs = {
Expand Down
49 changes: 49 additions & 0 deletions test/rebuild-napibuildversion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import * as fs from 'fs-extra';
import * as path from 'path';

import { expect } from 'chai';
import { rebuild } from '../lib/rebuild';
import { getExactElectronVersionSync } from './helpers/electron-version';
import { TIMEOUT_IN_MILLISECONDS, TEST_MODULE_PATH as testModulePath, cleanupTestModule, resetTestModule } from './helpers/module-setup';
import { expectNativeModuleToBeRebuilt } from './helpers/rebuild';
import detectLibc from 'detect-libc';

const testElectronVersion = getExactElectronVersionSync();

describe('rebuild with napi_build_versions in binary config', async function () {
this.timeout(TIMEOUT_IN_MILLISECONDS);

const napiBuildVersion = 6;
const napiBuildVersionSpecificPath = (arch: string, libc: string) => path.resolve(testModulePath, `node_modules/sqlite3/lib/binding/napi-v${ napiBuildVersion }-${ process.platform }-${ libc }-${ arch }/node_sqlite3.node`);

before(async () => {
await resetTestModule(testModulePath, true, 'napi-build-version')
// Forcing `msvs_version` needed in order for `arm64` `win32` binary to be built
process.env.GYP_MSVS_VERSION = "2019"
});
after(() => cleanupTestModule(testModulePath));

// https://github.com/electron/rebuild/issues/554
const archs = ['x64', 'arm64']
for (const arch of archs) {
it(`${ arch } arch should have rebuilt bianry with 'napi_build_versions' array and 'libc' provided`, async () => {
const libc = await detectLibc.family() || 'unknown'
const binaryPath = napiBuildVersionSpecificPath(arch, libc)

if (await fs.pathExists(binaryPath)) {
fs.removeSync(binaryPath)
}
expect(await fs.pathExists(binaryPath)).to.be.false;

await rebuild({
buildPath: testModulePath,
electronVersion: testElectronVersion,
arch
});

await expectNativeModuleToBeRebuilt(testModulePath, 'sqlite3');
expect(await fs.pathExists(binaryPath)).to.be.true;
});
}

});
25 changes: 4 additions & 21 deletions test/rebuild-yarnworkspace.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,19 @@
import * as fs from 'fs-extra';
import * as path from 'path';
import * as os from 'os';
import { spawn } from '@malept/cross-spawn-promise';

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

const testElectronVersion = getExactElectronVersionSync();

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

describe('core behavior', () => {
before(async () => {
await fs.remove(testModulePath);
await fs.copy(path.resolve(__dirname, 'fixture/workspace-test'), testModulePath);

await spawn('yarn', [], { cwd: testModulePath });
if (msvs_version) {
process.env.GYP_MSVS_VERSION = msvs_version;
}

await resetTestModule(testModulePath, true, 'workspace-test')
const projectRootPath = await getProjectRootPath(path.join(testModulePath, 'workspace-test', 'child-workspace'));

await rebuild({
Expand All @@ -34,6 +23,7 @@ describe('rebuild for yarn workspace', function() {
projectRootPath
});
});
after(() => cleanupTestModule(testModulePath));

it('should have rebuilt top level prod dependencies', async () => {
await expectNativeModuleToBeRebuilt(testModulePath, 'snappy');
Expand All @@ -42,12 +32,5 @@ describe('rebuild for yarn workspace', function() {
it('should not have rebuilt top level devDependencies', async () => {
await expectNativeModuleToNotBeRebuilt(testModulePath, 'sleep');
});

after(async () => {
await fs.remove(testModulePath);
if (msvs_version) {
process.env.GYP_MSVS_VERSION = msvs_version;
}
});
});
});
4 changes: 1 addition & 3 deletions test/rebuild.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { expect } from 'chai';
import * as fs from 'fs-extra';
import * as path from 'path';
import * as os from 'os';

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

const testElectronVersion = getExactElectronVersionSync();

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

describe('core behavior', function() {
this.timeout(TIMEOUT_IN_MILLISECONDS);
Expand Down