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

Side by Side Diff: win_toolchain/get_toolchain_if_necessary.py

Issue 135933002: Automatic Windows toolchain (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: extract whole iso Created 6 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
(Empty)
1 # Copyright 2013 The Chromium Authors. All rights reserved.
M-A Ruel 2014/01/13 18:29:05 shebang + +x too.
scottmg 2014/01/13 18:46:18 Done.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """Downloads and unpacks a toolchain for building on Windows. The contents are
6 matched by sha1 which will be updated when the toolchain is updated.
7
8 Having a toolchain script in depot_tools means that it's not versioned
9 directly with the source code. That is, if the toolchain is upgraded, but
10 you're trying to build an historical version of Chromium from before the
11 toolchain upgrade, this will cause you to build with a newer toolchain than
12 was available when that code was committed. This is done for a two main
13 reasons: 1) it would likely be annoying to have the up-to-date toolchain
14 removed and replaced by one without a service pack applied); 2) it would
15 require maintaining scripts that can build older not-up-to-date revisions of
16 the toolchain. This is likely to be a poorly tested code path that probably
17 won't be properly maintained. See http://crbug.com/323300.
18
19 This does not extend to major versions of the toolchain however, on the
20 assumption that there are more likely to be source incompatibilities between
21 major revisions. This script calls a subscript (currently, toolchain2013.py)
22 to do the main work. It is expected that toolchain2013.py will always be able
23 to acquire/build the most current revision of a VS2013-based toolchain. In the
24 future when a hypothetical VS2015 is released, the 2013 script will be
25 maintained, and a new 2015 script would be added.
26 """
27
28 import ctypes.wintypes
29 import hashlib
30 import json
31 import os
32 import subprocess
33 import sys
34
35
36 BASEDIR = os.path.dirname(os.path.abspath(__file__))
37
38
39 GetFileAttributes = ctypes.windll.kernel32.GetFileAttributesW
40 GetFileAttributes.argtypes = (ctypes.wintypes.LPWSTR,)
41 GetFileAttributes.restype = ctypes.wintypes.DWORD
42 FILE_ATTRIBUTE_HIDDEN = 0x2
43 FILE_ATTRIBUTE_SYSTEM = 0x4
44
45
46 def IsHidden(file_path):
47 """Returns whether the given |file_path| has the 'system' or 'hidden'
48 attribute set."""
49 p = GetFileAttributes(file_path)
50 assert p != 0xffffffff
51 return bool(p & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))
52
53
54 def GetFileList(root):
55 """Gets a normalized list of files under |root|."""
56 assert not os.path.isabs(root)
57 assert os.path.normpath(root) == root
58 file_list = []
59 for base, _, files in os.walk(root):
60 paths = [os.path.join(base, f) for f in files]
61 file_list.extend(x.lower() for x in paths if not IsHidden(x))
62 return sorted(file_list)
63
64
65 def MakeTimestampsFileName(root):
66 return os.path.join(root, '..', '.timestamps')
67
68
69 def CalculateHash(root):
70 """Calculates the sha1 of the paths to all files in the given |root| and the
71 contents of those files, and returns as a hex string."""
72 file_list = GetFileList(root)
73
74 # Check whether we previously saved timestamps in $root/../.timestamps. If
75 # we didn't, or they don't match, then do the full calculation, otherwise
76 # return the saved value.
77 timestamps_file = MakeTimestampsFileName(root)
78 timestamps_data = {'files': [], 'sha1': ''}
79 if os.path.exists(timestamps_file):
80 with open(timestamps_file, 'rb') as f:
81 try:
82 timestamps_data = json.load(f)
83 except ValueError:
84 # json couldn't be loaded, empty data will force a re-hash.
85 pass
86
87 matches = len(file_list) == len(timestamps_data['files'])
88 if matches:
89 for disk, cached in zip(file_list, timestamps_data['files']):
90 if disk != cached[0] or os.stat(disk).st_mtime != cached[1]:
91 matches = False
92 break
93 if matches:
94 return timestamps_data['sha1']
95
96 digest = hashlib.sha1()
97 for path in file_list:
98 digest.update(path)
99 with open(path, 'rb') as f:
100 digest.update(f.read())
101 return digest.hexdigest()
102
103
104 def SaveTimestampsAndHash(root, sha1):
105 """Save timestamps and the final hash to be able to early-out more quickly
106 next time."""
107 file_list = GetFileList(root)
108 timestamps_data = {
109 'files': [[f, os.stat(f).st_mtime] for f in file_list],
110 'sha1': sha1,
111 }
112 with open(MakeTimestampsFileName(root), 'wb') as f:
113 json.dump(timestamps_data, f)
114
115
116 def main():
117 if sys.platform not in ('win32', 'cygwin'):
M-A Ruel 2014/01/13 18:29:05 Sort values. This was tested in cygwin?
scottmg 2014/01/13 18:46:18 Done.
M-A Ruel 2014/01/13 18:50:32 Then it doesn't work. You'll have to wait for Pete
118 return 0
119
120 if len(sys.argv) != 1:
121 print >> sys.stderr, 'Unexpected arguments.'
122 return 1
123
124 # Move to depot_tools\win_toolchain where we'll store our files, and where
125 # the downloader script is.
126 os.chdir(os.path.normpath(os.path.join(BASEDIR)))
127 toolchain_dir = '.'
128 target_dir = os.path.normpath(os.path.join(toolchain_dir, 'vs2013_files'))
129
130 sha1path = os.path.join(toolchain_dir, 'toolchain.sha1')
131 desired_hash = ''
132 if os.path.isfile(sha1path):
133 with open(sha1path, 'rb') as f:
134 desired_hash = f.read().strip()
135
136 # If the current hash doesn't match what we want in the file, nuke and pave.
137 # Typically this script is only run when the .sha1 one file is updated, but
138 # directly calling "gclient runhooks" will also run it, so we cache
139 # based on timestamps to make that case fast.
140 current_hash = CalculateHash(target_dir)
141 if current_hash != desired_hash:
142 print 'Windows toolchain out of date or doesn\'t exist, updating...'
143 if os.path.isdir(target_dir):
144 subprocess.check_call('rmdir /s/q "%s"' % target_dir, shell=True)
145 subprocess.check_call([
146 sys.executable,
147 'toolchain2013.py',
148 '--targetdir', target_dir])
149 current_hash = CalculateHash(target_dir)
150 if current_hash != desired_hash:
151 print >> sys.stderr, (
152 'Got wrong hash after pulling a new toolchain. '
153 'Wanted \'%s\', got \'%s\'.' % (
154 desired_hash, current_hash))
155 return 1
156 SaveTimestampsAndHash(target_dir, current_hash)
157
158 return 0
159
160
161 if __name__ == '__main__':
162 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698