diff --git a/addon.gypi b/addon.gypi index 6b4641b693..e8b95c5501 100644 --- a/addon.gypi +++ b/addon.gypi @@ -1,6 +1,7 @@ { 'variables' : { 'node_engine_include_dir%': 'deps/v8/include', + 'node_host_binary%': 'node' }, 'target_defaults': { 'type': 'loadable_module', @@ -70,12 +71,13 @@ # is named node.exe, iojs.exe, or something else. 'conditions': [ [ 'OS=="win"', { + 'defines': [ 'HOST_BINARY=\"<(node_host_binary)<(EXECUTABLE_SUFFIX)\"', ], 'sources': [ '<(node_gyp_dir)/src/win_delay_load_hook.cc', ], 'msvs_settings': { 'VCLinkerTool': { - 'DelayLoadDLLs': [ 'iojs.exe', 'node.exe' ], + 'DelayLoadDLLs': [ '<(node_host_binary)<(EXECUTABLE_SUFFIX)' ], # Don't print a linker warning when no imports from either .exe # are used. 'AdditionalOptions': [ '/ignore:4199' ], diff --git a/src/win_delay_load_hook.cc b/src/win_delay_load_hook.cc index e75954b605..5e7f14b2b2 100644 --- a/src/win_delay_load_hook.cc +++ b/src/win_delay_load_hook.cc @@ -1,10 +1,10 @@ /* * When this file is linked to a DLL, it sets up a delay-load hook that - * intervenes when the DLL is trying to load 'node.exe' or 'iojs.exe' - * dynamically. Instead of trying to locate the .exe file it'll just return - * a handle to the process image. + * intervenes when the DLL is trying to load the host executable + * dynamically. Instead of trying to locate the .exe file it'll just + * return a handle to the process image. * - * This allows compiled addons to work when node.exe or iojs.exe is renamed. + * This allows compiled addons to work when the host executable is renamed. */ #ifdef _MSC_VER @@ -23,8 +23,7 @@ static FARPROC WINAPI load_exe_hook(unsigned int event, DelayLoadInfo* info) { if (event != dliNotePreLoadLibrary) return NULL; - if (_stricmp(info->szDll, "iojs.exe") != 0 && - _stricmp(info->szDll, "node.exe") != 0) + if (_stricmp(info->szDll, HOST_BINARY) != 0) return NULL; m = GetModuleHandle(NULL); diff --git a/test/test-addon.js b/test/test-addon.js index 89350effc4..900b0b049d 100644 --- a/test/test-addon.js +++ b/test/test-addon.js @@ -4,14 +4,19 @@ var test = require('tape') var path = require('path') var fs = require('graceful-fs') var child_process = require('child_process') +var os = require('os') var addonPath = path.resolve(__dirname, 'node_modules', 'hello_world') var nodeGyp = path.resolve(__dirname, '..', 'bin', 'node-gyp.js') var execFileSync = child_process.execFileSync || require('./process-exec-sync') var execFile = child_process.execFile -function runHello() { +function runHello(hostProcess) { + if (!hostProcess) { + hostProcess = process.execPath + } var testCode = "console.log(require('hello_world').hello())" - return execFileSync(process.execPath, ['-e', testCode], { cwd: __dirname }).toString() + console.log('running ', hostProcess); + return execFileSync(hostProcess, ['-e', testCode], { cwd: __dirname }).toString() } function getEncoding() { @@ -111,3 +116,29 @@ test('build simple addon in path with non-ascii characters', function (t) { proc.stdout.setEncoding('utf-8') proc.stderr.setEncoding('utf-8') }) + +test('addon works with renamed host executable', function (t) { + // No `fs.copyFileSync` before node8. + if (process.version.substr(1).split('.')[0] < 8) { + t.skip("skipping test for old node version"); + t.end(); + return; + } + + t.plan(3) + + var notNodePath = path.join(os.tmpdir(), 'notnode' + path.extname(process.execPath)) + fs.copyFileSync(process.execPath, notNodePath) + + var cmd = [nodeGyp, 'rebuild', '-C', addonPath, '--loglevel=verbose'] + var proc = execFile(process.execPath, cmd, function (err, stdout, stderr) { + var logLines = stderr.toString().trim().split(/\r?\n/) + var lastLine = logLines[logLines.length-1] + t.strictEqual(err, null) + t.strictEqual(lastLine, 'gyp info ok', 'should end in ok') + t.strictEqual(runHello(notNodePath).trim(), 'world') + fs.unlinkSync(notNodePath) + }) + proc.stdout.setEncoding('utf-8') + proc.stderr.setEncoding('utf-8') +})