Chromium Code Reviews| Index: win_toolchain/get_toolchain_if_necessary.py |
| diff --git a/win_toolchain/get_toolchain_if_necessary.py b/win_toolchain/get_toolchain_if_necessary.py |
| index 27fa18120dd11acf5903470bf8ef46758c0f279e..838805097cb01f7c8a311e97da12bc057ea29039 100755 |
| --- a/win_toolchain/get_toolchain_if_necessary.py |
| +++ b/win_toolchain/get_toolchain_if_necessary.py |
| @@ -26,10 +26,12 @@ future when a hypothetical VS2015 is released, the 2013 script will be |
| maintained, and a new 2015 script would be added. |
| """ |
| +import _winreg |
| import hashlib |
| import json |
| import optparse |
| import os |
| +import platform |
| import shutil |
| import subprocess |
| import sys |
| @@ -217,6 +219,74 @@ def DoTreeMirror(target_dir, tree_sha1): |
| RmDir(temp_dir) |
| +def GetInstallerName(): |
| + """Return the name of the Windows 10 Universal C Runtime installer for the |
| + current platform, or None if installer is not needed or not applicable. |
| + The registry has to be used instead of sys.getwindowsversion() because |
| + Python 2.7 is only manifested as being compatible up to Windows 8, so the |
| + version APIs helpfully return a maximum of 6.2 (Windows 8). |
| + """ |
| + key_name = r'Software\Microsoft\Windows NT\CurrentVersion' |
| + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key_name) |
| + value, keytype = _winreg.QueryValueEx(key, "CurrentVersion") |
| + key.Close() |
| + if keytype != _winreg.REG_SZ: |
| + raise Exception("Unexpected type in registry") |
| + if value == '6.1': |
| + # Windows 7 and Windows Server 2008 R2 |
| + return 'Windows6.1-KB2999226-x64.msu' |
| + elif value == '6.2': |
| + # Windows 8 and Windows Server 2012 |
| + return 'Windows8-RT-KB2999226-x64.msu' |
| + elif value == '6.3': |
| + # Windows 8.1, Windows Server 2012 R2, and Windows 10. |
| + # The Windows 8.1 installer doesn't work on Windows 10, but it will never |
| + # be used because the UCRT is always installed on Windows 10. |
| + return 'Windows8.1-KB2999226-x64.msu' |
| + else: |
| + # Some future OS. |
| + return None |
| + |
| + |
| +def InstallUniversalCRTIfNeeded(abs_target_dir): |
| + installer_name = GetInstallerName() |
| + if not installer_name: |
| + return |
| + |
| + bitness = platform.architecture()[0] |
| + # When running 64-bit python the x64 DLLs will be in System32 |
| + x64_path = 'System32' if bitness == '64bit' else 'Sysnative' |
| + x64_path = os.path.join(r'C:\Windows', x64_path) |
| + sample_crt_file = os.path.join(x64_path, 'ucrtbase.dll') |
| + |
| + if os.path.exists(sample_crt_file): |
| + # Nothing to do. |
| + return |
| + |
| + print ('%s does not exist - installing Windows 10 Universal C Runtime' % |
| + sample_crt_file) |
|
scottmg
2016/01/15 19:06:44
The indent should be after the (, aligned with '.
brucedawson
2016/01/15 19:16:46
Done.
|
| + |
| + installer = os.path.join(abs_target_dir, "installers", installer_name) |
| + command = r'wusa.exe /quiet "%s"' % installer |
| + print 'Running %s' % command |
| + |
| + try: |
| + subprocess.check_call(command) |
| + except WindowsError as e: |
| + if e.winerror == 740: # The requested operation requires elevation |
| + print '-'*80 |
| + print 'Elevation required. You must manually install this update:' |
| + print ' %s' % installer |
| + print '-'*80 |
| + raise Exception('Elevation required. You must manually install %s' % |
| + installer) |
| + raise e |
| + |
| + |
| def main(): |
| parser = optparse.OptionParser(description=sys.modules[__name__].__doc__) |
| parser.add_option('--output-json', metavar='FILE', |
| @@ -281,10 +351,15 @@ def main(): |
| sys.stdout.flush() |
| DelayBeforeRemoving(target_dir) |
| if sys.platform == 'win32': |
| - # This stays resident and will make the rmdir below fail. |
| - with open(os.devnull, 'wb') as nul: |
| - subprocess.call(['taskkill', '/f', '/im', 'mspdbsrv.exe'], |
| - stdin=nul, stdout=nul, stderr=nul) |
| + # These stay resident and will make the rmdir below fail. |
| + kill_list = [ |
| + 'mspdbsrv.exe', |
| + 'vctip.exe', # Compiler and tools experience improvement data uploader. |
| + ] |
| + for process_name in kill_list: |
| + with open(os.devnull, 'wb') as nul: |
| + subprocess.call(['taskkill', '/f', '/im', process_name], |
| + stdin=nul, stdout=nul, stderr=nul) |
| if os.path.isdir(target_dir): |
| RmDir(target_dir) |
| @@ -331,6 +406,9 @@ def main(): |
| shutil.copyfile(os.path.join(target_dir, '..', 'data.json'), |
| options.output_json) |
| + if os.environ.get('GYP_MSVS_VERSION') == '2015': |
| + InstallUniversalCRTIfNeeded(abs_target_dir) |
| + |
| return 0 |