Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(996)

Side by Side Diff: win_toolchain/get_toolchain_if_necessary.py

Issue 1588673004: Package/Install the Windows 10 Universal C Runtime for VS 2015 (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Use OSError instead of WindowsError for pylint on Linux Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | win_toolchain/package_from_installed.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2013 The Chromium Authors. All rights reserved. 2 # Copyright 2013 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Downloads and unpacks a toolchain for building on Windows. The contents are 6 """Downloads and unpacks a toolchain for building on Windows. The contents are
7 matched by sha1 which will be updated when the toolchain is updated. 7 matched by sha1 which will be updated when the toolchain is updated.
8 8
9 Having a toolchain script in depot_tools means that it's not versioned 9 Having a toolchain script in depot_tools means that it's not versioned
10 directly with the source code. That is, if the toolchain is upgraded, but 10 directly with the source code. That is, if the toolchain is upgraded, but
11 you're trying to build an historical version of Chromium from before the 11 you're trying to build an historical version of Chromium from before the
12 toolchain upgrade, this will cause you to build with a newer toolchain than 12 toolchain upgrade, this will cause you to build with a newer toolchain than
13 was available when that code was committed. This is done for a two main 13 was available when that code was committed. This is done for a two main
14 reasons: 1) it would likely be annoying to have the up-to-date toolchain 14 reasons: 1) it would likely be annoying to have the up-to-date toolchain
15 removed and replaced by one without a service pack applied); 2) it would 15 removed and replaced by one without a service pack applied); 2) it would
16 require maintaining scripts that can build older not-up-to-date revisions of 16 require maintaining scripts that can build older not-up-to-date revisions of
17 the toolchain. This is likely to be a poorly tested code path that probably 17 the toolchain. This is likely to be a poorly tested code path that probably
18 won't be properly maintained. See http://crbug.com/323300. 18 won't be properly maintained. See http://crbug.com/323300.
19 19
20 This does not extend to major versions of the toolchain however, on the 20 This does not extend to major versions of the toolchain however, on the
21 assumption that there are more likely to be source incompatibilities between 21 assumption that there are more likely to be source incompatibilities between
22 major revisions. This script calls a subscript (currently, toolchain2013.py) 22 major revisions. This script calls a subscript (currently, toolchain2013.py)
23 to do the main work. It is expected that toolchain2013.py will always be able 23 to do the main work. It is expected that toolchain2013.py will always be able
24 to acquire/build the most current revision of a VS2013-based toolchain. In the 24 to acquire/build the most current revision of a VS2013-based toolchain. In the
25 future when a hypothetical VS2015 is released, the 2013 script will be 25 future when a hypothetical VS2015 is released, the 2013 script will be
26 maintained, and a new 2015 script would be added. 26 maintained, and a new 2015 script would be added.
27 """ 27 """
28 28
29 import _winreg
29 import hashlib 30 import hashlib
30 import json 31 import json
31 import optparse 32 import optparse
32 import os 33 import os
34 import platform
33 import shutil 35 import shutil
34 import subprocess 36 import subprocess
35 import sys 37 import sys
36 import tempfile 38 import tempfile
37 import time 39 import time
38 import zipfile 40 import zipfile
39 41
40 42
41 BASEDIR = os.path.dirname(os.path.abspath(__file__)) 43 BASEDIR = os.path.dirname(os.path.abspath(__file__))
42 DEPOT_TOOLS_PATH = os.path.join(BASEDIR, '..') 44 DEPOT_TOOLS_PATH = os.path.join(BASEDIR, '..')
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 else: 212 else:
211 temp_dir, local_zip = DownloadUsingGsutil(tree_sha1 + '.zip') 213 temp_dir, local_zip = DownloadUsingGsutil(tree_sha1 + '.zip')
212 sys.stdout.write('Extracting %s...\n' % local_zip) 214 sys.stdout.write('Extracting %s...\n' % local_zip)
213 sys.stdout.flush() 215 sys.stdout.flush()
214 with zipfile.ZipFile(local_zip, 'r', zipfile.ZIP_DEFLATED, True) as zf: 216 with zipfile.ZipFile(local_zip, 'r', zipfile.ZIP_DEFLATED, True) as zf:
215 zf.extractall(target_dir) 217 zf.extractall(target_dir)
216 if temp_dir: 218 if temp_dir:
217 RmDir(temp_dir) 219 RmDir(temp_dir)
218 220
219 221
222 def GetInstallerName():
223 """Return the name of the Windows 10 Universal C Runtime installer for the
224 current platform, or None if installer is not needed or not applicable.
225 The registry has to be used instead of sys.getwindowsversion() because
226 Python 2.7 is only manifested as being compatible up to Windows 8, so the
227 version APIs helpfully return a maximum of 6.2 (Windows 8).
228 """
229 key_name = r'Software\Microsoft\Windows NT\CurrentVersion'
230 key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key_name)
231 value, keytype = _winreg.QueryValueEx(key, "CurrentVersion")
232 key.Close()
233 if keytype != _winreg.REG_SZ:
234 raise Exception("Unexpected type in registry")
235 if value == '6.1':
236 # Windows 7 and Windows Server 2008 R2
237 return 'Windows6.1-KB2999226-x64.msu'
238 elif value == '6.2':
239 # Windows 8 and Windows Server 2012
240 return 'Windows8-RT-KB2999226-x64.msu'
241 elif value == '6.3':
242 # Windows 8.1, Windows Server 2012 R2, and Windows 10.
243 # The Windows 8.1 installer doesn't work on Windows 10, but it will never
244 # be used because the UCRT is always installed on Windows 10.
245 return 'Windows8.1-KB2999226-x64.msu'
246 else:
247 # Some future OS.
248 return None
249
250
251 def InstallUniversalCRTIfNeeded(abs_target_dir):
252 installer_name = GetInstallerName()
253 if not installer_name:
254 return
255
256 bitness = platform.architecture()[0]
257 # When running 64-bit python the x64 DLLs will be in System32
258 x64_path = 'System32' if bitness == '64bit' else 'Sysnative'
259 x64_path = os.path.join(r'C:\Windows', x64_path)
260 sample_crt_file = os.path.join(x64_path, 'ucrtbase.dll')
261
262 if os.path.exists(sample_crt_file):
263 # Nothing to do.
264 return
265
266 print ('%s does not exist - installing Windows 10 Universal C Runtime' %
267 sample_crt_file)
268
269 installer = os.path.join(abs_target_dir, "installers", installer_name)
270 command = r'wusa.exe /quiet "%s"' % installer
271 print 'Running %s' % command
272
273 try:
274 subprocess.check_call(command)
275 # Trap OSError instead of WindowsError so pylint will succeed on Linux.
276 except OSError as e:
277 if e.winerror == 740: # The requested operation requires elevation
278 print
279 print '-'*80
280 print
281 print 'Elevation required. You must manually install this update:'
282 print ' %s' % installer
283 print
284 print '-'*80
285 print
286 raise Exception('Elevation required. You must manually install %s' %
287 installer)
288 raise e
289
290
220 def main(): 291 def main():
221 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__) 292 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
222 parser.add_option('--output-json', metavar='FILE', 293 parser.add_option('--output-json', metavar='FILE',
223 help='write information about toolchain to FILE') 294 help='write information about toolchain to FILE')
224 parser.add_option('--force', action='store_true', 295 parser.add_option('--force', action='store_true',
225 help='force script to run on non-Windows hosts') 296 help='force script to run on non-Windows hosts')
226 options, args = parser.parse_args() 297 options, args = parser.parse_args()
227 298
228 if not (sys.platform.startswith(('cygwin', 'win32')) or options.force): 299 if not (sys.platform.startswith(('cygwin', 'win32')) or options.force):
229 return 0 300 return 0
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 print('\n\n\nPlease follow the instructions at ' 345 print('\n\n\nPlease follow the instructions at '
275 'https://www.chromium.org/developers/how-tos/' 346 'https://www.chromium.org/developers/how-tos/'
276 'build-instructions-windows\n\n') 347 'build-instructions-windows\n\n')
277 return 1 348 return 1
278 print('Windows toolchain out of date or doesn\'t exist, updating (Pro)...') 349 print('Windows toolchain out of date or doesn\'t exist, updating (Pro)...')
279 print(' current_hash: %s' % current_hash) 350 print(' current_hash: %s' % current_hash)
280 print(' desired_hashes: %s' % ', '.join(desired_hashes)) 351 print(' desired_hashes: %s' % ', '.join(desired_hashes))
281 sys.stdout.flush() 352 sys.stdout.flush()
282 DelayBeforeRemoving(target_dir) 353 DelayBeforeRemoving(target_dir)
283 if sys.platform == 'win32': 354 if sys.platform == 'win32':
284 # This stays resident and will make the rmdir below fail. 355 # These stay resident and will make the rmdir below fail.
285 with open(os.devnull, 'wb') as nul: 356 kill_list = [
286 subprocess.call(['taskkill', '/f', '/im', 'mspdbsrv.exe'], 357 'mspdbsrv.exe',
287 stdin=nul, stdout=nul, stderr=nul) 358 'vctip.exe', # Compiler and tools experience improvement data uploader.
359 ]
360 for process_name in kill_list:
361 with open(os.devnull, 'wb') as nul:
362 subprocess.call(['taskkill', '/f', '/im', process_name],
363 stdin=nul, stdout=nul, stderr=nul)
288 if os.path.isdir(target_dir): 364 if os.path.isdir(target_dir):
289 RmDir(target_dir) 365 RmDir(target_dir)
290 366
291 DoTreeMirror(target_dir, desired_hashes[0]) 367 DoTreeMirror(target_dir, desired_hashes[0])
292 368
293 got_new_toolchain = True 369 got_new_toolchain = True
294 370
295 win_sdk = os.path.join(abs_target_dir, 'win_sdk') 371 win_sdk = os.path.join(abs_target_dir, 'win_sdk')
296 try: 372 try:
297 with open(os.path.join(target_dir, 'VS_VERSION'), 'rb') as f: 373 with open(os.path.join(target_dir, 'VS_VERSION'), 'rb') as f:
(...skipping 26 matching lines...) Expand all
324 'Got wrong hash after pulling a new toolchain. ' 400 'Got wrong hash after pulling a new toolchain. '
325 'Wanted one of \'%s\', got \'%s\'.' % ( 401 'Wanted one of \'%s\', got \'%s\'.' % (
326 ', '.join(desired_hashes), current_hash)) 402 ', '.join(desired_hashes), current_hash))
327 return 1 403 return 1
328 SaveTimestampsAndHash(target_dir, current_hash) 404 SaveTimestampsAndHash(target_dir, current_hash)
329 405
330 if options.output_json: 406 if options.output_json:
331 shutil.copyfile(os.path.join(target_dir, '..', 'data.json'), 407 shutil.copyfile(os.path.join(target_dir, '..', 'data.json'),
332 options.output_json) 408 options.output_json)
333 409
410 if os.environ.get('GYP_MSVS_VERSION') == '2015':
411 InstallUniversalCRTIfNeeded(abs_target_dir)
412
334 return 0 413 return 0
335 414
336 415
337 if __name__ == '__main__': 416 if __name__ == '__main__':
338 sys.exit(main()) 417 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | win_toolchain/package_from_installed.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698