thakis | 79870e2 | 2015-08-12 07:25:00 +0900 | [diff] [blame] | 1 | #!/usr/bin/env python |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [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 | df9e277 | 2016-02-09 13:27:52 +0900 | [diff] [blame] | 6 | import glob |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 7 | import json |
| 8 | import os |
| 9 | import pipes |
brucedawson | 815cd43 | 2016-06-02 03:37:18 +0900 | [diff] [blame] | 10 | import platform |
sebmarchand | 3a2260f | 2017-05-13 00:29:26 +0900 | [diff] [blame] | 11 | import re |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 12 | import shutil |
brucedawson | 815cd43 | 2016-06-02 03:37:18 +0900 | [diff] [blame] | 13 | import stat |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 14 | import subprocess |
| 15 | import sys |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 16 | |
| 17 | |
| 18 | script_dir = os.path.dirname(os.path.realpath(__file__)) |
| 19 | chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir)) |
| 20 | SRC_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 21 | sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib')) |
scottmg@chromium.org | f867a39 | 2014-04-09 10:56:20 +0900 | [diff] [blame] | 22 | json_data_file = os.path.join(script_dir, 'win_toolchain.json') |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 23 | |
| 24 | |
Bruce Dawson | b43c2ef | 2017-07-18 01:39:20 +0900 | [diff] [blame] | 25 | # Use MSVS2015 as the default toolchain. |
| 26 | CURRENT_DEFAULT_TOOLCHAIN_VERSION = '2015' |
sebmarchand | d84a2ff | 2016-01-16 07:29:57 +0900 | [diff] [blame] | 27 | |
| 28 | |
scottmg@chromium.org | f867a39 | 2014-04-09 10:56:20 +0900 | [diff] [blame] | 29 | def SetEnvironmentAndGetRuntimeDllDirs(): |
| 30 | """Sets up os.environ to use the depot_tools VS toolchain with gyp, and |
| 31 | returns the location of the VS runtime DLLs so they can be copied into |
| 32 | the output directory after gyp generation. |
brucedawson | 815cd43 | 2016-06-02 03:37:18 +0900 | [diff] [blame] | 33 | |
| 34 | Return value is [x64path, x86path] or None |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 35 | """ |
brucedawson | 0db1b9b | 2015-11-21 11:21:52 +0900 | [diff] [blame] | 36 | vs_runtime_dll_dirs = None |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 37 | depot_tools_win_toolchain = \ |
| 38 | bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) |
thakis | 79870e2 | 2015-08-12 07:25:00 +0900 | [diff] [blame] | 39 | # When running on a non-Windows host, only do this if the SDK has explicitly |
| 40 | # been downloaded before (in which case json_data_file will exist). |
scottmg | 3e19176 | 2015-08-26 08:03:35 +0900 | [diff] [blame] | 41 | if ((sys.platform in ('win32', 'cygwin') or os.path.exists(json_data_file)) |
| 42 | and depot_tools_win_toolchain): |
sebmarchand | d84a2ff | 2016-01-16 07:29:57 +0900 | [diff] [blame] | 43 | if ShouldUpdateToolchain(): |
scottmg@chromium.org | 2f8c83b | 2014-08-14 23:03:30 +0900 | [diff] [blame] | 44 | Update() |
scottmg@chromium.org | f867a39 | 2014-04-09 10:56:20 +0900 | [diff] [blame] | 45 | with open(json_data_file, 'r') as tempf: |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 46 | toolchain_data = json.load(tempf) |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 47 | |
| 48 | toolchain = toolchain_data['path'] |
| 49 | version = toolchain_data['version'] |
scottmg | 73c1e86 | 2015-06-02 10:15:44 +0900 | [diff] [blame] | 50 | win_sdk = toolchain_data.get('win_sdk') |
| 51 | if not win_sdk: |
| 52 | win_sdk = toolchain_data['win8sdk'] |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 53 | wdk = toolchain_data['wdk'] |
| 54 | # TODO(scottmg): The order unfortunately matters in these. They should be |
sebmarchand | 3a2260f | 2017-05-13 00:29:26 +0900 | [diff] [blame] | 55 | # split into separate keys for x86 and x64. (See CopyDlls call below). |
| 56 | # http://crbug.com/345992 |
brucedawson | 0db1b9b | 2015-11-21 11:21:52 +0900 | [diff] [blame] | 57 | vs_runtime_dll_dirs = toolchain_data['runtime_dirs'] |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 58 | |
| 59 | os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain |
| 60 | os.environ['GYP_MSVS_VERSION'] = version |
thestig | 8580360 | 2017-03-11 10:46:42 +0900 | [diff] [blame] | 61 | |
| 62 | # Limit the scope of the gyp import to only where it is used. This |
| 63 | # potentially lets build configs that never execute this block to drop |
| 64 | # their GYP checkout. |
| 65 | import gyp |
| 66 | |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 67 | # We need to make sure windows_sdk_path is set to the automated |
| 68 | # toolchain values in GYP_DEFINES, but don't want to override any |
| 69 | # otheroptions.express |
| 70 | # values there. |
| 71 | gyp_defines_dict = gyp.NameValueListToDict(gyp.ShlexEnv('GYP_DEFINES')) |
scottmg | 73c1e86 | 2015-06-02 10:15:44 +0900 | [diff] [blame] | 72 | gyp_defines_dict['windows_sdk_path'] = win_sdk |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 73 | os.environ['GYP_DEFINES'] = ' '.join('%s=%s' % (k, pipes.quote(str(v))) |
| 74 | for k, v in gyp_defines_dict.iteritems()) |
thestig | 8580360 | 2017-03-11 10:46:42 +0900 | [diff] [blame] | 75 | |
scottmg | 73c1e86 | 2015-06-02 10:15:44 +0900 | [diff] [blame] | 76 | os.environ['WINDOWSSDKDIR'] = win_sdk |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 77 | os.environ['WDK_DIR'] = wdk |
| 78 | # Include the VS runtime in the PATH in case it's not machine-installed. |
thakis | fe3b08a | 2016-02-16 03:18:01 +0900 | [diff] [blame] | 79 | runtime_path = os.path.pathsep.join(vs_runtime_dll_dirs) |
| 80 | os.environ['PATH'] = runtime_path + os.path.pathsep + os.environ['PATH'] |
bratell | 58b9a56 | 2016-01-08 01:30:12 +0900 | [diff] [blame] | 81 | elif sys.platform == 'win32' and not depot_tools_win_toolchain: |
| 82 | if not 'GYP_MSVS_OVERRIDE_PATH' in os.environ: |
| 83 | os.environ['GYP_MSVS_OVERRIDE_PATH'] = DetectVisualStudioPath() |
lwchkg | bc6ee72 | 2016-01-19 09:39:08 +0900 | [diff] [blame] | 84 | if not 'GYP_MSVS_VERSION' in os.environ: |
| 85 | os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion() |
bratell | 58b9a56 | 2016-01-08 01:30:12 +0900 | [diff] [blame] | 86 | |
brucedawson | 815cd43 | 2016-06-02 03:37:18 +0900 | [diff] [blame] | 87 | # When using an installed toolchain these files aren't needed in the output |
| 88 | # directory in order to run binaries locally, but they are needed in order |
| 89 | # to create isolates or the mini_installer. Copying them to the output |
| 90 | # directory ensures that they are available when needed. |
| 91 | bitness = platform.architecture()[0] |
| 92 | # When running 64-bit python the x64 DLLs will be in System32 |
| 93 | x64_path = 'System32' if bitness == '64bit' else 'Sysnative' |
| 94 | x64_path = os.path.join(r'C:\Windows', x64_path) |
| 95 | vs_runtime_dll_dirs = [x64_path, r'C:\Windows\SysWOW64'] |
| 96 | |
brucedawson | 0db1b9b | 2015-11-21 11:21:52 +0900 | [diff] [blame] | 97 | return vs_runtime_dll_dirs |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 98 | |
| 99 | |
bratell | 58b9a56 | 2016-01-08 01:30:12 +0900 | [diff] [blame] | 100 | def _RegistryGetValueUsingWinReg(key, value): |
| 101 | """Use the _winreg module to obtain the value of a registry key. |
| 102 | |
| 103 | Args: |
| 104 | key: The registry key. |
| 105 | value: The particular registry value to read. |
| 106 | Return: |
| 107 | contents of the registry key's value, or None on failure. Throws |
| 108 | ImportError if _winreg is unavailable. |
| 109 | """ |
| 110 | import _winreg |
| 111 | try: |
| 112 | root, subkey = key.split('\\', 1) |
| 113 | assert root == 'HKLM' # Only need HKLM for now. |
| 114 | with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey) as hkey: |
| 115 | return _winreg.QueryValueEx(hkey, value)[0] |
| 116 | except WindowsError: |
| 117 | return None |
| 118 | |
| 119 | |
| 120 | def _RegistryGetValue(key, value): |
| 121 | try: |
| 122 | return _RegistryGetValueUsingWinReg(key, value) |
| 123 | except ImportError: |
| 124 | raise Exception('The python library _winreg not found.') |
| 125 | |
| 126 | |
halton.huo | 08f7617 | 2016-01-13 11:23:30 +0900 | [diff] [blame] | 127 | def GetVisualStudioVersion(): |
sebmarchand | d84a2ff | 2016-01-16 07:29:57 +0900 | [diff] [blame] | 128 | """Return GYP_MSVS_VERSION of Visual Studio. |
halton.huo | 08f7617 | 2016-01-13 11:23:30 +0900 | [diff] [blame] | 129 | """ |
sebmarchand | d84a2ff | 2016-01-16 07:29:57 +0900 | [diff] [blame] | 130 | return os.environ.get('GYP_MSVS_VERSION', CURRENT_DEFAULT_TOOLCHAIN_VERSION) |
halton.huo | 08f7617 | 2016-01-13 11:23:30 +0900 | [diff] [blame] | 131 | |
| 132 | |
bratell | 58b9a56 | 2016-01-08 01:30:12 +0900 | [diff] [blame] | 133 | def DetectVisualStudioPath(): |
| 134 | """Return path to the GYP_MSVS_VERSION of Visual Studio. |
| 135 | """ |
| 136 | |
| 137 | # Note that this code is used from |
| 138 | # build/toolchain/win/setup_toolchain.py as well. |
halton.huo | 08f7617 | 2016-01-13 11:23:30 +0900 | [diff] [blame] | 139 | version_as_year = GetVisualStudioVersion() |
bratell | 58b9a56 | 2016-01-08 01:30:12 +0900 | [diff] [blame] | 140 | year_to_version = { |
bratell | 58b9a56 | 2016-01-08 01:30:12 +0900 | [diff] [blame] | 141 | '2015': '14.0', |
brucedawson | 8cb1a64 | 2017-01-23 15:57:21 +0900 | [diff] [blame] | 142 | '2017': '15.0', |
bratell | 58b9a56 | 2016-01-08 01:30:12 +0900 | [diff] [blame] | 143 | } |
| 144 | if version_as_year not in year_to_version: |
| 145 | raise Exception(('Visual Studio version %s (from GYP_MSVS_VERSION)' |
| 146 | ' not supported. Supported versions are: %s') % ( |
| 147 | version_as_year, ', '.join(year_to_version.keys()))) |
| 148 | version = year_to_version[version_as_year] |
brucedawson | 8cb1a64 | 2017-01-23 15:57:21 +0900 | [diff] [blame] | 149 | if version_as_year == '2017': |
| 150 | # The VC++ 2017 install location needs to be located using COM instead of |
| 151 | # the registry. For details see: |
| 152 | # https://blogs.msdn.microsoft.com/heaths/2016/09/15/changes-to-visual-studio-15-setup/ |
| 153 | # For now we use a hardcoded default with an environment variable override. |
drbasic | 49ee123 | 2017-04-14 11:13:01 +0900 | [diff] [blame] | 154 | for path in ( |
| 155 | os.environ.get('vs2017_install'), |
| 156 | r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional', |
| 157 | r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community'): |
| 158 | if path and os.path.exists(path): |
| 159 | return path |
brucedawson | 8cb1a64 | 2017-01-23 15:57:21 +0900 | [diff] [blame] | 160 | else: |
| 161 | keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version, |
| 162 | r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version] |
| 163 | for key in keys: |
| 164 | path = _RegistryGetValue(key, 'InstallDir') |
| 165 | if not path: |
| 166 | continue |
| 167 | path = os.path.normpath(os.path.join(path, '..', '..')) |
| 168 | return path |
bratell | 58b9a56 | 2016-01-08 01:30:12 +0900 | [diff] [blame] | 169 | |
| 170 | raise Exception(('Visual Studio Version %s (from GYP_MSVS_VERSION)' |
| 171 | ' not found.') % (version_as_year)) |
| 172 | |
| 173 | |
brucedawson | df9e277 | 2016-02-09 13:27:52 +0900 | [diff] [blame] | 174 | def _CopyRuntimeImpl(target, source, verbose=True): |
gab | 2244999 | 2016-04-19 00:29:14 +0900 | [diff] [blame] | 175 | """Copy |source| to |target| if it doesn't already exist or if it needs to be |
| 176 | updated (comparing last modified time as an approximate float match as for |
| 177 | some reason the values tend to differ by ~1e-07 despite being copies of the |
| 178 | same file... https://crbug.com/603603). |
dpranke | 650b37f | 2014-11-15 09:09:14 +0900 | [diff] [blame] | 179 | """ |
| 180 | if (os.path.isdir(os.path.dirname(target)) and |
| 181 | (not os.path.isfile(target) or |
gab | 2244999 | 2016-04-19 00:29:14 +0900 | [diff] [blame] | 182 | abs(os.stat(target).st_mtime - os.stat(source).st_mtime) >= 0.01)): |
brucedawson | df9e277 | 2016-02-09 13:27:52 +0900 | [diff] [blame] | 183 | if verbose: |
| 184 | print 'Copying %s to %s...' % (source, target) |
dpranke | 650b37f | 2014-11-15 09:09:14 +0900 | [diff] [blame] | 185 | if os.path.exists(target): |
brucedawson | 815cd43 | 2016-06-02 03:37:18 +0900 | [diff] [blame] | 186 | # Make the file writable so that we can delete it now. |
| 187 | os.chmod(target, stat.S_IWRITE) |
dpranke | 650b37f | 2014-11-15 09:09:14 +0900 | [diff] [blame] | 188 | os.unlink(target) |
| 189 | shutil.copy2(source, target) |
brucedawson | 815cd43 | 2016-06-02 03:37:18 +0900 | [diff] [blame] | 190 | # Make the file writable so that we can overwrite or delete it later. |
| 191 | os.chmod(target, stat.S_IWRITE) |
dpranke | 650b37f | 2014-11-15 09:09:14 +0900 | [diff] [blame] | 192 | |
| 193 | |
brucedawson | bdf66b6 | 2017-03-14 06:12:31 +0900 | [diff] [blame] | 194 | def _CopyUCRTRuntime(target_dir, source_dir, target_cpu, dll_pattern, suffix): |
scottmg | 73c1e86 | 2015-06-02 10:15:44 +0900 | [diff] [blame] | 195 | """Copy both the msvcp and vccorlib runtime DLLs, only if the target doesn't |
| 196 | exist, but the target directory does exist.""" |
sebmarchand | 6698572 | 2015-12-18 05:44:35 +0900 | [diff] [blame] | 197 | for file_part in ('msvcp', 'vccorlib', 'vcruntime'): |
scottmg | 73c1e86 | 2015-06-02 10:15:44 +0900 | [diff] [blame] | 198 | dll = dll_pattern % file_part |
| 199 | target = os.path.join(target_dir, dll) |
| 200 | source = os.path.join(source_dir, dll) |
| 201 | _CopyRuntimeImpl(target, source) |
brucedawson | bdf66b6 | 2017-03-14 06:12:31 +0900 | [diff] [blame] | 202 | # Copy the UCRT files needed by VS 2015 from the Windows SDK. This location |
| 203 | # includes the api-ms-win-crt-*.dll files that are not found in the Windows |
| 204 | # directory. These files are needed for component builds. |
| 205 | # If WINDOWSSDKDIR is not set use the default SDK path. This will be the case |
| 206 | # when DEPOT_TOOLS_WIN_TOOLCHAIN=0 and vcvarsall.bat has not been run. |
| 207 | win_sdk_dir = os.path.normpath( |
| 208 | os.environ.get('WINDOWSSDKDIR', |
| 209 | 'C:\\Program Files (x86)\\Windows Kits\\10')) |
Nico Weber | e6d34d9 | 2017-07-25 07:23:12 +0900 | [diff] [blame] | 210 | ucrt_dll_dirs = os.path.join(win_sdk_dir, 'Redist', 'ucrt', 'DLLs', |
| 211 | target_cpu) |
brucedawson | bdf66b6 | 2017-03-14 06:12:31 +0900 | [diff] [blame] | 212 | ucrt_files = glob.glob(os.path.join(ucrt_dll_dirs, 'api-ms-win-*.dll')) |
brucedawson | 815cd43 | 2016-06-02 03:37:18 +0900 | [diff] [blame] | 213 | assert len(ucrt_files) > 0 |
| 214 | for ucrt_src_file in ucrt_files: |
brucedawson | 83e79e9 | 2016-02-23 08:09:18 +0900 | [diff] [blame] | 215 | file_part = os.path.basename(ucrt_src_file) |
| 216 | ucrt_dst_file = os.path.join(target_dir, file_part) |
| 217 | _CopyRuntimeImpl(ucrt_dst_file, ucrt_src_file, False) |
| 218 | _CopyRuntimeImpl(os.path.join(target_dir, 'ucrtbase' + suffix), |
| 219 | os.path.join(source_dir, 'ucrtbase' + suffix)) |
dpranke | 650b37f | 2014-11-15 09:09:14 +0900 | [diff] [blame] | 220 | |
| 221 | |
sebmarchand | 2448ed2 | 2017-05-21 00:00:06 +0900 | [diff] [blame] | 222 | def FindVCToolsRoot(): |
| 223 | """In VS2017 the PGO runtime dependencies are located in |
| 224 | {toolchain_root}/VC/Tools/MSVC/{x.y.z}/bin/Host{target_cpu}/{target_cpu}/, the |
| 225 | {version_number} part is likely to change in case of a minor update of the |
| 226 | toolchain so we don't hardcode this value here (except for the major number). |
| 227 | |
| 228 | This returns the '{toolchain_root}/VC/Tools/MSVC/{x.y.z}/bin/' path. |
| 229 | |
| 230 | This function should only be called when using VS2017. |
| 231 | """ |
| 232 | assert GetVisualStudioVersion() == '2017' |
sebmarchand | 75c4928 | 2017-05-23 11:08:31 +0900 | [diff] [blame] | 233 | SetEnvironmentAndGetRuntimeDllDirs() |
sebmarchand | 2448ed2 | 2017-05-21 00:00:06 +0900 | [diff] [blame] | 234 | assert ('GYP_MSVS_OVERRIDE_PATH' in os.environ) |
| 235 | vc_tools_msvc_root = os.path.join(os.environ['GYP_MSVS_OVERRIDE_PATH'], |
| 236 | 'VC', 'Tools', 'MSVC') |
| 237 | for directory in os.listdir(vc_tools_msvc_root): |
| 238 | if not os.path.isdir(os.path.join(vc_tools_msvc_root, directory)): |
| 239 | continue |
| 240 | if re.match('14\.\d+\.\d+', directory): |
| 241 | return os.path.join(vc_tools_msvc_root, directory, 'bin') |
| 242 | raise Exception('Unable to find the VC tools directory.') |
| 243 | |
| 244 | |
sebmarchand | 3a2260f | 2017-05-13 00:29:26 +0900 | [diff] [blame] | 245 | def _CopyPGORuntime(target_dir, target_cpu): |
| 246 | """Copy the runtime dependencies required during a PGO build. |
| 247 | """ |
| 248 | env_version = GetVisualStudioVersion() |
| 249 | # These dependencies will be in a different location depending on the version |
| 250 | # of the toolchain. |
| 251 | if env_version == '2015': |
| 252 | pgo_x86_runtime_dir = os.path.join(os.environ.get('GYP_MSVS_OVERRIDE_PATH'), |
| 253 | 'VC', 'bin') |
| 254 | pgo_x64_runtime_dir = os.path.join(pgo_x86_runtime_dir, 'amd64') |
| 255 | elif env_version == '2017': |
sebmarchand | 2448ed2 | 2017-05-21 00:00:06 +0900 | [diff] [blame] | 256 | pgo_runtime_root = FindVCToolsRoot() |
sebmarchand | 3a2260f | 2017-05-13 00:29:26 +0900 | [diff] [blame] | 257 | assert pgo_runtime_root |
| 258 | # There's no version of pgosweep.exe in HostX64/x86, so we use the copy |
| 259 | # from HostX86/x86. |
| 260 | pgo_x86_runtime_dir = os.path.join(pgo_runtime_root, 'HostX86', 'x86') |
| 261 | pgo_x64_runtime_dir = os.path.join(pgo_runtime_root, 'HostX64', 'x64') |
| 262 | else: |
| 263 | raise Exception('Unexpected toolchain version: %s.' % env_version) |
| 264 | |
| 265 | # We need to copy 2 runtime dependencies used during the profiling step: |
| 266 | # - pgort140.dll: runtime library required to run the instrumented image. |
| 267 | # - pgosweep.exe: executable used to collect the profiling data |
| 268 | pgo_runtimes = ['pgort140.dll', 'pgosweep.exe'] |
| 269 | for runtime in pgo_runtimes: |
| 270 | if target_cpu == 'x86': |
| 271 | source = os.path.join(pgo_x86_runtime_dir, runtime) |
| 272 | elif target_cpu == 'x64': |
| 273 | source = os.path.join(pgo_x64_runtime_dir, runtime) |
| 274 | else: |
| 275 | raise NotImplementedError("Unexpected target_cpu value: " + target_cpu) |
| 276 | if not os.path.exists(source): |
| 277 | raise Exception('Unable to find %s.' % source) |
| 278 | _CopyRuntimeImpl(os.path.join(target_dir, runtime), source) |
| 279 | |
| 280 | |
brucedawson | 0db1b9b | 2015-11-21 11:21:52 +0900 | [diff] [blame] | 281 | def _CopyRuntime(target_dir, source_dir, target_cpu, debug): |
| 282 | """Copy the VS runtime DLLs, only if the target doesn't exist, but the target |
brucedawson | 6de2407 | 2017-03-28 05:59:15 +0900 | [diff] [blame] | 283 | directory does exist. Handles VS 2015 and VS 2017.""" |
brucedawson | 0db1b9b | 2015-11-21 11:21:52 +0900 | [diff] [blame] | 284 | suffix = "d.dll" if debug else ".dll" |
brucedawson | 6de2407 | 2017-03-28 05:59:15 +0900 | [diff] [blame] | 285 | # VS 2017 uses the same CRT DLLs as VS 2015. |
| 286 | _CopyUCRTRuntime(target_dir, source_dir, target_cpu, '%s140' + suffix, |
| 287 | suffix) |
brucedawson | 0db1b9b | 2015-11-21 11:21:52 +0900 | [diff] [blame] | 288 | |
dpranke | 650b37f | 2014-11-15 09:09:14 +0900 | [diff] [blame] | 289 | |
dpranke | 487f3cf | 2015-02-20 11:55:19 +0900 | [diff] [blame] | 290 | def CopyDlls(target_dir, configuration, target_cpu): |
dpranke | 650b37f | 2014-11-15 09:09:14 +0900 | [diff] [blame] | 291 | """Copy the VS runtime DLLs into the requested directory as needed. |
| 292 | |
| 293 | configuration is one of 'Debug' or 'Release'. |
dpranke | 487f3cf | 2015-02-20 11:55:19 +0900 | [diff] [blame] | 294 | target_cpu is one of 'x86' or 'x64'. |
dpranke | 650b37f | 2014-11-15 09:09:14 +0900 | [diff] [blame] | 295 | |
| 296 | The debug configuration gets both the debug and release DLLs; the |
| 297 | release config only the latter. |
| 298 | """ |
brucedawson | 0db1b9b | 2015-11-21 11:21:52 +0900 | [diff] [blame] | 299 | vs_runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs() |
| 300 | if not vs_runtime_dll_dirs: |
dpranke | 650b37f | 2014-11-15 09:09:14 +0900 | [diff] [blame] | 301 | return |
| 302 | |
brucedawson | 0db1b9b | 2015-11-21 11:21:52 +0900 | [diff] [blame] | 303 | x64_runtime, x86_runtime = vs_runtime_dll_dirs |
dpranke | 487f3cf | 2015-02-20 11:55:19 +0900 | [diff] [blame] | 304 | runtime_dir = x64_runtime if target_cpu == 'x64' else x86_runtime |
brucedawson | 0db1b9b | 2015-11-21 11:21:52 +0900 | [diff] [blame] | 305 | _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=False) |
dpranke | 650b37f | 2014-11-15 09:09:14 +0900 | [diff] [blame] | 306 | if configuration == 'Debug': |
brucedawson | 0db1b9b | 2015-11-21 11:21:52 +0900 | [diff] [blame] | 307 | _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=True) |
sebmarchand | 3a2260f | 2017-05-13 00:29:26 +0900 | [diff] [blame] | 308 | else: |
| 309 | _CopyPGORuntime(target_dir, target_cpu) |
sebmarchand@chromium.org | f1d42ff | 2014-07-22 09:18:32 +0900 | [diff] [blame] | 310 | |
brucedawson | 7649bc7 | 2017-04-20 07:27:40 +0900 | [diff] [blame] | 311 | _CopyDebugger(target_dir, target_cpu) |
| 312 | |
| 313 | |
| 314 | def _CopyDebugger(target_dir, target_cpu): |
sebmarchand | 7e78f53 | 2017-06-30 07:24:39 +0900 | [diff] [blame] | 315 | """Copy dbghelp.dll and dbgcore.dll into the requested directory as needed. |
brucedawson | 7649bc7 | 2017-04-20 07:27:40 +0900 | [diff] [blame] | 316 | |
| 317 | target_cpu is one of 'x86' or 'x64'. |
| 318 | |
| 319 | dbghelp.dll is used when Chrome needs to symbolize stacks. Copying this file |
| 320 | from the SDK directory avoids using the system copy of dbghelp.dll which then |
| 321 | ensures compatibility with recent debug information formats, such as VS |
| 322 | 2017 /debug:fastlink PDBs. |
sebmarchand | 7e78f53 | 2017-06-30 07:24:39 +0900 | [diff] [blame] | 323 | |
| 324 | dbgcore.dll is needed when using some functions from dbghelp.dll (like |
| 325 | MinidumpWriteDump). |
brucedawson | 7649bc7 | 2017-04-20 07:27:40 +0900 | [diff] [blame] | 326 | """ |
| 327 | win_sdk_dir = SetEnvironmentAndGetSDKDir() |
| 328 | if not win_sdk_dir: |
| 329 | return |
| 330 | |
sebmarchand | 7e78f53 | 2017-06-30 07:24:39 +0900 | [diff] [blame] | 331 | debug_files = ['dbghelp.dll', 'dbgcore.dll'] |
| 332 | for debug_file in debug_files: |
| 333 | full_path = os.path.join(win_sdk_dir, 'Debuggers', target_cpu, debug_file) |
| 334 | if not os.path.exists(full_path): |
| 335 | raise Exception('%s not found in "%s"\r\nYou must install the ' |
| 336 | '"Debugging Tools for Windows" feature from the Windows ' |
| 337 | '10 SDK.' % (debug_file, full_path)) |
| 338 | target_path = os.path.join(target_dir, debug_file) |
| 339 | _CopyRuntimeImpl(target_path, full_path) |
brucedawson | 7649bc7 | 2017-04-20 07:27:40 +0900 | [diff] [blame] | 340 | |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 341 | |
scottmg@chromium.org | f867a39 | 2014-04-09 10:56:20 +0900 | [diff] [blame] | 342 | def _GetDesiredVsToolchainHashes(): |
| 343 | """Load a list of SHA1s corresponding to the toolchains that we want installed |
| 344 | to build with.""" |
thestig | 8580360 | 2017-03-11 10:46:42 +0900 | [diff] [blame] | 345 | env_version = GetVisualStudioVersion() |
thestig | 8580360 | 2017-03-11 10:46:42 +0900 | [diff] [blame] | 346 | if env_version == '2015': |
brucedawson | e3f14f3 | 2017-06-23 02:40:42 +0900 | [diff] [blame] | 347 | # Update 3 final with 10.0.15063.468 SDK and no vctip.exe. |
| 348 | return ['f53e4598951162bad6330f7a167486c7ae5db1e5'] |
brucedawson | dc10036 | 2017-03-25 08:10:01 +0900 | [diff] [blame] | 349 | if env_version == '2017': |
Bruce Dawson | cd5982d | 2017-07-15 11:20:35 +0900 | [diff] [blame] | 350 | # VS 2017 Update 3 Preview 4 with 10.0.15063.468 SDK. |
| 351 | return ['1f52d730755ac72dddaf121b73c9d6fd5c24ddf8'] |
thestig | 8580360 | 2017-03-11 10:46:42 +0900 | [diff] [blame] | 352 | raise Exception('Unsupported VS version %s' % env_version) |
scottmg@chromium.org | f867a39 | 2014-04-09 10:56:20 +0900 | [diff] [blame] | 353 | |
| 354 | |
sebmarchand | d84a2ff | 2016-01-16 07:29:57 +0900 | [diff] [blame] | 355 | def ShouldUpdateToolchain(): |
| 356 | """Check if the toolchain should be upgraded.""" |
| 357 | if not os.path.exists(json_data_file): |
| 358 | return True |
| 359 | with open(json_data_file, 'r') as tempf: |
| 360 | toolchain_data = json.load(tempf) |
| 361 | version = toolchain_data['version'] |
| 362 | env_version = GetVisualStudioVersion() |
| 363 | # If there's a mismatch between the version set in the environment and the one |
| 364 | # in the json file then the toolchain should be updated. |
| 365 | return version != env_version |
| 366 | |
| 367 | |
thakis | 79870e2 | 2015-08-12 07:25:00 +0900 | [diff] [blame] | 368 | def Update(force=False): |
scottmg@chromium.org | f867a39 | 2014-04-09 10:56:20 +0900 | [diff] [blame] | 369 | """Requests an update of the toolchain to the specific hashes we have at |
| 370 | this revision. The update outputs a .json of the various configuration |
| 371 | information required to pass to gyp which we use in |GetToolchainDir()|. |
| 372 | """ |
thakis | 79870e2 | 2015-08-12 07:25:00 +0900 | [diff] [blame] | 373 | if force != False and force != '--force': |
| 374 | print >>sys.stderr, 'Unknown parameter "%s"' % force |
| 375 | return 1 |
| 376 | if force == '--force' or os.path.exists(json_data_file): |
| 377 | force = True |
| 378 | |
scottmg@chromium.org | f867a39 | 2014-04-09 10:56:20 +0900 | [diff] [blame] | 379 | depot_tools_win_toolchain = \ |
| 380 | bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) |
thakis | 79870e2 | 2015-08-12 07:25:00 +0900 | [diff] [blame] | 381 | if ((sys.platform in ('win32', 'cygwin') or force) and |
| 382 | depot_tools_win_toolchain): |
scottmg@chromium.org | f867a39 | 2014-04-09 10:56:20 +0900 | [diff] [blame] | 383 | import find_depot_tools |
| 384 | depot_tools_path = find_depot_tools.add_depot_tools_to_path() |
brucedawson | 31d3f67 | 2016-03-12 04:55:25 +0900 | [diff] [blame] | 385 | # Necessary so that get_toolchain_if_necessary.py will put the VS toolkit |
| 386 | # in the correct directory. |
| 387 | os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion() |
scottmg@chromium.org | f867a39 | 2014-04-09 10:56:20 +0900 | [diff] [blame] | 388 | get_toolchain_args = [ |
| 389 | sys.executable, |
| 390 | os.path.join(depot_tools_path, |
| 391 | 'win_toolchain', |
| 392 | 'get_toolchain_if_necessary.py'), |
| 393 | '--output-json', json_data_file, |
| 394 | ] + _GetDesiredVsToolchainHashes() |
thakis | 79870e2 | 2015-08-12 07:25:00 +0900 | [diff] [blame] | 395 | if force: |
| 396 | get_toolchain_args.append('--force') |
scottmg@chromium.org | f867a39 | 2014-04-09 10:56:20 +0900 | [diff] [blame] | 397 | subprocess.check_call(get_toolchain_args) |
| 398 | |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 399 | return 0 |
| 400 | |
scottmg@chromium.org | 0efdbb7 | 2014-03-21 02:42:25 +0900 | [diff] [blame] | 401 | |
brucedawson | 5b77725 | 2016-03-23 09:58:06 +0900 | [diff] [blame] | 402 | def NormalizePath(path): |
| 403 | while path.endswith("\\"): |
| 404 | path = path[:-1] |
| 405 | return path |
| 406 | |
| 407 | |
jochen | cc14d66 | 2017-02-16 07:45:26 +0900 | [diff] [blame] | 408 | def SetEnvironmentAndGetSDKDir(): |
| 409 | """Gets location information about the current sdk (must have been |
brettw@chromium.org | 4d8b423 | 2014-05-29 05:32:01 +0900 | [diff] [blame] | 410 | previously updated by 'update'). This is used for the GN build.""" |
tikuta | 0c091c0 | 2017-05-02 15:12:31 +0900 | [diff] [blame] | 411 | SetEnvironmentAndGetRuntimeDllDirs() |
ckocagil | cca62d4 | 2014-10-01 04:31:43 +0900 | [diff] [blame] | 412 | |
| 413 | # If WINDOWSSDKDIR is not set, search the default SDK path and set it. |
| 414 | if not 'WINDOWSSDKDIR' in os.environ: |
brucedawson | 738bfff | 2016-01-22 08:35:35 +0900 | [diff] [blame] | 415 | default_sdk_path = 'C:\\Program Files (x86)\\Windows Kits\\10' |
ckocagil | cca62d4 | 2014-10-01 04:31:43 +0900 | [diff] [blame] | 416 | if os.path.isdir(default_sdk_path): |
| 417 | os.environ['WINDOWSSDKDIR'] = default_sdk_path |
| 418 | |
jochen | cc14d66 | 2017-02-16 07:45:26 +0900 | [diff] [blame] | 419 | return NormalizePath(os.environ['WINDOWSSDKDIR']) |
| 420 | |
| 421 | |
| 422 | def GetToolchainDir(): |
| 423 | """Gets location information about the current toolchain (must have been |
| 424 | previously updated by 'update'). This is used for the GN build.""" |
| 425 | runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs() |
| 426 | win_sdk_dir = SetEnvironmentAndGetSDKDir() |
| 427 | |
brettw@chromium.org | 4d8b423 | 2014-05-29 05:32:01 +0900 | [diff] [blame] | 428 | print '''vs_path = "%s" |
| 429 | sdk_path = "%s" |
| 430 | vs_version = "%s" |
| 431 | wdk_dir = "%s" |
scottmg | d24020c | 2014-11-20 04:33:28 +0900 | [diff] [blame] | 432 | runtime_dirs = "%s" |
brettw@chromium.org | 4d8b423 | 2014-05-29 05:32:01 +0900 | [diff] [blame] | 433 | ''' % ( |
brucedawson | 5b77725 | 2016-03-23 09:58:06 +0900 | [diff] [blame] | 434 | NormalizePath(os.environ['GYP_MSVS_OVERRIDE_PATH']), |
jochen | cc14d66 | 2017-02-16 07:45:26 +0900 | [diff] [blame] | 435 | win_sdk_dir, |
halton.huo | 08f7617 | 2016-01-13 11:23:30 +0900 | [diff] [blame] | 436 | GetVisualStudioVersion(), |
brucedawson | 5b77725 | 2016-03-23 09:58:06 +0900 | [diff] [blame] | 437 | NormalizePath(os.environ.get('WDK_DIR', '')), |
thakis | fe3b08a | 2016-02-16 03:18:01 +0900 | [diff] [blame] | 438 | os.path.pathsep.join(runtime_dll_dirs or ['None'])) |
scottmg@chromium.org | f867a39 | 2014-04-09 10:56:20 +0900 | [diff] [blame] | 439 | |
| 440 | |
| 441 | def main(): |
scottmg@chromium.org | f867a39 | 2014-04-09 10:56:20 +0900 | [diff] [blame] | 442 | commands = { |
| 443 | 'update': Update, |
| 444 | 'get_toolchain_dir': GetToolchainDir, |
dpranke | 650b37f | 2014-11-15 09:09:14 +0900 | [diff] [blame] | 445 | 'copy_dlls': CopyDlls, |
scottmg@chromium.org | f867a39 | 2014-04-09 10:56:20 +0900 | [diff] [blame] | 446 | } |
| 447 | if len(sys.argv) < 2 or sys.argv[1] not in commands: |
| 448 | print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands) |
| 449 | return 1 |
dpranke | 650b37f | 2014-11-15 09:09:14 +0900 | [diff] [blame] | 450 | return commands[sys.argv[1]](*sys.argv[2:]) |
scottmg@chromium.org | f867a39 | 2014-04-09 10:56:20 +0900 | [diff] [blame] | 451 | |
| 452 | |
scottmg@chromium.org | 73ab3a5 | 2014-03-20 07:01:39 +0900 | [diff] [blame] | 453 | if __name__ == '__main__': |
| 454 | sys.exit(main()) |