thakis | 4f4b137 | 2015-08-11 22:25:00 | [diff] [blame] | 1 | #!/usr/bin/env python |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 2 | # Copyright 2014 The Chromium Authors. All rights reserved. |
| 3 | # Use of this source code is governed by a BSD-style license that can be |
| 4 | # found in the LICENSE file. |
| 5 | |
brucedawson | d5273dd | 2016-02-09 04:27:52 | [diff] [blame] | 6 | import glob |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 7 | import json |
| 8 | import os |
| 9 | import pipes |
brucedawson | e7bd034 | 2016-06-01 18:37:18 | [diff] [blame] | 10 | import platform |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 11 | import shutil |
brucedawson | e7bd034 | 2016-06-01 18:37:18 | [diff] [blame] | 12 | import stat |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 13 | import subprocess |
| 14 | import sys |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 15 | |
| 16 | |
| 17 | script_dir = os.path.dirname(os.path.realpath(__file__)) |
| 18 | chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir)) |
| 19 | SRC_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 20 | sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib')) |
[email protected] | c71d328 | 2014-04-09 01:56:20 | [diff] [blame] | 21 | json_data_file = os.path.join(script_dir, 'win_toolchain.json') |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 22 | |
| 23 | |
brucedawson | 2b33e7e | 2016-03-11 19:55:25 | [diff] [blame] | 24 | # Use MSVS2015 as the default toolchain. |
| 25 | CURRENT_DEFAULT_TOOLCHAIN_VERSION = '2015' |
sebmarchand | e44b02e | 2016-01-15 22:29:57 | [diff] [blame] | 26 | |
| 27 | |
[email protected] | c71d328 | 2014-04-09 01:56:20 | [diff] [blame] | 28 | def SetEnvironmentAndGetRuntimeDllDirs(): |
| 29 | """Sets up os.environ to use the depot_tools VS toolchain with gyp, and |
| 30 | returns the location of the VS runtime DLLs so they can be copied into |
| 31 | the output directory after gyp generation. |
brucedawson | e7bd034 | 2016-06-01 18:37:18 | [diff] [blame] | 32 | |
| 33 | Return value is [x64path, x86path] or None |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 34 | """ |
brucedawson | aaff8dc | 2015-11-21 02:21:52 | [diff] [blame] | 35 | vs_runtime_dll_dirs = None |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 36 | depot_tools_win_toolchain = \ |
| 37 | bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) |
thakis | 4f4b137 | 2015-08-11 22:25:00 | [diff] [blame] | 38 | # When running on a non-Windows host, only do this if the SDK has explicitly |
| 39 | # been downloaded before (in which case json_data_file will exist). |
scottmg | 05eac9c0 | 2015-08-25 23:03:35 | [diff] [blame] | 40 | if ((sys.platform in ('win32', 'cygwin') or os.path.exists(json_data_file)) |
| 41 | and depot_tools_win_toolchain): |
sebmarchand | e44b02e | 2016-01-15 22:29:57 | [diff] [blame] | 42 | if ShouldUpdateToolchain(): |
[email protected] | 9372bec | 2014-08-14 14:03:30 | [diff] [blame] | 43 | Update() |
[email protected] | c71d328 | 2014-04-09 01:56:20 | [diff] [blame] | 44 | with open(json_data_file, 'r') as tempf: |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 45 | toolchain_data = json.load(tempf) |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 46 | |
| 47 | toolchain = toolchain_data['path'] |
| 48 | version = toolchain_data['version'] |
scottmg | 54e4506 | 2015-06-02 01:15:44 | [diff] [blame] | 49 | win_sdk = toolchain_data.get('win_sdk') |
| 50 | if not win_sdk: |
| 51 | win_sdk = toolchain_data['win8sdk'] |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 52 | wdk = toolchain_data['wdk'] |
| 53 | # TODO(scottmg): The order unfortunately matters in these. They should be |
| 54 | # split into separate keys for x86 and x64. (See CopyVsRuntimeDlls call |
| 55 | # below). http://crbug.com/345992 |
brucedawson | aaff8dc | 2015-11-21 02:21:52 | [diff] [blame] | 56 | vs_runtime_dll_dirs = toolchain_data['runtime_dirs'] |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 57 | |
| 58 | os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain |
| 59 | os.environ['GYP_MSVS_VERSION'] = version |
thestig | 9b24fa5 | 2017-03-11 01:46:42 | [diff] [blame] | 60 | |
| 61 | # Limit the scope of the gyp import to only where it is used. This |
| 62 | # potentially lets build configs that never execute this block to drop |
| 63 | # their GYP checkout. |
| 64 | import gyp |
| 65 | |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 66 | # We need to make sure windows_sdk_path is set to the automated |
| 67 | # toolchain values in GYP_DEFINES, but don't want to override any |
| 68 | # otheroptions.express |
| 69 | # values there. |
| 70 | gyp_defines_dict = gyp.NameValueListToDict(gyp.ShlexEnv('GYP_DEFINES')) |
scottmg | 54e4506 | 2015-06-02 01:15:44 | [diff] [blame] | 71 | gyp_defines_dict['windows_sdk_path'] = win_sdk |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 72 | os.environ['GYP_DEFINES'] = ' '.join('%s=%s' % (k, pipes.quote(str(v))) |
| 73 | for k, v in gyp_defines_dict.iteritems()) |
thestig | 9b24fa5 | 2017-03-11 01:46:42 | [diff] [blame] | 74 | |
scottmg | 54e4506 | 2015-06-02 01:15:44 | [diff] [blame] | 75 | os.environ['WINDOWSSDKDIR'] = win_sdk |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 76 | os.environ['WDK_DIR'] = wdk |
| 77 | # Include the VS runtime in the PATH in case it's not machine-installed. |
thakis | 44a40f8 | 2016-02-15 18:18:01 | [diff] [blame] | 78 | runtime_path = os.path.pathsep.join(vs_runtime_dll_dirs) |
| 79 | os.environ['PATH'] = runtime_path + os.path.pathsep + os.environ['PATH'] |
bratell | c7af879 | 2016-01-07 16:30:12 | [diff] [blame] | 80 | elif sys.platform == 'win32' and not depot_tools_win_toolchain: |
| 81 | if not 'GYP_MSVS_OVERRIDE_PATH' in os.environ: |
| 82 | os.environ['GYP_MSVS_OVERRIDE_PATH'] = DetectVisualStudioPath() |
lwchkg | 833a437f | 2016-01-19 00:39:08 | [diff] [blame] | 83 | if not 'GYP_MSVS_VERSION' in os.environ: |
| 84 | os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion() |
bratell | c7af879 | 2016-01-07 16:30:12 | [diff] [blame] | 85 | |
brucedawson | e7bd034 | 2016-06-01 18:37:18 | [diff] [blame] | 86 | # When using an installed toolchain these files aren't needed in the output |
| 87 | # directory in order to run binaries locally, but they are needed in order |
| 88 | # to create isolates or the mini_installer. Copying them to the output |
| 89 | # directory ensures that they are available when needed. |
| 90 | bitness = platform.architecture()[0] |
| 91 | # When running 64-bit python the x64 DLLs will be in System32 |
| 92 | x64_path = 'System32' if bitness == '64bit' else 'Sysnative' |
| 93 | x64_path = os.path.join(r'C:\Windows', x64_path) |
| 94 | vs_runtime_dll_dirs = [x64_path, r'C:\Windows\SysWOW64'] |
| 95 | |
brucedawson | aaff8dc | 2015-11-21 02:21:52 | [diff] [blame] | 96 | return vs_runtime_dll_dirs |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 97 | |
| 98 | |
bratell | c7af879 | 2016-01-07 16:30:12 | [diff] [blame] | 99 | def _RegistryGetValueUsingWinReg(key, value): |
| 100 | """Use the _winreg module to obtain the value of a registry key. |
| 101 | |
| 102 | Args: |
| 103 | key: The registry key. |
| 104 | value: The particular registry value to read. |
| 105 | Return: |
| 106 | contents of the registry key's value, or None on failure. Throws |
| 107 | ImportError if _winreg is unavailable. |
| 108 | """ |
| 109 | import _winreg |
| 110 | try: |
| 111 | root, subkey = key.split('\\', 1) |
| 112 | assert root == 'HKLM' # Only need HKLM for now. |
| 113 | with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey) as hkey: |
| 114 | return _winreg.QueryValueEx(hkey, value)[0] |
| 115 | except WindowsError: |
| 116 | return None |
| 117 | |
| 118 | |
| 119 | def _RegistryGetValue(key, value): |
| 120 | try: |
| 121 | return _RegistryGetValueUsingWinReg(key, value) |
| 122 | except ImportError: |
| 123 | raise Exception('The python library _winreg not found.') |
| 124 | |
| 125 | |
halton.huo | 815e177 | 2016-01-13 02:23:30 | [diff] [blame] | 126 | def GetVisualStudioVersion(): |
sebmarchand | e44b02e | 2016-01-15 22:29:57 | [diff] [blame] | 127 | """Return GYP_MSVS_VERSION of Visual Studio. |
halton.huo | 815e177 | 2016-01-13 02:23:30 | [diff] [blame] | 128 | """ |
sebmarchand | e44b02e | 2016-01-15 22:29:57 | [diff] [blame] | 129 | return os.environ.get('GYP_MSVS_VERSION', CURRENT_DEFAULT_TOOLCHAIN_VERSION) |
halton.huo | 815e177 | 2016-01-13 02:23:30 | [diff] [blame] | 130 | |
| 131 | |
bratell | c7af879 | 2016-01-07 16:30:12 | [diff] [blame] | 132 | def DetectVisualStudioPath(): |
| 133 | """Return path to the GYP_MSVS_VERSION of Visual Studio. |
| 134 | """ |
| 135 | |
| 136 | # Note that this code is used from |
| 137 | # build/toolchain/win/setup_toolchain.py as well. |
halton.huo | 815e177 | 2016-01-13 02:23:30 | [diff] [blame] | 138 | version_as_year = GetVisualStudioVersion() |
bratell | c7af879 | 2016-01-07 16:30:12 | [diff] [blame] | 139 | year_to_version = { |
bratell | c7af879 | 2016-01-07 16:30:12 | [diff] [blame] | 140 | '2015': '14.0', |
brucedawson | adddab4 | 2017-01-23 06:57:21 | [diff] [blame] | 141 | '2017': '15.0', |
bratell | c7af879 | 2016-01-07 16:30:12 | [diff] [blame] | 142 | } |
| 143 | if version_as_year not in year_to_version: |
| 144 | raise Exception(('Visual Studio version %s (from GYP_MSVS_VERSION)' |
| 145 | ' not supported. Supported versions are: %s') % ( |
| 146 | version_as_year, ', '.join(year_to_version.keys()))) |
| 147 | version = year_to_version[version_as_year] |
brucedawson | adddab4 | 2017-01-23 06:57:21 | [diff] [blame] | 148 | if version_as_year == '2017': |
| 149 | # The VC++ 2017 install location needs to be located using COM instead of |
| 150 | # the registry. For details see: |
| 151 | # https://blogs.msdn.microsoft.com/heaths/2016/09/15/changes-to-visual-studio-15-setup/ |
| 152 | # For now we use a hardcoded default with an environment variable override. |
| 153 | path = r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional' |
| 154 | path = os.environ.get('vs2017_install', path) |
| 155 | if os.path.exists(path): |
| 156 | return path |
| 157 | else: |
| 158 | keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version, |
| 159 | r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version] |
| 160 | for key in keys: |
| 161 | path = _RegistryGetValue(key, 'InstallDir') |
| 162 | if not path: |
| 163 | continue |
| 164 | path = os.path.normpath(os.path.join(path, '..', '..')) |
| 165 | return path |
bratell | c7af879 | 2016-01-07 16:30:12 | [diff] [blame] | 166 | |
| 167 | raise Exception(('Visual Studio Version %s (from GYP_MSVS_VERSION)' |
| 168 | ' not found.') % (version_as_year)) |
| 169 | |
| 170 | |
scottmg | 54e4506 | 2015-06-02 01:15:44 | [diff] [blame] | 171 | def _VersionNumber(): |
| 172 | """Gets the standard version number ('120', '140', etc.) based on |
| 173 | GYP_MSVS_VERSION.""" |
halton.huo | 815e177 | 2016-01-13 02:23:30 | [diff] [blame] | 174 | vs_version = GetVisualStudioVersion() |
thestig | 9b24fa5 | 2017-03-11 01:46:42 | [diff] [blame] | 175 | if vs_version == '2015': |
scottmg | 54e4506 | 2015-06-02 01:15:44 | [diff] [blame] | 176 | return '140' |
thestig | 9b24fa5 | 2017-03-11 01:46:42 | [diff] [blame] | 177 | if vs_version == '2017': |
brucedawson | adddab4 | 2017-01-23 06:57:21 | [diff] [blame] | 178 | return '150' |
thestig | 9b24fa5 | 2017-03-11 01:46:42 | [diff] [blame] | 179 | raise ValueError('Unexpected GYP_MSVS_VERSION') |
scottmg | 54e4506 | 2015-06-02 01:15:44 | [diff] [blame] | 180 | |
| 181 | |
brucedawson | d5273dd | 2016-02-09 04:27:52 | [diff] [blame] | 182 | def _CopyRuntimeImpl(target, source, verbose=True): |
gab | 381d9f17 | 2016-04-18 15:29:14 | [diff] [blame] | 183 | """Copy |source| to |target| if it doesn't already exist or if it needs to be |
| 184 | updated (comparing last modified time as an approximate float match as for |
| 185 | some reason the values tend to differ by ~1e-07 despite being copies of the |
| 186 | same file... https://crbug.com/603603). |
dpranke | 0b95195 | 2014-11-15 00:09:14 | [diff] [blame] | 187 | """ |
| 188 | if (os.path.isdir(os.path.dirname(target)) and |
| 189 | (not os.path.isfile(target) or |
gab | 381d9f17 | 2016-04-18 15:29:14 | [diff] [blame] | 190 | abs(os.stat(target).st_mtime - os.stat(source).st_mtime) >= 0.01)): |
brucedawson | d5273dd | 2016-02-09 04:27:52 | [diff] [blame] | 191 | if verbose: |
| 192 | print 'Copying %s to %s...' % (source, target) |
dpranke | 0b95195 | 2014-11-15 00:09:14 | [diff] [blame] | 193 | if os.path.exists(target): |
brucedawson | e7bd034 | 2016-06-01 18:37:18 | [diff] [blame] | 194 | # Make the file writable so that we can delete it now. |
| 195 | os.chmod(target, stat.S_IWRITE) |
dpranke | 0b95195 | 2014-11-15 00:09:14 | [diff] [blame] | 196 | os.unlink(target) |
| 197 | shutil.copy2(source, target) |
brucedawson | e7bd034 | 2016-06-01 18:37:18 | [diff] [blame] | 198 | # Make the file writable so that we can overwrite or delete it later. |
| 199 | os.chmod(target, stat.S_IWRITE) |
dpranke | 0b95195 | 2014-11-15 00:09:14 | [diff] [blame] | 200 | |
| 201 | |
brucedawson | 46cd6d93 | 2017-03-13 21:12:31 | [diff] [blame] | 202 | def _CopyUCRTRuntime(target_dir, source_dir, target_cpu, dll_pattern, suffix): |
scottmg | 54e4506 | 2015-06-02 01:15:44 | [diff] [blame] | 203 | """Copy both the msvcp and vccorlib runtime DLLs, only if the target doesn't |
| 204 | exist, but the target directory does exist.""" |
sebmarchand | 7cebe21 | 2015-12-17 20:44:35 | [diff] [blame] | 205 | for file_part in ('msvcp', 'vccorlib', 'vcruntime'): |
scottmg | 54e4506 | 2015-06-02 01:15:44 | [diff] [blame] | 206 | dll = dll_pattern % file_part |
| 207 | target = os.path.join(target_dir, dll) |
| 208 | source = os.path.join(source_dir, dll) |
| 209 | _CopyRuntimeImpl(target, source) |
brucedawson | 46cd6d93 | 2017-03-13 21:12:31 | [diff] [blame] | 210 | # Copy the UCRT files needed by VS 2015 from the Windows SDK. This location |
| 211 | # includes the api-ms-win-crt-*.dll files that are not found in the Windows |
| 212 | # directory. These files are needed for component builds. |
| 213 | # If WINDOWSSDKDIR is not set use the default SDK path. This will be the case |
| 214 | # when DEPOT_TOOLS_WIN_TOOLCHAIN=0 and vcvarsall.bat has not been run. |
| 215 | win_sdk_dir = os.path.normpath( |
| 216 | os.environ.get('WINDOWSSDKDIR', |
| 217 | 'C:\\Program Files (x86)\\Windows Kits\\10')) |
| 218 | ucrt_dll_dirs = os.path.join(win_sdk_dir, r'Redist\ucrt\DLLs', target_cpu) |
| 219 | ucrt_files = glob.glob(os.path.join(ucrt_dll_dirs, 'api-ms-win-*.dll')) |
brucedawson | e7bd034 | 2016-06-01 18:37:18 | [diff] [blame] | 220 | assert len(ucrt_files) > 0 |
| 221 | for ucrt_src_file in ucrt_files: |
brucedawson | c6f6c69 | 2016-02-22 23:09:18 | [diff] [blame] | 222 | file_part = os.path.basename(ucrt_src_file) |
| 223 | ucrt_dst_file = os.path.join(target_dir, file_part) |
| 224 | _CopyRuntimeImpl(ucrt_dst_file, ucrt_src_file, False) |
| 225 | _CopyRuntimeImpl(os.path.join(target_dir, 'ucrtbase' + suffix), |
| 226 | os.path.join(source_dir, 'ucrtbase' + suffix)) |
dpranke | 0b95195 | 2014-11-15 00:09:14 | [diff] [blame] | 227 | |
| 228 | |
brucedawson | aaff8dc | 2015-11-21 02:21:52 | [diff] [blame] | 229 | def _CopyRuntime(target_dir, source_dir, target_cpu, debug): |
| 230 | """Copy the VS runtime DLLs, only if the target doesn't exist, but the target |
brucedawson | e7c0d99 | 2017-03-27 20:59:15 | [diff] [blame] | 231 | directory does exist. Handles VS 2015 and VS 2017.""" |
brucedawson | aaff8dc | 2015-11-21 02:21:52 | [diff] [blame] | 232 | suffix = "d.dll" if debug else ".dll" |
brucedawson | e7c0d99 | 2017-03-27 20:59:15 | [diff] [blame] | 233 | # VS 2017 uses the same CRT DLLs as VS 2015. |
| 234 | _CopyUCRTRuntime(target_dir, source_dir, target_cpu, '%s140' + suffix, |
| 235 | suffix) |
brucedawson | aaff8dc | 2015-11-21 02:21:52 | [diff] [blame] | 236 | |
| 237 | # Copy the PGO runtime library to the release directories. |
| 238 | if not debug and os.environ.get('GYP_MSVS_OVERRIDE_PATH'): |
| 239 | pgo_x86_runtime_dir = os.path.join(os.environ.get('GYP_MSVS_OVERRIDE_PATH'), |
| 240 | 'VC', 'bin') |
| 241 | pgo_x64_runtime_dir = os.path.join(pgo_x86_runtime_dir, 'amd64') |
| 242 | pgo_runtime_dll = 'pgort' + _VersionNumber() + '.dll' |
| 243 | if target_cpu == "x86": |
| 244 | source_x86 = os.path.join(pgo_x86_runtime_dir, pgo_runtime_dll) |
| 245 | if os.path.exists(source_x86): |
| 246 | _CopyRuntimeImpl(os.path.join(target_dir, pgo_runtime_dll), source_x86) |
| 247 | elif target_cpu == "x64": |
| 248 | source_x64 = os.path.join(pgo_x64_runtime_dir, pgo_runtime_dll) |
| 249 | if os.path.exists(source_x64): |
| 250 | _CopyRuntimeImpl(os.path.join(target_dir, pgo_runtime_dll), |
| 251 | source_x64) |
| 252 | else: |
| 253 | raise NotImplementedError("Unexpected target_cpu value:" + target_cpu) |
| 254 | |
| 255 | |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 256 | def CopyVsRuntimeDlls(output_dir, runtime_dirs): |
| 257 | """Copies the VS runtime DLLs from the given |runtime_dirs| to the output |
| 258 | directory so that even if not system-installed, built binaries are likely to |
| 259 | be able to run. |
| 260 | |
| 261 | This needs to be run after gyp has been run so that the expected target |
| 262 | output directories are already created. |
brucedawson | aaff8dc | 2015-11-21 02:21:52 | [diff] [blame] | 263 | |
| 264 | This is used for the GYP build and gclient runhooks. |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 265 | """ |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 266 | x86, x64 = runtime_dirs |
| 267 | out_debug = os.path.join(output_dir, 'Debug') |
| 268 | out_debug_nacl64 = os.path.join(output_dir, 'Debug', 'x64') |
| 269 | out_release = os.path.join(output_dir, 'Release') |
| 270 | out_release_nacl64 = os.path.join(output_dir, 'Release', 'x64') |
| 271 | out_debug_x64 = os.path.join(output_dir, 'Debug_x64') |
| 272 | out_release_x64 = os.path.join(output_dir, 'Release_x64') |
| 273 | |
| 274 | if os.path.exists(out_debug) and not os.path.exists(out_debug_nacl64): |
| 275 | os.makedirs(out_debug_nacl64) |
| 276 | if os.path.exists(out_release) and not os.path.exists(out_release_nacl64): |
| 277 | os.makedirs(out_release_nacl64) |
brucedawson | aaff8dc | 2015-11-21 02:21:52 | [diff] [blame] | 278 | _CopyRuntime(out_debug, x86, "x86", debug=True) |
| 279 | _CopyRuntime(out_release, x86, "x86", debug=False) |
| 280 | _CopyRuntime(out_debug_x64, x64, "x64", debug=True) |
| 281 | _CopyRuntime(out_release_x64, x64, "x64", debug=False) |
| 282 | _CopyRuntime(out_debug_nacl64, x64, "x64", debug=True) |
| 283 | _CopyRuntime(out_release_nacl64, x64, "x64", debug=False) |
dpranke | 0b95195 | 2014-11-15 00:09:14 | [diff] [blame] | 284 | |
| 285 | |
dpranke | 4327621 | 2015-02-20 02:55:19 | [diff] [blame] | 286 | def CopyDlls(target_dir, configuration, target_cpu): |
dpranke | 0b95195 | 2014-11-15 00:09:14 | [diff] [blame] | 287 | """Copy the VS runtime DLLs into the requested directory as needed. |
| 288 | |
| 289 | configuration is one of 'Debug' or 'Release'. |
dpranke | 4327621 | 2015-02-20 02:55:19 | [diff] [blame] | 290 | target_cpu is one of 'x86' or 'x64'. |
dpranke | 0b95195 | 2014-11-15 00:09:14 | [diff] [blame] | 291 | |
| 292 | The debug configuration gets both the debug and release DLLs; the |
| 293 | release config only the latter. |
brucedawson | aaff8dc | 2015-11-21 02:21:52 | [diff] [blame] | 294 | |
| 295 | This is used for the GN build. |
dpranke | 0b95195 | 2014-11-15 00:09:14 | [diff] [blame] | 296 | """ |
brucedawson | aaff8dc | 2015-11-21 02:21:52 | [diff] [blame] | 297 | vs_runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs() |
| 298 | if not vs_runtime_dll_dirs: |
dpranke | 0b95195 | 2014-11-15 00:09:14 | [diff] [blame] | 299 | return |
| 300 | |
brucedawson | aaff8dc | 2015-11-21 02:21:52 | [diff] [blame] | 301 | x64_runtime, x86_runtime = vs_runtime_dll_dirs |
dpranke | 4327621 | 2015-02-20 02:55:19 | [diff] [blame] | 302 | runtime_dir = x64_runtime if target_cpu == 'x64' else x86_runtime |
brucedawson | aaff8dc | 2015-11-21 02:21:52 | [diff] [blame] | 303 | _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=False) |
dpranke | 0b95195 | 2014-11-15 00:09:14 | [diff] [blame] | 304 | if configuration == 'Debug': |
brucedawson | aaff8dc | 2015-11-21 02:21:52 | [diff] [blame] | 305 | _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=True) |
[email protected] | 3322252 | 2014-07-22 00:18:32 | [diff] [blame] | 306 | |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 307 | |
[email protected] | c71d328 | 2014-04-09 01:56:20 | [diff] [blame] | 308 | def _GetDesiredVsToolchainHashes(): |
| 309 | """Load a list of SHA1s corresponding to the toolchains that we want installed |
| 310 | to build with.""" |
thestig | 9b24fa5 | 2017-03-11 01:46:42 | [diff] [blame] | 311 | env_version = GetVisualStudioVersion() |
thestig | 9b24fa5 | 2017-03-11 01:46:42 | [diff] [blame] | 312 | if env_version == '2015': |
scottmg | b77dd49 | 2016-12-08 05:58:07 | [diff] [blame] | 313 | # Update 3 final with patches with 10.0.14393.0 SDK. |
| 314 | return ['d3cb0e37bdd120ad0ac4650b674b09e81be45616'] |
brucedawson | 560bb95 | 2017-03-24 23:10:01 | [diff] [blame] | 315 | if env_version == '2017': |
brucedawson | 6a01e98 | 2017-03-28 23:28:26 | [diff] [blame] | 316 | # VS 2017 RTM with 10.0.14393.0 SDK and dbghelp.dll fixes. |
| 317 | return ['4e8a360587a3c8ff3fa46aa9271e982bf3e948ec'] |
thestig | 9b24fa5 | 2017-03-11 01:46:42 | [diff] [blame] | 318 | raise Exception('Unsupported VS version %s' % env_version) |
[email protected] | c71d328 | 2014-04-09 01:56:20 | [diff] [blame] | 319 | |
| 320 | |
sebmarchand | e44b02e | 2016-01-15 22:29:57 | [diff] [blame] | 321 | def ShouldUpdateToolchain(): |
| 322 | """Check if the toolchain should be upgraded.""" |
| 323 | if not os.path.exists(json_data_file): |
| 324 | return True |
| 325 | with open(json_data_file, 'r') as tempf: |
| 326 | toolchain_data = json.load(tempf) |
| 327 | version = toolchain_data['version'] |
| 328 | env_version = GetVisualStudioVersion() |
| 329 | # If there's a mismatch between the version set in the environment and the one |
| 330 | # in the json file then the toolchain should be updated. |
| 331 | return version != env_version |
| 332 | |
| 333 | |
thakis | 4f4b137 | 2015-08-11 22:25:00 | [diff] [blame] | 334 | def Update(force=False): |
[email protected] | c71d328 | 2014-04-09 01:56:20 | [diff] [blame] | 335 | """Requests an update of the toolchain to the specific hashes we have at |
| 336 | this revision. The update outputs a .json of the various configuration |
| 337 | information required to pass to gyp which we use in |GetToolchainDir()|. |
| 338 | """ |
thakis | 4f4b137 | 2015-08-11 22:25:00 | [diff] [blame] | 339 | if force != False and force != '--force': |
| 340 | print >>sys.stderr, 'Unknown parameter "%s"' % force |
| 341 | return 1 |
| 342 | if force == '--force' or os.path.exists(json_data_file): |
| 343 | force = True |
| 344 | |
[email protected] | c71d328 | 2014-04-09 01:56:20 | [diff] [blame] | 345 | depot_tools_win_toolchain = \ |
| 346 | bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) |
thakis | 4f4b137 | 2015-08-11 22:25:00 | [diff] [blame] | 347 | if ((sys.platform in ('win32', 'cygwin') or force) and |
| 348 | depot_tools_win_toolchain): |
[email protected] | c71d328 | 2014-04-09 01:56:20 | [diff] [blame] | 349 | import find_depot_tools |
| 350 | depot_tools_path = find_depot_tools.add_depot_tools_to_path() |
brucedawson | 2b33e7e | 2016-03-11 19:55:25 | [diff] [blame] | 351 | # Necessary so that get_toolchain_if_necessary.py will put the VS toolkit |
| 352 | # in the correct directory. |
| 353 | os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion() |
[email protected] | c71d328 | 2014-04-09 01:56:20 | [diff] [blame] | 354 | get_toolchain_args = [ |
| 355 | sys.executable, |
| 356 | os.path.join(depot_tools_path, |
| 357 | 'win_toolchain', |
| 358 | 'get_toolchain_if_necessary.py'), |
| 359 | '--output-json', json_data_file, |
| 360 | ] + _GetDesiredVsToolchainHashes() |
thakis | 4f4b137 | 2015-08-11 22:25:00 | [diff] [blame] | 361 | if force: |
| 362 | get_toolchain_args.append('--force') |
[email protected] | c71d328 | 2014-04-09 01:56:20 | [diff] [blame] | 363 | subprocess.check_call(get_toolchain_args) |
| 364 | |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 365 | return 0 |
| 366 | |
[email protected] | ffe20562 | 2014-03-20 17:42:25 | [diff] [blame] | 367 | |
brucedawson | 12bbca4 | 2016-03-23 00:58:06 | [diff] [blame] | 368 | def NormalizePath(path): |
| 369 | while path.endswith("\\"): |
| 370 | path = path[:-1] |
| 371 | return path |
| 372 | |
| 373 | |
jochen | 6c29ace | 2017-02-15 22:45:26 | [diff] [blame] | 374 | def SetEnvironmentAndGetSDKDir(): |
| 375 | """Gets location information about the current sdk (must have been |
[email protected] | 308a6cae | 2014-05-28 20:32:01 | [diff] [blame] | 376 | previously updated by 'update'). This is used for the GN build.""" |
scottmg | 9bf8fb3 | 2014-11-19 19:33:28 | [diff] [blame] | 377 | runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs() |
ckocagil | fc8d7f23 | 2014-09-30 19:31:43 | [diff] [blame] | 378 | |
| 379 | # If WINDOWSSDKDIR is not set, search the default SDK path and set it. |
| 380 | if not 'WINDOWSSDKDIR' in os.environ: |
brucedawson | 953e376 | 2016-01-21 23:35:35 | [diff] [blame] | 381 | default_sdk_path = 'C:\\Program Files (x86)\\Windows Kits\\10' |
ckocagil | fc8d7f23 | 2014-09-30 19:31:43 | [diff] [blame] | 382 | if os.path.isdir(default_sdk_path): |
| 383 | os.environ['WINDOWSSDKDIR'] = default_sdk_path |
| 384 | |
jochen | 6c29ace | 2017-02-15 22:45:26 | [diff] [blame] | 385 | return NormalizePath(os.environ['WINDOWSSDKDIR']) |
| 386 | |
| 387 | |
| 388 | def GetToolchainDir(): |
| 389 | """Gets location information about the current toolchain (must have been |
| 390 | previously updated by 'update'). This is used for the GN build.""" |
| 391 | runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs() |
| 392 | win_sdk_dir = SetEnvironmentAndGetSDKDir() |
| 393 | |
[email protected] | 308a6cae | 2014-05-28 20:32:01 | [diff] [blame] | 394 | print '''vs_path = "%s" |
| 395 | sdk_path = "%s" |
| 396 | vs_version = "%s" |
| 397 | wdk_dir = "%s" |
scottmg | 9bf8fb3 | 2014-11-19 19:33:28 | [diff] [blame] | 398 | runtime_dirs = "%s" |
[email protected] | 308a6cae | 2014-05-28 20:32:01 | [diff] [blame] | 399 | ''' % ( |
brucedawson | 12bbca4 | 2016-03-23 00:58:06 | [diff] [blame] | 400 | NormalizePath(os.environ['GYP_MSVS_OVERRIDE_PATH']), |
jochen | 6c29ace | 2017-02-15 22:45:26 | [diff] [blame] | 401 | win_sdk_dir, |
halton.huo | 815e177 | 2016-01-13 02:23:30 | [diff] [blame] | 402 | GetVisualStudioVersion(), |
brucedawson | 12bbca4 | 2016-03-23 00:58:06 | [diff] [blame] | 403 | NormalizePath(os.environ.get('WDK_DIR', '')), |
thakis | 44a40f8 | 2016-02-15 18:18:01 | [diff] [blame] | 404 | os.path.pathsep.join(runtime_dll_dirs or ['None'])) |
[email protected] | c71d328 | 2014-04-09 01:56:20 | [diff] [blame] | 405 | |
| 406 | |
| 407 | def main(): |
[email protected] | c71d328 | 2014-04-09 01:56:20 | [diff] [blame] | 408 | commands = { |
| 409 | 'update': Update, |
| 410 | 'get_toolchain_dir': GetToolchainDir, |
dpranke | 0b95195 | 2014-11-15 00:09:14 | [diff] [blame] | 411 | 'copy_dlls': CopyDlls, |
[email protected] | c71d328 | 2014-04-09 01:56:20 | [diff] [blame] | 412 | } |
| 413 | if len(sys.argv) < 2 or sys.argv[1] not in commands: |
| 414 | print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands) |
| 415 | return 1 |
dpranke | 0b95195 | 2014-11-15 00:09:14 | [diff] [blame] | 416 | return commands[sys.argv[1]](*sys.argv[2:]) |
[email protected] | c71d328 | 2014-04-09 01:56:20 | [diff] [blame] | 417 | |
| 418 | |
[email protected] | 4e8a247 | 2014-03-19 22:01:39 | [diff] [blame] | 419 | if __name__ == '__main__': |
| 420 | sys.exit(main()) |