Skip to content

Commit

Permalink
patch: remove native modules from gui
Browse files Browse the repository at this point in the history
  • Loading branch information
aethernet committed Sep 27, 2023
1 parent d4fb075 commit 3f556ea
Showing 1 changed file with 1 addition and 201 deletions.
202 changes: 1 addition & 201 deletions webpack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@
*/

import * as CopyPlugin from 'copy-webpack-plugin';
import { readdirSync } from 'fs';
import * as _ from 'lodash';
import * as os from 'os';
import outdent from 'outdent';
import * as path from 'path';
import { env } from 'process';
import * as SimpleProgressWebpackPlugin from 'simple-progress-webpack-plugin';
import * as TerserPlugin from 'terser-webpack-plugin';
import {
Expand Down Expand Up @@ -48,24 +44,6 @@ function externalPackageJson(packageJsonPath: string) {
};
}

function platformSpecificModule(
platform: string,
module: string,
replacement = '{}',
) {
// Resolves module on platform, otherwise resolves the replacement
return (
{ request }: { context: string; request: string },
callback: (error?: Error, result?: string, type?: string) => void,
) => {
if (request === module && os.platform() !== platform) {
callback(undefined, replacement);
return;
}
callback();
};
}

function renameNodeModules(resourcePath: string) {
// electron-builder excludes the node_modules folder even if you specifically include it
// Work around by renaming it to "modules"
Expand All @@ -74,80 +52,11 @@ function renameNodeModules(resourcePath: string) {
path
.relative(__dirname, resourcePath)
.replace('node_modules', 'modules')
// use the same name on all architectures so electron-builder can build a universal dmg on mac
.replace(LZMA_BINDINGS_FOLDER, LZMA_BINDINGS_FOLDER_RENAMED)
// file-loader expects posix paths, even on Windows
.replace(/\\/g, '/')
);
}

function findUsbPrebuild(): string[] {
const usbPrebuildsFolder = path.join('node_modules', 'usb', 'prebuilds');
const prebuildFolders = readdirSync(usbPrebuildsFolder);
let bindingFile: string | undefined = 'node.napi.node';
const platformFolder = prebuildFolders.find(
(f) => f.startsWith(os.platform()) && f.indexOf(os.arch()) > -1,
);
if (platformFolder === undefined) {
throw new Error(
'Could not find usb prebuild. Should try fallback to node-gyp and use /build/Release instead of /prebuilds',
);
}

const bindingFiles = readdirSync(
path.join(usbPrebuildsFolder, platformFolder),
)?.filter((f) => f.endsWith('.node'));

console.log(bindingFiles);

if (!bindingFiles.length) {
throw new Error('Could not find usb prebuild for platform');
}

if (bindingFiles.length === 1) {
bindingFile = bindingFiles[0];
}

// armv6 vs v7 in linux-arm and
// glibc vs musl in linux-x64
if (bindingFiles.length > 1) {
bindingFile = bindingFiles.find((file) => {
if (bindingFiles.indexOf('arm') > -1) {
const process = require('process');
return file.indexOf(process.config.variables.arm_version) > -1;
} else {
return file.indexOf('glibc') > -1;
}
});
}

if (bindingFile === undefined) {
throw new Error('Could not find usb prebuild for platform');
}

return [platformFolder, bindingFile];
}

const [USB_BINDINGS_FOLDER, USB_BINDINGS_FILE] = findUsbPrebuild();

function findLzmaNativeBindingsFolder(): string {
const files = readdirSync(
path.join('node_modules', 'lzma-native', 'prebuilds'),
);
const bindingsFolder = files.find(
(f) =>
f.startsWith(os.platform()) &&
f.endsWith(env.npm_config_target_arch || os.arch()),
);
if (bindingsFolder === undefined) {
throw new Error('Could not find lzma_native binding');
}
return bindingsFolder;
}

const LZMA_BINDINGS_FOLDER = findLzmaNativeBindingsFolder();
const LZMA_BINDINGS_FOLDER_RENAMED = 'binding';

interface ReplacementRule {
search: string;
replace: string | (() => string);
Expand Down Expand Up @@ -224,94 +133,10 @@ const commonConfig = {
search: './adapters/xhr',
replace: './adapters/http',
}),
// remove bindings magic from drivelist
replace(
/node_modules\/drivelist\/js\/index\.js$/,
{
search: 'require("bindings");',
replace: "require('../build/Release/drivelist.node')",
},
{
search: "bindings('drivelist')",
replace: 'bindings',
},
),
replace(
/node_modules\/lzma-native\/index\.js$/,
// remove node-pre-gyp magic from lzma-native
{
search: `require('node-gyp-build')(__dirname);`,
replace: `require('./prebuilds/${LZMA_BINDINGS_FOLDER}/electron.napi.node')`,
},
// use regular stream module instead of readable-stream
{
search: "var stream = require('readable-stream');",
replace: "var stream = require('stream');",
},
),
// remove node-pre-gyp magic from usb
replace(/node_modules\/usb\/dist\/usb\/bindings\.js$/, {
search: `require('node-gyp-build')(path_1.join(__dirname, '..', '..'));`,
replace: `require('../../prebuilds/${USB_BINDINGS_FOLDER}/${USB_BINDINGS_FILE}')`,
}),
// remove bindings magic from mountutils
replace(/node_modules\/mountutils\/index\.js$/, {
search: outdent`
require('bindings')({
bindings: 'MountUtils',
/* eslint-disable camelcase */
module_root: __dirname
/* eslint-enable camelcase */
})
`,
replace: "require('./build/Release/MountUtils.node')",
}),
// remove bindings magic from winusb-driver-generator
replace(/node_modules\/winusb-driver-generator\/index\.js$/, {
search: outdent`
require('bindings')({
bindings: 'Generator',
/* eslint-disable camelcase */
module_root: __dirname
/* eslint-enable camelcase */
});
`,
replace: "require('./build/Release/Generator.node')",
}),
replace(/node_modules\/node-raspberrypi-usbboot\/build\/index\.js$/, {
search:
"return await readFile(Path.join(__dirname, '..', 'blobs', filename));",
replace: outdent`
const remote = require('@electron/remote');
return await readFile(
Path.join(
// With macOS universal builds, getAppPath() returns the path to an app.asar file containing an index.js file which will
// include the app-x64 or app-arm64 folder depending on the arch.
// We don't care about the app.asar file, we want the actual folder.
remote.app.getAppPath().replace(/\\.asar$/, () => process.platform === 'darwin' ? '-' + process.arch : ''),
'generated',
__dirname.replace('node_modules', 'modules'),
'..',
'blobs',
filename
)
);
`,
}),
// Copy native modules to generated folder
{
test: /\.node$/,
use: [
{
loader: 'native-addon-loader',
options: { name: renameNodeModules },
},
],
},
],
},
resolve: {
extensions: ['.node', '.js', '.json', '.ts', '.tsx'],
extensions: ['.js', '.json', '.ts', '.tsx'],
},
plugins: [
PnpWebpackPlugin,
Expand Down Expand Up @@ -343,32 +168,9 @@ const commonConfig = {
externals: [
// '../package.json' because we are in 'generated'
externalPackageJson('../package.json'),
// Only exists on windows
platformSpecificModule('win32', 'winusb-driver-generator'),
// Not needed but required by resin-corvus > os-locale > execa > cross-spawn
platformSpecificModule('none', 'spawn-sync'),
// Not needed as we replace all requires for it
platformSpecificModule('none', 'node-pre-gyp', '{ find: () => {} }'),
// Not needed as we replace all requires for it
platformSpecificModule('none', 'bindings'),
],
};

const guiConfigCopyPatterns = [
{
from: 'node_modules/node-raspberrypi-usbboot/blobs',
to: 'modules/node-raspberrypi-usbboot/blobs',
},
];

if (os.platform() === 'win32') {
// liblzma.dll is required on Windows for lzma-native
guiConfigCopyPatterns.push({
from: `node_modules/lzma-native/prebuilds/${LZMA_BINDINGS_FOLDER}/liblzma.dll`,
to: `modules/lzma-native/prebuilds/${LZMA_BINDINGS_FOLDER_RENAMED}/liblzma.dll`,
});
}

const guiConfig = {
...commonConfig,
target: 'electron-renderer',
Expand All @@ -379,7 +181,6 @@ const guiConfig = {
entry: {
gui: path.join(__dirname, 'lib', 'gui', 'app', 'renderer.ts'),
},
// entry: path.join(__dirname, 'lib', 'gui', 'app', 'renderer.ts'),
plugins: [
...commonConfig.plugins,
new CopyPlugin({
Expand All @@ -395,7 +196,6 @@ const guiConfig = {
banner: '__REACT_DEVTOOLS_GLOBAL_HOOK__ = { isDisabled: true };',
raw: true,
}),
new CopyPlugin({ patterns: guiConfigCopyPatterns }),
],
};

Expand Down

0 comments on commit 3f556ea

Please sign in to comment.