| Index: build/toolchain/win/setup_toolchain.py
|
| diff --git a/build/toolchain/win/setup_toolchain.py b/build/toolchain/win/setup_toolchain.py
|
| index 1e20387b0b240e987b22e85898c9368d8b0b0b9a..3fd21ea832f386083a748fc389f4beb407fe6eb9 100644
|
| --- a/build/toolchain/win/setup_toolchain.py
|
| +++ b/build/toolchain/win/setup_toolchain.py
|
| @@ -49,10 +49,11 @@ def _ExtractImportantEnvironment(output_of_set):
|
| setting = os.path.dirname(sys.executable) + os.pathsep + setting
|
| env[var.upper()] = setting
|
| break
|
| - for required in ('SYSTEMROOT', 'TEMP', 'TMP'):
|
| - if required not in env:
|
| - raise Exception('Environment variable "%s" '
|
| - 'required to be set to valid path' % required)
|
| + if sys.platform in ('win32', 'cygwin'):
|
| + for required in ('SYSTEMROOT', 'TEMP', 'TMP'):
|
| + if required not in env:
|
| + raise Exception('Environment variable "%s" '
|
| + 'required to be set to valid path' % required)
|
| return env
|
|
|
|
|
| @@ -67,35 +68,93 @@ def _DetectVisualStudioPath():
|
| return vs_toolchain.DetectVisualStudioPath()
|
|
|
|
|
| -def _SetupScript(target_cpu, sdk_dir):
|
| - """Returns a command (with arguments) to be used to set up the
|
| - environment."""
|
| +def _InterpretBatFile(batpath, env):
|
| + """Interprets a simple .bat file consisting of set, if, and goto statements,
|
| + reading and writing variables to and from |env|."""
|
| + var_re = re.compile(r'%'
|
| + r'(?P<mods>~(?:[fdpnxsatz]|\$[^:]*:)*)?'
|
| + r'(?P<name>[0-9]|[a-zA-Z][a-zA-Z0-9]*%|%|\*)')
|
| + def _ExpandVar(m):
|
| + name = m.group('name')
|
| + if name == '%': return '%'
|
| + if name == '*' or ':' in name:
|
| + raise ValueError("'%s' variable interpolation not implemented" % name);
|
| + if name[-1] == '%': name = name[:-1]
|
| + replacement = env.get(name, '')
|
| + mods = m.group('mods')
|
| + if mods and len(mods) > 1:
|
| + assert mods[0] == '~'
|
| + replacement, mod_index = '', 1
|
| + while mod_index < len(mods):
|
| + if mods[mod_index] == 'd':
|
| + replacement += os.path.splitdrive(env.get(name, ''))[0]
|
| + elif mods[mod_index] == 'p':
|
| + replacement += os.path.dirname(env.get(name, '')) + os.path.sep
|
| + else:
|
| + raise ValueError("modifier '%s' not implemented" % mods[mod_index])
|
| + mod_index += 1
|
| + return replacement
|
| + with open(batpath) as f:
|
| + for l in f:
|
| + l = l.strip()
|
| + if l.startswith('@echo'): continue
|
| + if l.startswith('::'): continue
|
| + l = re.sub(var_re, _ExpandVar, l)
|
| + if l.startswith('set '):
|
| + key, val = l[len('set '):].split('=', 1)
|
| + # clang-cl wants include and lib separated by ';'s,
|
| + # but PATH is of course separated by :
|
| + env[key] = val.replace('\\', os.path.sep)
|
| + if key == 'PATH': env[key] = env[key].replace(';', os.path.pathsep)
|
| + continue
|
| + if l.startswith('if '):
|
| + if 'else' in l: raise ValueError('else not implemented')
|
| + m = re.match(r'if\s+(?P<lhs>"[^"]*")\s*==\s*(?P<rhs>"[^"]*")\s*'
|
| + r'(?P<body>[^(]*)$', l)
|
| + if not m: raise ValueError('only very limited if statement support')
|
| + if m.group('rhs') != m.group('lhs'): continue # if condition false: skip
|
| + l = m.group('body')
|
| + # fall through
|
| + if l.startswith('goto'):
|
| + label = re.match(r'goto\s*(?P<label>\S*)', l).group('label')
|
| + if label.upper() == ':EOF': break
|
| + l = next(f)
|
| + while l.strip() != ':' + label:
|
| + l = next(f)
|
| + continue
|
| + raise ValueError('unimplemented bat statement "%s"' % l)
|
| +
|
| +
|
| +def _LoadToolchainEnv(cpu, sdk_dir):
|
| + """Returns a dictionary with environment variables that must be set while
|
| + running binaries from the toolchain (e.g. INCLUDE and PATH for cl.exe)."""
|
| # Check if we are running in the SDK command line environment and use
|
| - # the setup script from the SDK if so. |target_cpu| should be either
|
| - # 'x86' or 'x64'.
|
| - assert target_cpu in ('x86', 'x64')
|
| + # the setup script from the SDK if so. |cpu| should be either 'x86' or 'x64'.
|
| + assert cpu in ('x86', 'x64')
|
| if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', 1))) and sdk_dir:
|
| - return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')),
|
| - '/' + target_cpu]
|
| + script = os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd'))
|
| + # SetEnv.Cmd is fairly simple and controlled by us. Run it through a
|
| + # manual simple bat parser, which also runs on non-Windows hosts.
|
| + env = dict(os.environ)
|
| + env['0'] = script
|
| + env['1'] = '/' + cpu
|
| + _InterpretBatFile(script, env)
|
| + variables = '\n'.join(['%s=%s' % (k, v) for k, v in env.iteritems()])
|
| else:
|
| if 'GYP_MSVS_OVERRIDE_PATH' not in os.environ:
|
| os.environ['GYP_MSVS_OVERRIDE_PATH'] = _DetectVisualStudioPath()
|
| # We only support x64-hosted tools.
|
| - return [os.path.normpath(os.path.join(os.environ['GYP_MSVS_OVERRIDE_PATH'],
|
| + args = [os.path.normpath(os.path.join(os.environ['GYP_MSVS_OVERRIDE_PATH'],
|
| 'VC/vcvarsall.bat')),
|
| - 'amd64_x86' if target_cpu == 'x86' else 'amd64']
|
| -
|
| -
|
| -def _LoadToolchainEnv(cpu, win_sdk_path):
|
| - """Returns a dictionary with environment variables that must be set while
|
| - running binaries from the toolchain (e.g. INCLUDE and PATH for cl.exe)."""
|
| - args = _SetupScript(cpu, win_sdk_path)
|
| - args.extend(('&&', 'set'))
|
| - popen = subprocess.Popen(
|
| - args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
| - variables, _ = popen.communicate()
|
| - if popen.returncode != 0:
|
| - raise Exception('"%s" failed with error %d' % (args, popen.returncode))
|
| + 'amd64_x86' if cpu == 'x86' else 'amd64']
|
| + # Don't try to manually parse vcvarsall.bat; we don't control it and it's
|
| + # likely complicated. Assume a Windows host for this.
|
| + args.extend(('&&', 'set'))
|
| + popen = subprocess.Popen(
|
| + args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
| + variables, _ = popen.communicate()
|
| + if popen.returncode != 0:
|
| + raise Exception('"%s" failed with error %d' % (args, popen.returncode))
|
| return _ExtractImportantEnvironment(variables)
|
|
|
|
|
| @@ -163,11 +222,12 @@ def main():
|
| # version is used.
|
|
|
| if win_sdk_path:
|
| + # INCLUDE always uses ; separators, even on non-Windows.
|
| additional_includes = [
|
| os.path.join(win_sdk_path, 'Include', '10.0.10586.0', p)
|
| for p in ['shared', 'um', 'winrt']]
|
| - additional_includes = os.path.pathsep.join(additional_includes)
|
| - env['INCLUDE'] = additional_includes + os.path.pathsep + env['INCLUDE']
|
| + additional_includes = ';'.join(additional_includes)
|
| + env['INCLUDE'] = additional_includes + ';' + env['INCLUDE']
|
| env_block = _FormatAsEnvironmentBlock(env)
|
| with open('environment.' + cpu, 'wb') as f:
|
| f.write(env_block)
|
|
|