18from gn_helpers
import ToGNString
42TOOLCHAIN_HASH =
'27370823e7'
43SDK_VERSION =
'10.0.22621.0'
45script_dir = os.path.dirname(os.path.realpath(__file__))
46json_data_file = os.path.join(script_dir,
'win_toolchain.json')
51MSVS_VERSIONS = collections.OrderedDict([
59MSVC_TOOLSET_VERSION = {
66 """Returns True if running on a Windows host (including under cygwin)."""
67 return sys.platform
in (
'win32',
'cygwin')
70 """Sets up os.environ to use the depot_tools VS toolchain with gyp, and
71 returns the location of the VC runtime DLLs so they can be copied into
72 the output directory after gyp generation.
74 Return value is [x64path, x86path, 'Arm64Unused'] or None. arm64path is
75 generated separately because there are multiple folders for the arm64 VC
78 vs_runtime_dll_dirs =
None
79 depot_tools_win_toolchain = \
80 bool(
int(os.environ.get(
'DEPOT_TOOLS_WIN_TOOLCHAIN',
'1')))
84 and depot_tools_win_toolchain):
86 if len(sys.argv) > 1
and sys.argv[1] ==
'update':
89 update_result =
Update(no_download=
True)
90 if update_result != 0:
91 raise Exception(
'Failed to update, error code %d.' % update_result)
92 with open(json_data_file,
'r')
as tempf:
93 toolchain_data = json.load(tempf)
95 toolchain = toolchain_data[
'path']
96 version = toolchain_data[
'version']
97 win_sdk = toolchain_data.get(
'win_sdk')
98 wdk = toolchain_data[
'wdk']
102 vs_runtime_dll_dirs = toolchain_data[
'runtime_dirs']
106 if len(vs_runtime_dll_dirs) == 2:
107 vs_runtime_dll_dirs.append(
'Arm64Unused')
109 os.environ[
'GYP_MSVS_OVERRIDE_PATH'] = toolchain
111 os.environ[
'WINDOWSSDKDIR'] = win_sdk
112 os.environ[
'WDK_DIR'] = wdk
114 runtime_path = os.path.pathsep.join(vs_runtime_dll_dirs)
115 os.environ[
'PATH'] = runtime_path + os.path.pathsep + os.environ[
'PATH']
116 elif sys.platform ==
'win32' and not depot_tools_win_toolchain:
117 if not 'GYP_MSVS_OVERRIDE_PATH' in os.environ:
124 bitness = platform.architecture()[0]
128 x64_path =
'System32' if bitness ==
'64bit' else 'Sysnative'
129 x64_path = os.path.join(os.path.expandvars(
'%windir%'), x64_path)
130 vs_runtime_dll_dirs = [x64_path,
131 os.path.join(os.path.expandvars(
'%windir%'),
135 return vs_runtime_dll_dirs
139 """Use the _winreg module to obtain the value of a registry key.
142 key: The registry key.
143 value: The particular registry value to read.
145 contents of the registry key's value, or None on failure. Throws
146 ImportError if _winreg is unavailable.
150 root, subkey = key.split(
'\\', 1)
151 assert root ==
'HKLM'
152 with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey)
as hkey:
153 return _winreg.QueryValueEx(hkey, value)[0]
162 raise Exception(
'The python library _winreg not found.')
166 """Return best available version of Visual Studio.
168 supported_versions = list(MSVS_VERSIONS.keys())
171 if bool(
int(os.environ.get(
'DEPOT_TOOLS_WIN_TOOLCHAIN',
'1'))):
172 return supported_versions[0]
175 supported_versions_str =
', '.join(
'{} ({})'.
format(v,k)
176 for k,v
in MSVS_VERSIONS.items())
177 available_versions = []
178 for version
in supported_versions:
183 path = os.environ.get(
'vs%s_install' % version)
184 if path
and os.path.exists(path):
185 available_versions.append(version)
188 if version >=
'2022':
189 program_files_path_variable =
'%ProgramFiles%'
191 program_files_path_variable =
'%ProgramFiles(x86)%'
192 path = os.path.expandvars(program_files_path_variable +
193 '/Microsoft Visual Studio/%s' % version)
195 os.path.exists(os.path.join(path, edition))
196 for edition
in (
'Enterprise',
'Professional',
'Community',
'Preview',
198 available_versions.append(version)
201 if not available_versions:
202 raise Exception(
'No supported Visual Studio can be found.'
203 ' Supported versions are: %s.' % supported_versions_str)
204 return available_versions[0]
208 """Return path to the installed Visual Studio.
219 if version_as_year >=
'2022':
220 program_files_path_variable =
'%ProgramFiles%'
222 program_files_path_variable =
'%ProgramFiles(x86)%'
223 for path
in (os.environ.get(
'vs%s_install' % version_as_year),
224 os.path.expandvars(program_files_path_variable +
225 '/Microsoft Visual Studio/%s/Enterprise' %
227 os.path.expandvars(program_files_path_variable +
228 '/Microsoft Visual Studio/%s/Professional' %
230 os.path.expandvars(program_files_path_variable +
231 '/Microsoft Visual Studio/%s/Community' %
233 os.path.expandvars(program_files_path_variable +
234 '/Microsoft Visual Studio/%s/Preview' %
236 os.path.expandvars(program_files_path_variable +
237 '/Microsoft Visual Studio/%s/BuildTools' %
239 if path
and os.path.exists(path):
242 raise Exception(
'Visual Studio Version %s not found.' % version_as_year)
246 """Copy |source| to |target| if it doesn't already exist or if it needs to be
247 updated (comparing last modified time as an approximate float match as for
248 some reason the values tend to differ by ~1e-07 despite being copies of the
249 same file... https://crbug.com/603603).
251 if (os.path.isdir(os.path.dirname(target))
and
252 (
not os.path.isfile(target)
or
253 abs(os.stat(target).st_mtime - os.stat(source).st_mtime) >= 0.01)):
255 print(
'Copying %s to %s...' % (source, target))
256 if os.path.exists(target):
259 os.chmod(target, stat.S_IWRITE | stat.S_IREAD)
261 shutil.copy2(source, target)
264 os.chmod(target, stat.S_IWRITE | stat.S_IREAD)
267 """This sorts |list_of_str_versions| according to version number rules
268 so that version "1.12" is higher than version "1.9". Does not work
269 with non-numeric versions like 1.4.a8 which will be higher than
270 1.4.a12. It does handle the versions being embedded in file paths.
272 def to_int_if_int(x):
278 def to_number_sequence(x):
279 part_sequence = re.split(
r'[\\/\.]', x)
280 return [to_int_if_int(x)
for x
in part_sequence]
282 list_of_str_versions.sort(key=to_number_sequence, reverse=
True)
286 """Copy both the msvcp and vccorlib runtime DLLs, only if the target doesn't
287 exist, but the target directory does exist."""
288 if target_cpu ==
'arm64':
293 if suffix.startswith(
'.'):
294 vc_toolset_dir =
'Microsoft.{}.CRT' \
296 source_dir = os.path.join(vc_redist_root,
297 'arm64', vc_toolset_dir)
299 vc_toolset_dir =
'Microsoft.{}.DebugCRT' \
301 source_dir = os.path.join(vc_redist_root,
'debug_nonredist',
302 'arm64', vc_toolset_dir)
303 file_parts = (
'msvcp140',
'vccorlib140',
'vcruntime140')
305 file_parts = file_parts + (
'vcruntime140_1', )
306 for file_part
in file_parts:
307 dll = file_part + suffix
308 target = os.path.join(target_dir, dll)
309 source = os.path.join(source_dir, dll)
313 if not suffix.startswith(
'.'):
314 win_sdk_dir = os.path.normpath(
317 os.path.expandvars(
'%ProgramFiles(x86)%'
318 '\\Windows Kits\\10')))
321 sdk_bin_root = os.path.join(win_sdk_dir,
'bin')
322 sdk_bin_sub_dirs = glob.glob(os.path.join(sdk_bin_root,
'10.*'))
325 for directory
in sdk_bin_sub_dirs:
326 sdk_redist_root_version = os.path.join(sdk_bin_root, directory)
327 if not os.path.isdir(sdk_redist_root_version):
329 source_dir = os.path.join(sdk_redist_root_version, target_cpu,
'ucrt')
330 if not os.path.isdir(source_dir):
334 os.path.join(source_dir,
'ucrtbase' + suffix))
338 """Find the most recent Tools or Redist or other directory in an MSVC install.
339 Typical results are {toolchain_root}/VC/{component}/MSVC/{x.y.z}. The {x.y.z}
340 version number part changes frequently so the highest version number found is
345 assert (
'GYP_MSVS_OVERRIDE_PATH' in os.environ)
346 vc_component_msvc_root = os.path.join(os.environ[
'GYP_MSVS_OVERRIDE_PATH'],
347 'VC', component,
'MSVC')
348 vc_component_msvc_contents = glob.glob(
349 os.path.join(vc_component_msvc_root,
'14.*'))
352 for directory
in vc_component_msvc_contents:
353 if os.path.isdir(directory):
355 raise Exception(
'Unable to find the VC %s directory.' % component)
359 """In >=VS2017, Redist binaries are located in
360 {toolchain_root}/VC/Redist/MSVC/{x.y.z}/{target_cpu}/.
362 This returns the '{toolchain_root}/VC/Redist/MSVC/{x.y.z}/' path.
368 """Copy the VS runtime DLLs, only if the target doesn't exist, but the target
369 directory does exist. Handles VS 2015, 2017 and 2019."""
370 suffix =
'd.dll' if debug
else '.dll'
375def CopyDlls(target_dir, configuration, target_cpu):
376 """Copy the VS runtime DLLs into the requested directory as needed.
378 configuration is one of 'Debug' or 'Release'.
379 target_cpu is one of 'x86', 'x64' or 'arm64'.
381 The debug configuration gets both the debug and release DLLs; the
382 release config only the latter.
385 if not vs_runtime_dll_dirs:
388 x64_runtime, x86_runtime, arm64_runtime = vs_runtime_dll_dirs
389 if target_cpu ==
'x64':
390 runtime_dir = x64_runtime
391 elif target_cpu ==
'x86':
392 runtime_dir = x86_runtime
393 elif target_cpu ==
'arm64':
394 runtime_dir = arm64_runtime
396 raise Exception(
'Unknown target_cpu: ' + target_cpu)
397 _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=
False)
398 if configuration ==
'Debug':
399 _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=
True)
401 if target_cpu ==
'arm64':
402 target_dir = os.path.join(target_dir,
'win_clang_x64')
404 runtime_dir = x64_runtime
405 os.makedirs(target_dir, exist_ok=
True)
406 _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=
False)
407 if configuration ==
'Debug':
408 _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=
True)
413 """Copy dbghelp.dll, dbgcore.dll, and msdia140.dll into the requested
416 target_cpu is one of 'x86', 'x64' or 'arm64'.
418 dbghelp.dll is used when Chrome needs to symbolize stacks. Copying this file
419 from the SDK directory avoids using the system copy of dbghelp.dll which then
420 ensures compatibility with recent debug information formats, such as
421 large-page PDBs. Note that for these DLLs to be deployed to swarming bots they
422 also need to be listed in group("runtime_libs").
424 dbgcore.dll is needed when using some functions from dbghelp.dll (like
427 msdia140.dll is needed for tools like symupload.exe and dump_syms.exe.
435 debug_files = [(
'dbghelp.dll',
False), (
'dbgcore.dll',
True)]
436 for debug_file, is_optional
in debug_files:
437 full_path = os.path.join(win_sdk_dir,
'Debuggers', target_cpu, debug_file)
438 if not os.path.exists(full_path):
442 raise Exception(
'%s not found in "%s"\r\nYou must install '
443 'Windows 10 SDK version %s including the '
444 '"Debugging Tools for Windows" feature.' %
445 (debug_file, full_path, SDK_VERSION))
446 target_path = os.path.join(target_dir, debug_file)
451 dia_path = os.path.join(
NormalizePath(os.environ[
'GYP_MSVS_OVERRIDE_PATH']),
452 'DIA SDK',
'bin',
'amd64',
'msdia140.dll')
457 """Load a list of SHA1s corresponding to the toolchains that we want installed
461 toolchain_hash_mapping_key =
'GYP_MSVS_HASH_%s' % TOOLCHAIN_HASH
462 return [os.environ.get(toolchain_hash_mapping_key, TOOLCHAIN_HASH)]
466 """Check if the toolchain should be upgraded."""
467 if not os.path.exists(json_data_file):
469 with open(json_data_file,
'r')
as tempf:
470 toolchain_data = json.load(tempf)
471 version = toolchain_data[
'version']
475 return version != env_version
478def Update(force=False, no_download=False):
479 """Requests an update of the toolchain to the specific hashes we have at
480 this revision. The update outputs a .json of the various configuration
481 information required to pass to gyp which we use in |GetToolchainDir()|.
482 If no_download is true then the toolchain will be configured if present but
483 will not be downloaded.
485 if force !=
False and force !=
'--force':
486 print(
'Unknown parameter "%s"' % force, file=sys.stderr)
488 if force ==
'--force' or os.path.exists(json_data_file):
491 depot_tools_win_toolchain = \
492 bool(
int(os.environ.get(
'DEPOT_TOOLS_WIN_TOOLCHAIN',
'1')))
494 import find_depot_tools
501 toolchain_dir = os.path.join(depot_tools_path,
'win_toolchain',
'vs_files')
504 if sys.platform.startswith(
'linux')
and not os.path.ismount(toolchain_dir):
505 ciopfs = shutil.which(
'ciopfs')
508 ciopfs = os.path.join(script_dir,
'ciopfs')
509 if not os.path.isdir(toolchain_dir):
510 os.mkdir(toolchain_dir)
511 if not os.path.isdir(toolchain_dir +
'.ciopfs'):
512 os.mkdir(toolchain_dir +
'.ciopfs')
517 subprocess.check_call([
518 ciopfs,
'-o',
'use_ino', toolchain_dir +
'.ciopfs', toolchain_dir])
523 toolchain_dir = os.path.join(os.getcwd(),
'sdk',
'win_toolchain')
524 get_toolchain_args = [
526 os.path.join(depot_tools_path,
528 'get_toolchain_if_necessary.py'),
529 '--output-json', json_data_file,
530 '--toolchain-dir', toolchain_dir,
533 get_toolchain_args.append(
'--force')
535 get_toolchain_args.append(
'--no-download')
536 subprocess.check_call(get_toolchain_args)
542 while path.endswith(
'\\'):
548 """Gets location information about the current sdk (must have been
549 previously updated by 'update'). This is used for the GN build."""
553 if not 'WINDOWSSDKDIR' in os.environ:
554 default_sdk_path = os.path.expandvars(
'%ProgramFiles(x86)%'
555 '\\Windows Kits\\10')
556 if os.path.isdir(default_sdk_path):
557 os.environ[
'WINDOWSSDKDIR'] = default_sdk_path
563 """Gets location information about the current toolchain (must have been
564 previously updated by 'update'). This is used for the GN build."""
568 print(
'''vs_path = %s
575 os.environ[
'GYP_MSVS_OVERRIDE_PATH'])), ToGNString(SDK_VERSION),
578 ToGNString(os.path.pathsep.join(runtime_dll_dirs
or [
'None']))))
584 'get_toolchain_dir': GetToolchainDir,
585 'copy_dlls': CopyDlls,
587 if len(sys.argv) < 2
or sys.argv[1]
not in commands:
588 print(
'Expected one of: %s' %
', '.join(commands), file=sys.stderr)
590 return commands[sys.argv[1]](*sys.argv[2:])
593if __name__ ==
'__main__':
Type::kYUV Type::kRGBA() int(0.7 *637)
uint32_t uint32_t * format