|  | # Copyright 2014 The Chromium Authors. All rights reserved. | 
|  | # Use of this source code is governed by a BSD-style license that can be | 
|  | # found in the LICENSE file. | 
|  |  | 
|  | import json | 
|  | import os | 
|  | import pipes | 
|  | import shutil | 
|  | import subprocess | 
|  | import sys | 
|  |  | 
|  |  | 
|  | script_dir = os.path.dirname(os.path.realpath(__file__)) | 
|  | sys.path.insert(0, os.path.join(script_dir, 'gyp', 'pylib')) | 
|  | json_data_file = os.path.join(script_dir, 'win_toolchain.json') | 
|  |  | 
|  |  | 
|  | import gyp | 
|  |  | 
|  |  | 
|  | # Use MSVS2015 as the default toolchain. | 
|  | CURRENT_DEFAULT_TOOLCHAIN_VERSION = '2015' | 
|  |  | 
|  |  | 
|  | def SetEnvironmentAndGetRuntimeDllDirs(): | 
|  | """Sets up os.environ to use the depot_tools VS toolchain with gyp, and | 
|  | returns the location of the VS runtime DLLs so they can be copied into | 
|  | the output directory after gyp generation. | 
|  | """ | 
|  | vs_runtime_dll_dirs = None | 
|  | depot_tools_win_toolchain = \ | 
|  | bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) | 
|  | if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain: | 
|  | if not os.path.exists(json_data_file): | 
|  | Update() | 
|  | with open(json_data_file, 'r') as tempf: | 
|  | toolchain_data = json.load(tempf) | 
|  |  | 
|  | toolchain = toolchain_data['path'] | 
|  | version = toolchain_data['version'] | 
|  | win_sdk = toolchain_data.get('win_sdk') | 
|  | if not win_sdk: | 
|  | win_sdk = toolchain_data['win8sdk'] | 
|  | wdk = toolchain_data['wdk'] | 
|  | # TODO(scottmg): The order unfortunately matters in these. They should be | 
|  | # split into separate keys for x86 and x64. (See CopyVsRuntimeDlls call | 
|  | # below). http://crbug.com/345992 | 
|  | vs_runtime_dll_dirs = toolchain_data['runtime_dirs'] | 
|  |  | 
|  | os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain | 
|  | os.environ['GYP_MSVS_VERSION'] = version | 
|  | # We need to make sure windows_sdk_path is set to the automated | 
|  | # toolchain values in GYP_DEFINES, but don't want to override any | 
|  | # otheroptions.express | 
|  | # values there. | 
|  | gyp_defines_dict = gyp.NameValueListToDict(gyp.ShlexEnv('GYP_DEFINES')) | 
|  | gyp_defines_dict['windows_sdk_path'] = win_sdk | 
|  | os.environ['GYP_DEFINES'] = ' '.join('%s=%s' % (k, pipes.quote(str(v))) | 
|  | for k, v in gyp_defines_dict.iteritems()) | 
|  | os.environ['WINDOWSSDKDIR'] = win_sdk | 
|  | os.environ['WDK_DIR'] = wdk | 
|  | # Include the VS runtime in the PATH in case it's not machine-installed. | 
|  | runtime_path = ';'.join(vs_runtime_dll_dirs) | 
|  | os.environ['PATH'] = runtime_path + ';' + os.environ['PATH'] | 
|  | return vs_runtime_dll_dirs | 
|  |  | 
|  |  | 
|  | def FindDepotTools(): | 
|  | """Returns the path to depot_tools in $PATH.""" | 
|  | for path in os.environ['PATH'].split(os.pathsep): | 
|  | if os.path.isfile(os.path.join(path, 'gclient.py')): | 
|  | return path | 
|  | raise Exception("depot_tools not found!") | 
|  |  | 
|  |  | 
|  | def GetVisualStudioVersion(): | 
|  | """Return GYP_MSVS_VERSION of Visual Studio. | 
|  | """ | 
|  | return os.environ.get('GYP_MSVS_VERSION', CURRENT_DEFAULT_TOOLCHAIN_VERSION) | 
|  |  | 
|  |  | 
|  | def _GetDesiredVsToolchainHashes(): | 
|  | """Load a list of SHA1s corresponding to the toolchains that we want installed | 
|  | to build with.""" | 
|  | env_version = GetVisualStudioVersion() | 
|  | if env_version == '2015': | 
|  | # Update 3 final with 10.0.15063.468 SDK and no vctip.exe. | 
|  | return ['f53e4598951162bad6330f7a167486c7ae5db1e5'] | 
|  | if env_version == '2017': | 
|  | # VS 2017 Update 3.2 with 10.0.15063.468 SDK. | 
|  | return ['9bc7ccbf9f4bd50d4a3bd185e8ca94ff1618de0b'] | 
|  | raise Exception('Unsupported VS version %s' % env_version) | 
|  |  | 
|  |  | 
|  | def Update(): | 
|  | """Requests an update of the toolchain to the specific hashes we have at | 
|  | this revision. The update outputs a .json of the various configuration | 
|  | information required to pass to gyp which we use in |GetToolchainDir()|. | 
|  | """ | 
|  | depot_tools_win_toolchain = \ | 
|  | bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) | 
|  | if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain: | 
|  | depot_tools_path = FindDepotTools() | 
|  | # Necessary so that get_toolchain_if_necessary.py will put the VS toolkit | 
|  | # in the correct directory. | 
|  | os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion() | 
|  | get_toolchain_args = [ | 
|  | sys.executable, | 
|  | os.path.join(depot_tools_path, | 
|  | 'win_toolchain', | 
|  | 'get_toolchain_if_necessary.py'), | 
|  | '--output-json', json_data_file, | 
|  | ] + _GetDesiredVsToolchainHashes() | 
|  | subprocess.check_call(get_toolchain_args) | 
|  |  | 
|  | return 0 | 
|  |  | 
|  |  | 
|  | def main(): | 
|  | if not sys.platform.startswith(('win32', 'cygwin')): | 
|  | return 0 | 
|  | commands = { | 
|  | 'update': Update, | 
|  | } | 
|  | if len(sys.argv) < 2 or sys.argv[1] not in commands: | 
|  | print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands) | 
|  | return 1 | 
|  | return commands[sys.argv[1]](*sys.argv[2:]) | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | sys.exit(main()) |