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

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 _winreg, and add vctip.exe to kill list 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
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 and Windows Server 2012 R2
243 return 'Windows8.1-KB2999226-x64.msu'
244 else:
245 # Windows 10 or higher assumed
246 return None
247
248
249 def InstallUniversalCRTIfNeeded(abs_target_dir):
250 installer_name = GetInstallerName()
251 if not installer_name:
252 # Assumed to be Windows 10+ so nothing to do
253 return
254
255 bitness = platform.architecture()[0]
256 # When running 64-bit python the x64 DLLs will be in System32
257 x64_path = 'System32' if bitness == '64bit' else 'Sysnative'
258 x64_path = os.path.join(r'C:\Windows', x64_path)
259 sample_crt_file = os.path.join(x64_path, 'api-ms-win-crt-math-l1-1-0.dll')
260
261 if os.path.exists(sample_crt_file):
262 # Nothing to do.
263 return
264
265 print ('%s does not exist - installing Windows 10 Universal C Runtime' %
266 sample_crt_file)
267
268 installer = os.path.join(abs_target_dir, "installers", installer_name)
269 command = r'wusa.exe /quiet "%s"' % installer
270 print 'Running %s' % command
271
272 try:
273 subprocess.check_call(command)
274 except WindowsError as e:
275 if e.winerror == 740: # The requested operation requires elevation
276 print
277 print '-'*80
278 print
279 print 'Elevation required. You must manually install this update:'
280 print ' %s' % installer
281 print
282 print '-'*80
283 print
284 raise Exception('Elevation required. You must manually install %s' %
285 installer)
286 raise e
287
288
220 def main(): 289 def main():
221 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__) 290 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
222 parser.add_option('--output-json', metavar='FILE', 291 parser.add_option('--output-json', metavar='FILE',
223 help='write information about toolchain to FILE') 292 help='write information about toolchain to FILE')
224 parser.add_option('--force', action='store_true', 293 parser.add_option('--force', action='store_true',
225 help='force script to run on non-Windows hosts') 294 help='force script to run on non-Windows hosts')
226 options, args = parser.parse_args() 295 options, args = parser.parse_args()
227 296
228 if not (sys.platform.startswith(('cygwin', 'win32')) or options.force): 297 if not (sys.platform.startswith(('cygwin', 'win32')) or options.force):
229 return 0 298 return 0
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 print('\n\n\nPlease follow the instructions at ' 343 print('\n\n\nPlease follow the instructions at '
275 'https://www.chromium.org/developers/how-tos/' 344 'https://www.chromium.org/developers/how-tos/'
276 'build-instructions-windows\n\n') 345 'build-instructions-windows\n\n')
277 return 1 346 return 1
278 print('Windows toolchain out of date or doesn\'t exist, updating (Pro)...') 347 print('Windows toolchain out of date or doesn\'t exist, updating (Pro)...')
279 print(' current_hash: %s' % current_hash) 348 print(' current_hash: %s' % current_hash)
280 print(' desired_hashes: %s' % ', '.join(desired_hashes)) 349 print(' desired_hashes: %s' % ', '.join(desired_hashes))
281 sys.stdout.flush() 350 sys.stdout.flush()
282 DelayBeforeRemoving(target_dir) 351 DelayBeforeRemoving(target_dir)
283 if sys.platform == 'win32': 352 if sys.platform == 'win32':
284 # This stays resident and will make the rmdir below fail. 353 # These stay resident and will make the rmdir below fail.
285 with open(os.devnull, 'wb') as nul: 354 kill_list = [
286 subprocess.call(['taskkill', '/f', '/im', 'mspdbsrv.exe'], 355 'mspdbsrv.exe',
287 stdin=nul, stdout=nul, stderr=nul) 356 'vctip.exe', # compiler and tools experience improvement data uploader
scottmg 2016/01/14 22:45:11 compiler -> Compiler and end with a '.'.
brucedawson 2016/01/15 00:10:31 Done.
357 ]
358 for process_name in kill_list:
359 with open(os.devnull, 'wb') as nul:
360 subprocess.call(['taskkill', '/f', '/im', process_name],
361 stdin=nul, stdout=nul, stderr=nul)
288 if os.path.isdir(target_dir): 362 if os.path.isdir(target_dir):
289 RmDir(target_dir) 363 RmDir(target_dir)
290 364
291 DoTreeMirror(target_dir, desired_hashes[0]) 365 DoTreeMirror(target_dir, desired_hashes[0])
292 366
293 got_new_toolchain = True 367 got_new_toolchain = True
294 368
295 win_sdk = os.path.join(abs_target_dir, 'win_sdk') 369 win_sdk = os.path.join(abs_target_dir, 'win_sdk')
296 try: 370 try:
297 with open(os.path.join(target_dir, 'VS_VERSION'), 'rb') as f: 371 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. ' 398 'Got wrong hash after pulling a new toolchain. '
325 'Wanted one of \'%s\', got \'%s\'.' % ( 399 'Wanted one of \'%s\', got \'%s\'.' % (
326 ', '.join(desired_hashes), current_hash)) 400 ', '.join(desired_hashes), current_hash))
327 return 1 401 return 1
328 SaveTimestampsAndHash(target_dir, current_hash) 402 SaveTimestampsAndHash(target_dir, current_hash)
329 403
330 if options.output_json: 404 if options.output_json:
331 shutil.copyfile(os.path.join(target_dir, '..', 'data.json'), 405 shutil.copyfile(os.path.join(target_dir, '..', 'data.json'),
332 options.output_json) 406 options.output_json)
333 407
408 InstallUniversalCRTIfNeeded(abs_target_dir)
409
334 return 0 410 return 0
335 411
336 412
337 if __name__ == '__main__': 413 if __name__ == '__main__':
338 sys.exit(main()) 414 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | win_toolchain/package_from_installed.py » ('j') | win_toolchain/package_from_installed.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698