diff --git a/lib/create-config-gypi.js b/lib/create-config-gypi.js index 01a820e9f2..d471da5169 100644 --- a/lib/create-config-gypi.js +++ b/lib/create-config-gypi.js @@ -99,6 +99,11 @@ async function getCurrentConfigGypi ({ gyp, nodeDir, vsInfo, python }) { if (config.variables.clang === 1) { config.variables.clang = 0 } + // disable LTO for addon builds. node release builds may enable (thin) LTO, + // which leaks clang/lld-only flags like -flto=thin and /opt:lldltojobs into + // addons built with the default MSVC toolchain, which rejects those flags + variables.enable_lto = 'false' + variables.enable_thin_lto = 'false' } // loop through the rest of the opts and add the unknown ones as variables. diff --git a/test/fixtures/win-lto/include/node/config.gypi b/test/fixtures/win-lto/include/node/config.gypi new file mode 100644 index 0000000000..2e432eb842 --- /dev/null +++ b/test/fixtures/win-lto/include/node/config.gypi @@ -0,0 +1,8 @@ +# Test configuration simulating a Node.js Windows release built with Thin LTO +{ + 'variables': { + 'enable_lto': 'true', + 'enable_thin_lto': 'true', + 'lto_jobs': '2' + } +} diff --git a/test/test-create-config-gypi.js b/test/test-create-config-gypi.js index 3c77b87859..602fd3d678 100644 --- a/test/test-create-config-gypi.js +++ b/test/test-create-config-gypi.js @@ -52,6 +52,25 @@ describe('create-config-gypi', function () { assert.strictEqual(config.variables.build_with_electron, undefined) }) + it('config.gypi disables LTO for addon builds on Windows', async function () { + const nodeDir = path.join(__dirname, 'fixtures', 'win-lto') + + const prog = gyp() + prog.parseArgv(['_', '_', `--nodedir=${nodeDir}`]) + + const originalPlatform = process.platform + Object.defineProperty(process, 'platform', { value: 'win32' }) + try { + const config = await getCurrentConfigGypi({ gyp: prog, nodeDir, vsInfo: {} }) + // thin LTO leaks clang/lld-only flags into the MSVC addon build, so it + // must be disabled regardless of how node itself was built + assert.strictEqual(config.variables.enable_lto, 'false') + assert.strictEqual(config.variables.enable_thin_lto, 'false') + } finally { + Object.defineProperty(process, 'platform', { value: originalPlatform }) + } + }) + it('config.gypi parsing', function () { const str = "# Some comments\n{'variables': {'multiline': 'A'\n'B'}}" const config = parseConfigGypi(str)