Flutter Engine
The Flutter Engine
vs_toolchain.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# Copyright 2014 The Chromium Authors
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6
7import collections
8import glob
9import json
10import os
11import platform
12import re
13import shutil
14import stat
15import subprocess
16import sys
17
18from gn_helpers import ToGNString
19
20# VS 2022 17.4 with 10.0.22621.0 SDK with ARM64 libraries and UWP support.
21# See go/chromium-msvc-toolchain for instructions about how to update the
22# toolchain.
23#
24# When updating the toolchain, consider the following areas impacted by the
25# toolchain version:
26#
27# * //base/win/windows_version.cc NTDDI preprocessor check
28# Triggers a compiler error if the available SDK is older than the minimum.
29# * SDK_VERSION in this file
30# Must match the packaged/required SDK version.
31# * SDK_VERSION in build/toolchain/win/setup_toolchain.py.
32# * //build/config/win/BUILD.gn NTDDI_VERSION value
33# Affects the availability of APIs in the toolchain headers.
34# * //docs/windows_build_instructions.md mentions of VS or Windows SDK.
35# Keeps the document consistent with the toolchain version.
36# * //tools/win/setenv.py
37# Add/remove VS versions when upgrading to a new VS version.
38# * MSVC_TOOLSET_VERSION in this file
39# Maps between Visual Studio version and MSVC toolset
40# * MSVS_VERSIONS in this file
41# Records the packaged and default version of Visual Studio
42TOOLCHAIN_HASH = '27370823e7'
43SDK_VERSION = '10.0.22621.0'
44
45script_dir = os.path.dirname(os.path.realpath(__file__))
46json_data_file = os.path.join(script_dir, 'win_toolchain.json')
47
48# VS versions are listed in descending order of priority (highest first).
49# The first version is assumed by this script to be the one that is packaged,
50# which makes a difference for the arm64 runtime.
51MSVS_VERSIONS = collections.OrderedDict([
52 ('2022', '17.0'), # Default and packaged version of Visual Studio.
53 ('2019', '16.0'),
54 ('2017', '15.0'),
55])
56
57# List of preferred VC toolset version based on MSVS
58# Order is not relevant for this dictionary.
59MSVC_TOOLSET_VERSION = {
60 '2022': 'VC143',
61 '2019': 'VC142',
62 '2017': 'VC141',
63}
64
65def _HostIsWindows():
66 """Returns True if running on a Windows host (including under cygwin)."""
67 return sys.platform in ('win32', 'cygwin')
68
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.
73
74 Return value is [x64path, x86path, 'Arm64Unused'] or None. arm64path is
75 generated separately because there are multiple folders for the arm64 VC
76 runtime.
77 """
78 vs_runtime_dll_dirs = None
79 depot_tools_win_toolchain = \
80 bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
81 # When running on a non-Windows host, only do this if the SDK has explicitly
82 # been downloaded before (in which case json_data_file will exist).
83 if ((_HostIsWindows() or os.path.exists(json_data_file))
84 and depot_tools_win_toolchain):
86 if len(sys.argv) > 1 and sys.argv[1] == 'update':
87 update_result = Update()
88 else:
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)
94
95 toolchain = toolchain_data['path']
96 version = toolchain_data['version']
97 win_sdk = toolchain_data.get('win_sdk')
98 wdk = toolchain_data['wdk']
99 # TODO(scottmg): The order unfortunately matters in these. They should be
100 # split into separate keys for x64/x86/arm64. (See CopyDlls call below).
101 # http://crbug.com/345992
102 vs_runtime_dll_dirs = toolchain_data['runtime_dirs']
103 # The number of runtime_dirs in the toolchain_data was two (x64/x86) but
104 # changed to three (x64/x86/arm64) and this code needs to handle both
105 # possibilities, which can change independently from this code.
106 if len(vs_runtime_dll_dirs) == 2:
107 vs_runtime_dll_dirs.append('Arm64Unused')
108
109 os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain
110
111 os.environ['WINDOWSSDKDIR'] = win_sdk
112 os.environ['WDK_DIR'] = wdk
113 # Include the VS runtime in the PATH in case it's not machine-installed.
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:
118 os.environ['GYP_MSVS_OVERRIDE_PATH'] = DetectVisualStudioPath()
119
120 # When using an installed toolchain these files aren't needed in the output
121 # directory in order to run binaries locally, but they are needed in order
122 # to create isolates or the mini_installer. Copying them to the output
123 # directory ensures that they are available when needed.
124 bitness = platform.architecture()[0]
125 # When running 64-bit python the x64 DLLs will be in System32
126 # ARM64 binaries will not be available in the system directories because we
127 # don't build on ARM64 machines.
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%'),
132 'SysWOW64'),
133 'Arm64Unused']
134
135 return vs_runtime_dll_dirs
136
137
138def _RegistryGetValueUsingWinReg(key, value):
139 """Use the _winreg module to obtain the value of a registry key.
140
141 Args:
142 key: The registry key.
143 value: The particular registry value to read.
144 Return:
145 contents of the registry key's value, or None on failure. Throws
146 ImportError if _winreg is unavailable.
147 """
148 import _winreg
149 try:
150 root, subkey = key.split('\\', 1)
151 assert root == 'HKLM' # Only need HKLM for now.
152 with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey) as hkey:
153 return _winreg.QueryValueEx(hkey, value)[0]
154 except WindowsError:
155 return None
156
157
158def _RegistryGetValue(key, value):
159 try:
160 return _RegistryGetValueUsingWinReg(key, value)
161 except ImportError:
162 raise Exception('The python library _winreg not found.')
163
164
166 """Return best available version of Visual Studio.
167 """
168 supported_versions = list(MSVS_VERSIONS.keys())
169
170 # VS installed in depot_tools for Googlers
171 if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))):
172 return supported_versions[0]
173
174 # VS installed in system for external developers
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:
179 # Checking vs%s_install environment variables.
180 # For example, vs2019_install could have the value
181 # "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community".
182 # Only vs2017_install, vs2019_install and vs2022_install are supported.
183 path = os.environ.get('vs%s_install' % version)
184 if path and os.path.exists(path):
185 available_versions.append(version)
186 break
187 # Detecting VS under possible paths.
188 if version >= '2022':
189 program_files_path_variable = '%ProgramFiles%'
190 else:
191 program_files_path_variable = '%ProgramFiles(x86)%'
192 path = os.path.expandvars(program_files_path_variable +
193 '/Microsoft Visual Studio/%s' % version)
194 if path and any(
195 os.path.exists(os.path.join(path, edition))
196 for edition in ('Enterprise', 'Professional', 'Community', 'Preview',
197 'BuildTools')):
198 available_versions.append(version)
199 break
200
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]
205
206
208 """Return path to the installed Visual Studio.
209 """
210
211 # Note that this code is used from
212 # build/toolchain/win/setup_toolchain.py as well.
213 version_as_year = GetVisualStudioVersion()
214
215 # The VC++ >=2017 install location needs to be located using COM instead of
216 # the registry. For details see:
217 # https://blogs.msdn.microsoft.com/heaths/2016/09/15/changes-to-visual-studio-15-setup/
218 # For now we use a hardcoded default with an environment variable override.
219 if version_as_year >= '2022':
220 program_files_path_variable = '%ProgramFiles%'
221 else:
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' %
226 version_as_year),
227 os.path.expandvars(program_files_path_variable +
228 '/Microsoft Visual Studio/%s/Professional' %
229 version_as_year),
230 os.path.expandvars(program_files_path_variable +
231 '/Microsoft Visual Studio/%s/Community' %
232 version_as_year),
233 os.path.expandvars(program_files_path_variable +
234 '/Microsoft Visual Studio/%s/Preview' %
235 version_as_year),
236 os.path.expandvars(program_files_path_variable +
237 '/Microsoft Visual Studio/%s/BuildTools' %
238 version_as_year)):
239 if path and os.path.exists(path):
240 return path
241
242 raise Exception('Visual Studio Version %s not found.' % version_as_year)
243
244
245def _CopyRuntimeImpl(target, source, verbose=True):
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).
250 """
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)):
254 if verbose:
255 print('Copying %s to %s...' % (source, target))
256 if os.path.exists(target):
257 # Make the file writable so that we can delete it now, and keep it
258 # readable.
259 os.chmod(target, stat.S_IWRITE | stat.S_IREAD)
260 os.unlink(target)
261 shutil.copy2(source, target)
262 # Make the file writable so that we can overwrite or delete it later,
263 # keep it readable.
264 os.chmod(target, stat.S_IWRITE | stat.S_IREAD)
265
266def _SortByHighestVersionNumberFirst(list_of_str_versions):
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.
271 """
272 def to_int_if_int(x):
273 try:
274 return int(x)
275 except ValueError:
276 return x
277
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]
281
282 list_of_str_versions.sort(key=to_number_sequence, reverse=True)
283
284
285def _CopyUCRTRuntime(target_dir, source_dir, target_cpu, suffix):
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':
289 # Windows ARM64 VCRuntime is located at {toolchain_root}/VC/Redist/MSVC/
290 # {x.y.z}/[debug_nonredist/]arm64/Microsoft.VC14x.CRT/.
291 # Select VC toolset directory based on Visual Studio version
292 vc_redist_root = FindVCRedistRoot()
293 if suffix.startswith('.'):
294 vc_toolset_dir = 'Microsoft.{}.CRT' \
295 .format(MSVC_TOOLSET_VERSION[GetVisualStudioVersion()])
296 source_dir = os.path.join(vc_redist_root,
297 'arm64', vc_toolset_dir)
298 else:
299 vc_toolset_dir = 'Microsoft.{}.DebugCRT' \
300 .format(MSVC_TOOLSET_VERSION[GetVisualStudioVersion()])
301 source_dir = os.path.join(vc_redist_root, 'debug_nonredist',
302 'arm64', vc_toolset_dir)
303 file_parts = ('msvcp140', 'vccorlib140', 'vcruntime140')
304 if target_cpu == 'x64' and GetVisualStudioVersion() != '2017':
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)
310 _CopyRuntimeImpl(target, source)
311 # We must copy ucrtbased.dll for all CPU types. The rest of the Universal CRT
312 # is installed as part of the OS in Windows 10 and beyond.
313 if not suffix.startswith('.'):
314 win_sdk_dir = os.path.normpath(
315 os.environ.get(
316 'WINDOWSSDKDIR',
317 os.path.expandvars('%ProgramFiles(x86)%'
318 '\\Windows Kits\\10')))
319 # ucrtbased.dll is located at {win_sdk_dir}/bin/{a.b.c.d}/{target_cpu}/
320 # ucrt/.
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.*'))
323 # Select the most recent SDK if there are multiple versions installed.
324 _SortByHighestVersionNumberFirst(sdk_bin_sub_dirs)
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):
328 continue
329 source_dir = os.path.join(sdk_redist_root_version, target_cpu, 'ucrt')
330 if not os.path.isdir(source_dir):
331 continue
332 break
333 _CopyRuntimeImpl(os.path.join(target_dir, 'ucrtbase' + suffix),
334 os.path.join(source_dir, 'ucrtbase' + suffix))
335
336
337def FindVCComponentRoot(component):
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
341 used.
342 """
343
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.*'))
350 # Select the most recent toolchain if there are several.
351 _SortByHighestVersionNumberFirst(vc_component_msvc_contents)
352 for directory in vc_component_msvc_contents:
353 if os.path.isdir(directory):
354 return directory
355 raise Exception('Unable to find the VC %s directory.' % component)
356
357
359 """In >=VS2017, Redist binaries are located in
360 {toolchain_root}/VC/Redist/MSVC/{x.y.z}/{target_cpu}/.
361
362 This returns the '{toolchain_root}/VC/Redist/MSVC/{x.y.z}/' path.
363 """
364 return FindVCComponentRoot('Redist')
365
366
367def _CopyRuntime(target_dir, source_dir, target_cpu, debug):
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'
371 # VS 2015, 2017 and 2019 use the same CRT DLLs.
372 _CopyUCRTRuntime(target_dir, source_dir, target_cpu, suffix)
373
374
375def CopyDlls(target_dir, configuration, target_cpu):
376 """Copy the VS runtime DLLs into the requested directory as needed.
377
378 configuration is one of 'Debug' or 'Release'.
379 target_cpu is one of 'x86', 'x64' or 'arm64'.
380
381 The debug configuration gets both the debug and release DLLs; the
382 release config only the latter.
383 """
384 vs_runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
385 if not vs_runtime_dll_dirs:
386 return
387
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
395 else:
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)
400 _CopyDebugger(target_dir, target_cpu)
401 if target_cpu == 'arm64':
402 target_dir = os.path.join(target_dir, 'win_clang_x64')
403 target_cpu = '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)
409 _CopyDebugger(target_dir, target_cpu)
410
411
412def _CopyDebugger(target_dir, target_cpu):
413 """Copy dbghelp.dll, dbgcore.dll, and msdia140.dll into the requested
414 directory.
415
416 target_cpu is one of 'x86', 'x64' or 'arm64'.
417
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").
423
424 dbgcore.dll is needed when using some functions from dbghelp.dll (like
425 MinidumpWriteDump).
426
427 msdia140.dll is needed for tools like symupload.exe and dump_syms.exe.
428 """
429 win_sdk_dir = SetEnvironmentAndGetSDKDir()
430 if not win_sdk_dir:
431 return
432
433 # List of debug files that should be copied, the first element of the tuple is
434 # the name of the file and the second indicates if it's optional.
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):
439 if is_optional:
440 continue
441 else:
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)
447 _CopyRuntimeImpl(target_path, full_path)
448
449 # The x64 version of msdia140.dll is always used because symupload and
450 # dump_syms are always built as x64 binaries.
451 dia_path = os.path.join(NormalizePath(os.environ['GYP_MSVS_OVERRIDE_PATH']),
452 'DIA SDK', 'bin', 'amd64', 'msdia140.dll')
453 _CopyRuntimeImpl(os.path.join(target_dir, 'msdia140.dll'), dia_path)
454
455
456def _GetDesiredVsToolchainHashes():
457 """Load a list of SHA1s corresponding to the toolchains that we want installed
458 to build with."""
459 # Third parties that do not have access to the canonical toolchain can map
460 # canonical toolchain version to their own toolchain versions.
461 toolchain_hash_mapping_key = 'GYP_MSVS_HASH_%s' % TOOLCHAIN_HASH
462 return [os.environ.get(toolchain_hash_mapping_key, TOOLCHAIN_HASH)]
463
464
466 """Check if the toolchain should be upgraded."""
467 if not os.path.exists(json_data_file):
468 return True
469 with open(json_data_file, 'r') as tempf:
470 toolchain_data = json.load(tempf)
471 version = toolchain_data['version']
472 env_version = GetVisualStudioVersion()
473 # If there's a mismatch between the version set in the environment and the one
474 # in the json file then the toolchain should be updated.
475 return version != env_version
476
477
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.
484 """
485 if force != False and force != '--force':
486 print('Unknown parameter "%s"' % force, file=sys.stderr)
487 return 1
488 if force == '--force' or os.path.exists(json_data_file):
489 force = True
490
491 depot_tools_win_toolchain = \
492 bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
493 if (_HostIsWindows() or force) and depot_tools_win_toolchain:
494 import find_depot_tools
496
497 # On Linux, the file system is usually case-sensitive while the Windows
498 # SDK only works on case-insensitive file systems. If it doesn't already
499 # exist, set up a ciopfs fuse mount to put the SDK in a case-insensitive
500 # part of the file system.
501 toolchain_dir = os.path.join(depot_tools_path, 'win_toolchain', 'vs_files')
502 # For testing this block, unmount existing mounts with
503 # fusermount -u third_party/depot_tools/win_toolchain/vs_files
504 if sys.platform.startswith('linux') and not os.path.ismount(toolchain_dir):
505 ciopfs = shutil.which('ciopfs')
506 if not ciopfs:
507 # ciopfs not found in PATH; try the one downloaded from the DEPS hook.
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')
513 # Without use_ino, clang's #pragma once and Wnonportable-include-path
514 # both don't work right, see https://llvm.org/PR34931
515 # use_ino doesn't slow down builds, so it seems there's no drawback to
516 # just using it always.
517 subprocess.check_call([
518 ciopfs, '-o', 'use_ino', toolchain_dir + '.ciopfs', toolchain_dir])
519
520 # Dart specific patch: Store the visual studio toolchain inside the exec
521 # root directory such that it can be sent to RBE and invoked with a
522 # relative path identical on all checkouts.
523 toolchain_dir = os.path.join(os.getcwd(), 'sdk', 'win_toolchain')
524 get_toolchain_args = [
525 sys.executable,
526 os.path.join(depot_tools_path,
527 'win_toolchain',
528 'get_toolchain_if_necessary.py'),
529 '--output-json', json_data_file,
530 '--toolchain-dir', toolchain_dir,
531 ] + _GetDesiredVsToolchainHashes()
532 if force:
533 get_toolchain_args.append('--force')
534 if no_download:
535 get_toolchain_args.append('--no-download')
536 subprocess.check_call(get_toolchain_args)
537
538 return 0
539
540
542 while path.endswith('\\'):
543 path = path[:-1]
544 return path
545
546
548 """Gets location information about the current sdk (must have been
549 previously updated by 'update'). This is used for the GN build."""
551
552 # If WINDOWSSDKDIR is not set, search the default SDK path and set it.
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
558
559 return NormalizePath(os.environ['WINDOWSSDKDIR'])
560
561
563 """Gets location information about the current toolchain (must have been
564 previously updated by 'update'). This is used for the GN build."""
565 runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
566 win_sdk_dir = SetEnvironmentAndGetSDKDir()
567
568 print('''vs_path = %s
569sdk_version = %s
570sdk_path = %s
571vs_version = %s
572wdk_dir = %s
573runtime_dirs = %s
575 os.environ['GYP_MSVS_OVERRIDE_PATH'])), ToGNString(SDK_VERSION),
577 ToGNString(NormalizePath(os.environ.get('WDK_DIR', ''))),
578 ToGNString(os.path.pathsep.join(runtime_dll_dirs or ['None']))))
579
580
581def main():
582 commands = {
583 'update': Update,
584 'get_toolchain_dir': GetToolchainDir,
585 'copy_dlls': CopyDlls,
586 }
587 if len(sys.argv) < 2 or sys.argv[1] not in commands:
588 print('Expected one of: %s' % ', '.join(commands), file=sys.stderr)
589 return 1
590 return commands[sys.argv[1]](*sys.argv[2:])
591
592
593if __name__ == '__main__':
594 sys.exit(main())
uint32_t uint32_t * format
def ToGNString(value, allow_dicts=True)
Definition: gn_helpers.py:30
Definition: main.py:1
def print(*args, **kwargs)
Definition: run_tests.py:49
SIN Vec< N, float > abs(const Vec< N, float > &x)
Definition: SkVx.h:707
SIT bool any(const Vec< 1, T > &x)
Definition: SkVx.h:530
def FindVCRedistRoot()
def NormalizePath(path)
def DetectVisualStudioPath()
def SetEnvironmentAndGetRuntimeDllDirs()
Definition: vs_toolchain.py:69
def Update(force=False, no_download=False)
def CopyDlls(target_dir, configuration, target_cpu)
def GetVisualStudioVersion()
def ShouldUpdateToolchain()
def SetEnvironmentAndGetSDKDir()
def FindVCComponentRoot(component)
def GetToolchainDir()
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741