1 # Copyright 2014 The Chromium Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import json 6 import os 7 import pipes 8 import shutil 9 import subprocess 10 import sys 11 12 13 script_dir = os.path.dirname(os.path.realpath(__file__)) 14 sys.path.insert(0, os.path.join(script_dir, 'gyp', 'pylib')) 15 json_data_file = os.path.join(script_dir, 'win_toolchain.json') 16 17 18 import gyp 19 20 21 # Use MSVS2015 as the default toolchain. 22 CURRENT_DEFAULT_TOOLCHAIN_VERSION = '2015' 23 24 25 def SetEnvironmentAndGetRuntimeDllDirs(): 26 """Sets up os.environ to use the depot_tools VS toolchain with gyp, and 27 returns the location of the VS runtime DLLs so they can be copied into 28 the output directory after gyp generation. 29 """ 30 vs_runtime_dll_dirs = None 31 depot_tools_win_toolchain = \ 32 bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) 33 if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain: 34 if not os.path.exists(json_data_file): 35 Update() 36 with open(json_data_file, 'r') as tempf: 37 toolchain_data = json.load(tempf) 38 39 toolchain = toolchain_data['path'] 40 version = toolchain_data['version'] 41 win_sdk = toolchain_data.get('win_sdk') 42 if not win_sdk: 43 win_sdk = toolchain_data['win8sdk'] 44 wdk = toolchain_data['wdk'] 45 # TODO(scottmg): The order unfortunately matters in these. They should be 46 # split into separate keys for x86 and x64. (See CopyVsRuntimeDlls call 47 # below). http://crbug.com/345992 48 vs_runtime_dll_dirs = toolchain_data['runtime_dirs'] 49 50 os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain 51 os.environ['GYP_MSVS_VERSION'] = version 52 # We need to make sure windows_sdk_path is set to the automated 53 # toolchain values in GYP_DEFINES, but don't want to override any 54 # otheroptions.express 55 # values there. 56 gyp_defines_dict = gyp.NameValueListToDict(gyp.ShlexEnv('GYP_DEFINES')) 57 gyp_defines_dict['windows_sdk_path'] = win_sdk 58 os.environ['GYP_DEFINES'] = ' '.join('%s=%s' % (k, pipes.quote(str(v))) 59 for k, v in gyp_defines_dict.iteritems()) 60 os.environ['WINDOWSSDKDIR'] = win_sdk 61 os.environ['WDK_DIR'] = wdk 62 # Include the VS runtime in the PATH in case it's not machine-installed. 63 runtime_path = ';'.join(vs_runtime_dll_dirs) 64 os.environ['PATH'] = runtime_path + ';' + os.environ['PATH'] 65 return vs_runtime_dll_dirs 66 67 68 def FindDepotTools(): 69 """Returns the path to depot_tools in $PATH.""" 70 for path in os.environ['PATH'].split(os.pathsep): 71 if os.path.isfile(os.path.join(path, 'gclient.py')): 72 return path 73 raise Exception("depot_tools not found!") 74 75 76 def GetVisualStudioVersion(): 77 """Return GYP_MSVS_VERSION of Visual Studio. 78 """ 79 return os.environ.get('GYP_MSVS_VERSION', CURRENT_DEFAULT_TOOLCHAIN_VERSION) 80 81 82 def _GetDesiredVsToolchainHashes(): 83 """Load a list of SHA1s corresponding to the toolchains that we want installed 84 to build with.""" 85 env_version = GetVisualStudioVersion() 86 if env_version == '2015': 87 # Update 3 final with 10.0.15063.468 SDK and no vctip.exe. 88 return ['f53e4598951162bad6330f7a167486c7ae5db1e5'] 89 if env_version == '2017': 90 # VS 2017 Update 3.2 with 10.0.15063.468 SDK, patched setenv.cmd, and 91 # 10.0.16299.15 debuggers. 92 return ['1180cb75833ea365097e279efb2d5d7a42dee4b0'] 93 raise Exception('Unsupported VS version %s' % env_version) 94 95 96 def Update(): 97 """Requests an update of the toolchain to the specific hashes we have at 98 this revision. The update outputs a .json of the various configuration 99 information required to pass to gyp which we use in |GetToolchainDir()|. 100 """ 101 depot_tools_win_toolchain = \ 102 bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) 103 if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain: 104 depot_tools_path = FindDepotTools() 105 # Necessary so that get_toolchain_if_necessary.py will put the VS toolkit 106 # in the correct directory. 107 os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion() 108 get_toolchain_args = [ 109 sys.executable, 110 os.path.join(depot_tools_path, 111 'win_toolchain', 112 'get_toolchain_if_necessary.py'), 113 '--output-json', json_data_file, 114 ] + _GetDesiredVsToolchainHashes() 115 subprocess.check_call(get_toolchain_args) 116 117 return 0 118 119 120 def main(): 121 if not sys.platform.startswith(('win32', 'cygwin')): 122 return 0 123 commands = { 124 'update': Update, 125 } 126 if len(sys.argv) < 2 or sys.argv[1] not in commands: 127 print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands) 128 return 1 129 return commands[sys.argv[1]](*sys.argv[2:]) 130 131 132 if __name__ == '__main__': 133 sys.exit(main()) 134