Skip to content

Commit

Permalink
win: refactor ENV resolution for self application
Browse files Browse the repository at this point in the history
We resolve the ENV variables early and apply to process
in order for `which` to properly work
  • Loading branch information
refack committed Feb 6, 2017
1 parent 7fc6054 commit ea66223
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 49 deletions.
7 changes: 7 additions & 0 deletions lib/gyp.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
72 changes: 33 additions & 39 deletions lib/gyp/platform/win.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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();

Expand All @@ -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) {
Expand All @@ -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
Expand All @@ -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;
};

30 changes: 20 additions & 10 deletions test/platform-win-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
);
}
});
});
}
Expand Down

0 comments on commit ea66223

Please sign in to comment.