diff --git a/scripts/prebuild.js b/scripts/prebuild.js index a8fc9302..e830ed61 100644 --- a/scripts/prebuild.js +++ b/scripts/prebuild.js @@ -4,22 +4,25 @@ const fs = require('fs'); const path = require('path'); /** - * This script copies the prebuilt binaries from the prebuild directory - * for the current platform and architecture to the build/Release directory. - * + * This script checks for the prebuilt binaries for the current platform and + * architecture. It exits with 0 if prebuilds are found and 1 if not. + * + * If npm_config_build_from_source is set then it removes the prebuilds for the + * current platform so they are not loaded at runtime. + * * Usage: * node scripts/prebuild.js */ +const PREBUILD_DIR = path.join(__dirname, '..', 'prebuilds', `${process.platform}-${process.arch}`); + // Skip copying prebuilds when npm_config_build_from_source is set if (process.env.npm_config_build_from_source === 'true') { - console.log('\x1b[33m> Skipping prebuild copy because npm_config_build_from_source is set\x1b[0m'); + console.log('\x1b[33m> Removing prebuilds and rebuilding because npm_config_build_from_source is set\x1b[0m'); + fs.rmSync(PREBUILD_DIR, { recursive: true }); process.exit(1); } -const PREBUILD_DIR = path.join(__dirname, '..', 'prebuilds', `${process.platform}-${process.arch}`); -const RELEASE_DIR = path.join(__dirname, '../build/Release'); - /* Copy prebuild files to build/Release */ console.log('\x1b[32m> Copying prebuilds to release folder...\x1b[0m'); if (!fs.existsSync(PREBUILD_DIR)) { @@ -27,4 +30,5 @@ if (!fs.existsSync(PREBUILD_DIR)) { // Exit with 1 to fall back on node-gyp building the native modules process.exit(1); } -fs.cpSync(PREBUILD_DIR, RELEASE_DIR, { recursive: true }); \ No newline at end of file +// Exit with 0 to skip node-gyp building from source +process.exit(0); diff --git a/src/conpty_console_list_agent.ts b/src/conpty_console_list_agent.ts index d7700cff..181ccabb 100644 --- a/src/conpty_console_list_agent.ts +++ b/src/conpty_console_list_agent.ts @@ -6,13 +6,9 @@ * single console attached to a process. */ -let getConsoleProcessList: any; -try { - getConsoleProcessList = require('../build/Release/conpty_console_list.node').getConsoleProcessList; -} catch (err) { - getConsoleProcessList = require('../build/Debug/conpty_console_list.node').getConsoleProcessList; -} +import { loadNativeModule } from './utils'; +const getConsoleProcessList = loadNativeModule('conpty_console_list').module.getConsoleProcessList; const shellPid = parseInt(process.argv[2], 10); const consoleProcessList = getConsoleProcessList(shellPid); process.send!({ consoleProcessList }); diff --git a/src/index.ts b/src/index.ts index 53d0322e..8a7e9505 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,6 +6,7 @@ import { ITerminal, IPtyOpenOptions, IPtyForkOptions, IWindowsPtyForkOptions } from './interfaces'; import { ArgvOrCommandLine } from './types'; +import { loadNativeModule } from './utils'; let terminalCtor: any; if (process.platform === 'win32') { @@ -48,4 +49,4 @@ export function open(options: IPtyOpenOptions): ITerminal { * Expose the native API when not Windows, note that this is not public API and * could be removed at any time. */ -export const native = (process.platform !== 'win32' ? require('../build/Release/pty.node') : null); +export const native = (process.platform !== 'win32' ? loadNativeModule('pty').module : null); diff --git a/src/unixTerminal.ts b/src/unixTerminal.ts index b745d762..05120dbd 100644 --- a/src/unixTerminal.ts +++ b/src/unixTerminal.ts @@ -9,24 +9,11 @@ import * as tty from 'tty'; import { Terminal, DEFAULT_COLS, DEFAULT_ROWS } from './terminal'; import { IProcessEnv, IPtyForkOptions, IPtyOpenOptions } from './interfaces'; import { ArgvOrCommandLine } from './types'; -import { assign } from './utils'; - -let pty: IUnixNative; -let helperPath: string; -try { - pty = require('../build/Release/pty.node'); - helperPath = '../build/Release/spawn-helper'; -} catch (outerError) { - try { - pty = require('../build/Debug/pty.node'); - helperPath = '../build/Debug/spawn-helper'; - } catch (innerError) { - console.error('innerError', innerError); - // Re-throw the exception from the Release require if the Debug require fails as well - throw outerError; - } -} +import { assign, loadNativeModule } from './utils'; +const native = loadNativeModule('pty'); +const pty: IUnixNative = native.module; +let helperPath = native.dir + '/spawn-helper'; helperPath = path.resolve(__dirname, helperPath); helperPath = helperPath.replace('app.asar', 'app.asar.unpacked'); helperPath = helperPath.replace('node_modules.asar', 'node_modules.asar.unpacked'); diff --git a/src/utils.ts b/src/utils.ts index 6306c8ba..81a70c77 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -7,3 +7,23 @@ export function assign(target: any, ...sources: any[]): any { sources.forEach(source => Object.keys(source).forEach(key => target[key] = source[key])); return target; } + + +export function loadNativeModule(name: string): {dir: string, module: any} { + // Check build, debug, and then prebuilds. + const dirs = ['build/Release', 'build/Debug', `prebuilds/${process.platform}-${process.arch}`]; + // Check relative to the parent dir for unbundled and then the current dir for bundled + const relative = ['..', '.']; + let lastError: unknown; + for (const d of dirs) { + for (const r of relative) { + const dir = `${r}/${d}/`; + try { + return { dir, module: require(`${dir}/${name}.node`) }; + } catch (e) { + lastError = e; + } + } + } + throw new Error(`Failed to load native module: ${name}.node, checked: ${dirs.join(', ')}: ${lastError}`); +} diff --git a/src/windowsPtyAgent.ts b/src/windowsPtyAgent.ts index ba5dbdbc..d7054449 100644 --- a/src/windowsPtyAgent.ts +++ b/src/windowsPtyAgent.ts @@ -11,6 +11,7 @@ import { fork } from 'child_process'; import { Socket } from 'net'; import { ArgvOrCommandLine } from './types'; import { ConoutConnection } from './windowsConoutConnection'; +import { loadNativeModule } from './utils'; let conptyNative: IConptyNative; let winptyNative: IWinptyNative; @@ -62,31 +63,11 @@ export class WindowsPtyAgent { } if (this._useConpty) { if (!conptyNative) { - try { - conptyNative = require('../build/Release/conpty.node'); - } catch (outerError) { - try { - conptyNative = require('../build/Debug/conpty.node'); - } catch (innerError) { - console.error('innerError', innerError); - // Re-throw the exception from the Release require if the Debug require fails as well - throw outerError; - } - } + conptyNative = loadNativeModule('conpty').module; } } else { if (!winptyNative) { - try { - winptyNative = require('../build/Release/pty.node'); - } catch (outerError) { - try { - winptyNative = require('../build/Debug/pty.node'); - } catch (innerError) { - console.error('innerError', innerError); - // Re-throw the exception from the Release require if the Debug require fails as well - throw outerError; - } - } + winptyNative = loadNativeModule('pty').module; } } this._ptyNative = this._useConpty ? conptyNative : winptyNative;