diff --git a/lib/gyp.js b/lib/gyp.js index 623bd7c..666844d 100644 --- a/lib/gyp.js +++ b/lib/gyp.js @@ -376,6 +376,13 @@ gyp.main = function main(args, extra) { const targets = loadRes.targets; const data = loadRes.data; + if (process.platform === 'win32') { + const someTarget = targets[flatList[0]]; + const someConfig = someTarget.configurations[someTarget.default_configuration]; + params['target_arch'] = params['target_arch'] || someConfig.msvs_configuration_platform || 'ia32'; + gyp.platform.win.setEnvironment(params['target_arch']); + } + /* TODO(mark): Pass |data| for now because the generator needs a list of * build files that came in. In the future, maybe it should just accept * a list, and not the whole data dict. diff --git a/lib/gyp/platform/win.js b/lib/gyp/platform/win.js index 73a0a02..0cc012b 100644 --- a/lib/gyp/platform/win.js +++ b/lib/gyp/platform/win.js @@ -8,10 +8,7 @@ const process = gyp.bindings.process; const win = exports; win.ninjaRules = function ninjaRules(n, outDir, generatorFlags, params) { - let envFile = win.genEnvironment( - outDir, - generatorFlags['msvs_version'] || 'auto', - params['target_arch'] || 'ia32'); + let envFile = win.genEnvironment(outDir, params['target_arch'] || 'ia32'); if (envFile) envFile = ` -e ${envFile} `; else @@ -365,17 +362,12 @@ win.detectVersion = function detectVersion() { }; const IMPORTANT_VARS = - /^(include|lib|libpath|path|pathext|systemroot|temp|tmp)=(.*)$/i; + /^include|lib|libpath|path|pathext|systemroot|temp|tmp/i; -function formatEnvBlock(lines) { - let res = ''; - lines.forEach((line) => { - const match = line.match(IMPORTANT_VARS); - if (match === null) - return; - - res += match[1].toUpperCase() + '=' + match[2] + '\0'; - }); +function formatEnvBlock() { + const res = Object.keys(process.env) + .filter(key => key.match(IMPORTANT_VARS)) + .reduce((agg, key) => agg + key.toUpperCase() + '=' + process.env[key] + '\0', ''); return res; } @@ -409,7 +401,7 @@ win.getOSBits = function getOSBits() { return 32; }; -win.genEnvironment = function genEnvironment(outDir, version, arch) { +win.resolveDevEnvironment = function resolveDevEnvironment(target_arch) { const env = process.env; const bits = win.getOSBits(); @@ -424,7 +416,7 @@ win.genEnvironment = function genEnvironment(outDir, version, arch) { return s; }, {}); const VsDevCmd = path.join(vsSetup.InstallationPath, 'Common7', 'Tools', 'VsDevCmd.bat'); - const argArch = arch === 'x64' ? 'amd64' : 'x86'; + const argArch = target_arch === 'x64' ? 'amd64' : 'x86'; const argHost = bits === 64 ? 'amd64' : 'x86'; return `${VsDevCmd} -arch=${argArch} -host_arch=${argHost} -no_logo`; } catch (e) { @@ -434,6 +426,7 @@ win.genEnvironment = function genEnvironment(outDir, version, arch) { function findVcVarsFile() { // NOTE: Largely inspired by MSVSVersion.py + let version = win.getMSVSVersion(); let tools; // Try to find a MSVS installation @@ -453,53 +446,54 @@ win.genEnvironment = function genEnvironment(outDir, version, arch) { // TODO(indutny): does it work with MSVS Express? if (version === 'auto') { - gyp.bindings.error('No Visual Studio found. When building - please ' + + throw new Error('No Visual Studio found. When building - please ' + 'run `ninja` from the MSVS console'); - return; } - let vcvars; + let vcEnvCmd; // TODO(indutny): proper escape for the .bat file - if (arch === 'ia32') { + if (target_arch === 'ia32') { if (bits === 64) - vcvars = '"' + path.join(tools, 'VC', 'vcvarsall.bat') + '" amd64_x86'; + vcEnvCmd = '"' + path.join(tools, 'VC', 'vcvarsall.bat') + '" amd64_x86'; else - vcvars = '"' + path.join(tools, 'Common7', 'Tools', 'vsvars32.bat') + '"'; - } else if (arch === 'x64') { + vcEnvCmd = '"' + path.join(tools, 'Common7', 'Tools', 'vsvars32.bat') + '"'; + } else if (target_arch === 'x64') { let arg; if (bits === 64) arg = 'amd64'; else arg = 'x86_amd64'; - vcvars = '"' + path.join(tools, 'VC', 'vcvarsall.bat') + '" ' + arg; + vcEnvCmd = '"' + path.join(tools, 'VC', 'vcvarsall.bat') + '" ' + arg; } else { - throw new Error(`Arch: '${arch}' is not supported on windows`); + throw new Error(`Arch: '${target_arch}' is not supported on windows`); } - return vcvars; + return vcEnvCmd; } - const vcvars = tryVS7() || findVcVarsFile(); - if (!vcvars) { - return; - } - - let lines; + const vcEnvCmd = tryVS7() || findVcVarsFile(); + let lines = []; try { - lines = gyp.bindings.execSync(`${vcvars} & set`, { env: {} }).toString() + lines = gyp.bindings.execSync(`${vcEnvCmd} & set`, {env: {}}).toString() .trim().split(/\r\n/g); } catch (e) { gyp.bindings.error(e.message); - return; } + return lines; +}; +win.setEnvironment = function setEnvironment(target_arch) { + const lines = win.resolveDevEnvironment(target_arch); + lines.forEach(l => { + const kv = l.split('='); + process.env[kv[0]] = kv[1]; + }); +}; - if (!outDir) { - return lines; - } - - const envBlock = formatEnvBlock(lines); +win.genEnvironment = function genEnvironment(outDir, arch) { + const envBlock = formatEnvBlock(); const envFile = 'environment.' + arch; fs.writeFileSync(path.join(outDir, envFile), envBlock); return envFile; }; + diff --git a/test/platform-win-test.js b/test/platform-win-test.js index a569d07..6cac22a 100644 --- a/test/platform-win-test.js +++ b/test/platform-win-test.js @@ -229,20 +229,30 @@ describe('gyp.platform.win', () => { describe('genEnvironment', function () { this.timeout(20000); it('resolve for x64', () => { - const env = win.genEnvironment(null, 'auto', 'x64'); + const env = win.resolveDevEnvironment('x64'); assert(env, 'didn\'t get ENVIRONMENT :('); - assert.equal(env.find(l => l.includes('ARG_TGT_ARCH')), 'VSCMD_ARG_TGT_ARCH=x64'); - assert.equal(env.pop().split('=')[0], '__VSCMD_PREINIT_PATH', - 'Last env var should be __VSCMD_PREINIT_PATH' - ); + const COMNTOOLS = env.find(l => l.includes('COMNTOOLS')); + assert(COMNTOOLS, 'didn\'t get COMNTOOLS :('); + if (COMNTOOLS.includes('VS150COMNTOOLS')){ + assert.equal(env.find(l => l.includes('ARG_TGT_ARCH')), 'VSCMD_ARG_TGT_ARCH=x64'); + assert.equal(env.find(l => l.includes('VisualStudioVersion')), 'VisualStudioVersion=15.0'); + assert.equal(env.pop().split('=')[0], '__VSCMD_PREINIT_PATH', + 'Last env var should be __VSCMD_PREINIT_PATH' + ); + } }); it('resolve for x86', () => { - const env = win.genEnvironment(null, 'auto', 'x86'); + const env = win.resolveDevEnvironment('x86'); assert(env, 'didn\'t get ENVIRONMENT :('); - assert.equal(env.find(l => l.includes('ARG_TGT_ARCH')), 'VSCMD_ARG_TGT_ARCH=x86'); - assert.equal(env.pop().split('=')[0], '__VSCMD_PREINIT_PATH', - 'Last env var should be __VSCMD_PREINIT_PATH' - ); + const COMNTOOLS = env.find(l => l.includes('COMNTOOLS')); + assert(COMNTOOLS, 'didn\'t get COMNTOOLS :('); + if (COMNTOOLS.includes('VS150COMNTOOLS')) { + assert.equal(env.find(l => l.includes('ARG_TGT_ARCH')), 'VSCMD_ARG_TGT_ARCH=x86'); + assert.equal(env.find(l => l.includes('VisualStudioVersion')), 'VisualStudioVersion=15.0'); + assert.equal(env.pop().split('=')[0], '__VSCMD_PREINIT_PATH', + 'Last env var should be __VSCMD_PREINIT_PATH' + ); + } }); }); }