Package/Install the Windows 10 Universal C Runtime for VS 2015

The VS 2015 tools require the Windows 10 Universal C Runtime, either
installed in C:\Windows or in every directory containing tools, or
dynamically linked executables created with VS 2015. Installing to
C:\Windows seems less error prone.

This is only applicable for Google developers and build machines that
don't have VS 2015 installed.

This updates the packaging script so that it packages the three
installers, and no longer packages the installed files (which vary
between operating systems anyway).

The installer is updated to check for the existence of one of the
Universal C Runtime files. If it isn't found then it detects the
version of Windows in order to select and run the correct installer.

I manually confirmed that, for instance, the installers for Windows 7
and Windows 2008 R2, were identical despite coming from different
download URLs.

If the installation fails because gclient runhooks is run non-elevated
then the developer will have to do a one-time manual install of the
update. A message will be printed indicating this.

BUG=440500

Review URL: https://codereview.chromium.org/1588673004

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@298286 0039d316-1c4b-4281-b951-d872f2087c98
parent a83663a0
......@@ -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,75 @@ 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)
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)
# Trap OSError instead of WindowsError so pylint will succeed on Linux.
except OSError as e:
if e.winerror == 740: # The requested operation requires elevation
print
print '-'*80
print
print 'Elevation required. You must manually install this update:'
print ' %s' % installer
print
print '-'*80
print
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 +352,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 +407,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
......
......@@ -133,32 +133,26 @@ def BuildFileList():
result.append((combined, to))
if VS_VERSION == '2015':
# The Windows 10 Universal C Runtime installers are needed when packaging
# VS 2015. They can be download from here:
# https://support.microsoft.com/en-us/kb/2999226
# and they must be downloaded to the current user's downloads directory.
# The versions needed are those for 64-bit Windows 7, Windows 8, and
# Windows 8.1. The 64-bit Server 2008 R2, Server 2012, and Server 2012 R2
# versions are identical (same name and contents).
universal_runtime_installers = [
'Windows6.1-KB2999226-x64.msu',
'Windows8-RT-KB2999226-x64.msu',
'Windows8.1-KB2999226-x64.msu',
]
for installer in universal_runtime_installers:
result.append((os.path.join(os.environ['userprofile'], 'downloads',
installer),
os.path.join('installers', installer)))
system_crt_files = [
'api-ms-win-core-file-l1-2-0.dll',
'api-ms-win-core-file-l2-1-0.dll',
'api-ms-win-core-localization-l1-2-0.dll',
'api-ms-win-core-processthreads-l1-1-1.dll',
'api-ms-win-core-synch-l1-2-0.dll',
'api-ms-win-core-timezone-l1-1-0.dll',
'api-ms-win-core-xstate-l2-1-0.dll',
'api-ms-win-crt-conio-l1-1-0.dll',
'api-ms-win-crt-convert-l1-1-0.dll',
'api-ms-win-crt-environment-l1-1-0.dll',
'api-ms-win-crt-filesystem-l1-1-0.dll',
'api-ms-win-crt-heap-l1-1-0.dll',
'api-ms-win-crt-locale-l1-1-0.dll',
'api-ms-win-crt-math-l1-1-0.dll',
'api-ms-win-crt-multibyte-l1-1-0.dll',
'api-ms-win-crt-private-l1-1-0.dll',
'api-ms-win-crt-process-l1-1-0.dll',
'api-ms-win-crt-runtime-l1-1-0.dll',
'api-ms-win-crt-stdio-l1-1-0.dll',
'api-ms-win-crt-string-l1-1-0.dll',
'api-ms-win-crt-time-l1-1-0.dll',
'api-ms-win-crt-utility-l1-1-0.dll',
'api-ms-win-eventing-provider-l1-1-0.dll',
'ucrtbase.dll',
# Needed to let debug binaries run.
'ucrtbased.dll',
]
bitness = platform.architecture()[0]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment