OLD | NEW |
---|---|
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """ | 5 """ |
6 From a system-installed copy of the toolchain, packages all the required bits | 6 From a system-installed copy of the toolchain, packages all the required bits |
7 into a .zip file. | 7 into a .zip file. |
8 | 8 |
9 It assumes default install locations for tools, in particular: | 9 It assumes default install locations for tools, in particular: |
10 - C:\Program Files (x86)\Microsoft Visual Studio 12.0\... | 10 - C:\Program Files (x86)\Microsoft Visual Studio 12.0\... |
(...skipping 13 matching lines...) Expand all Loading... | |
24 import os | 24 import os |
25 import shutil | 25 import shutil |
26 import sys | 26 import sys |
27 import tempfile | 27 import tempfile |
28 import zipfile | 28 import zipfile |
29 | 29 |
30 import get_toolchain_if_necessary | 30 import get_toolchain_if_necessary |
31 | 31 |
32 | 32 |
33 VS_VERSION = None | 33 VS_VERSION = None |
34 WIN_VERSION = None | |
34 | 35 |
35 | 36 |
36 def BuildFileList(): | 37 def BuildFileList(): |
37 result = [] | 38 result = [] |
38 | 39 |
39 # Subset of VS corresponding roughly to VC. | 40 # Subset of VS corresponding roughly to VC. |
40 paths = [ | 41 paths = [ |
41 'DIA SDK/bin', | 42 'DIA SDK/bin', |
42 'DIA SDK/idl', | 43 'DIA SDK/idl', |
43 'DIA SDK/include', | 44 'DIA SDK/include', |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
105 else: | 106 else: |
106 result.append((final_from, dest)) | 107 result.append((final_from, dest)) |
107 | 108 |
108 # Just copy the whole SDK. | 109 # Just copy the whole SDK. |
109 sdk_path = r'C:\Program Files (x86)\Windows Kits\10' | 110 sdk_path = r'C:\Program Files (x86)\Windows Kits\10' |
110 for root, _, files in os.walk(sdk_path): | 111 for root, _, files in os.walk(sdk_path): |
111 for f in files: | 112 for f in files: |
112 combined = os.path.normpath(os.path.join(root, f)) | 113 combined = os.path.normpath(os.path.join(root, f)) |
113 # Some of the files in this directory are exceedingly long (and exceed | 114 # Some of the files in this directory are exceedingly long (and exceed |
114 #_MAX_PATH for any moderately long root), so exclude them. We don't need | 115 #_MAX_PATH for any moderately long root), so exclude them. We don't need |
115 # them anyway. | 116 # them anyway. Exclude the Windows Performance Toolkit just to save space. |
116 tail = combined[len(sdk_path) + 1:] | 117 tail = combined[len(sdk_path) + 1:] |
117 if tail.startswith('References\\'): | 118 if tail.startswith('References\\') or \ |
scottmg
2015/12/07 20:58:04
Put () around this if instead of using \.
brucedawson
2015/12/08 01:13:49
Done.
| |
119 tail.startswith('Windows Performance Toolkit\\'): | |
118 continue | 120 continue |
121 if VS_VERSION == '2015': | |
122 # There may be many Include\Lib\Source directories for many different | |
123 # versions of Windows and packaging them all wastes ~450 MB | |
124 # (uncompressed) per version and wastes time. Only copy the specified | |
125 # version. | |
126 if tail.startswith('Include\\') or tail.startswith('Lib\\') or \ | |
127 tail.startswith('Source\\'): | |
scottmg
2015/12/07 20:58:04
Same here.
brucedawson
2015/12/08 01:13:49
Done.
| |
128 if tail.count(WIN_VERSION) == 0: | |
129 continue | |
119 to = os.path.join('win_sdk', tail) | 130 to = os.path.join('win_sdk', tail) |
120 result.append((combined, to)) | 131 result.append((combined, to)) |
121 | 132 |
122 if VS_VERSION == '2015': | 133 if VS_VERSION == '2015': |
123 for ucrt_path in ( | |
124 (r'C:\Program Files (x86)\Windows Kits\10\Include', 'Include'), | |
125 (r'C:\Program Files (x86)\Windows Kits\10\Lib', 'Lib'), | |
126 (r'C:\Program Files (x86)\Windows Kits\10\Source', 'Source')): | |
127 src, target = ucrt_path | |
128 for root, _, files in os.walk(src): | |
129 for f in files: | |
130 combined = os.path.normpath(os.path.join(root, f)) | |
131 to = os.path.join('ucrt', target, combined[len(src) + 1:]) | |
132 result.append((combined, to)) | |
133 | 134 |
134 system_crt_files = [ | 135 system_crt_files = [ |
scottmg
2015/12/07 20:58:04
Have you tried the package on a non-redist install
brucedawson
2015/12/08 01:13:49
I have not yet tried using the package on a machin
| |
135 'api-ms-win-core-file-l1-2-0.dll', | 136 'api-ms-win-core-file-l1-2-0.dll', |
136 'api-ms-win-core-file-l2-1-0.dll', | 137 'api-ms-win-core-file-l2-1-0.dll', |
137 'api-ms-win-core-localization-l1-2-0.dll', | 138 'api-ms-win-core-localization-l1-2-0.dll', |
138 'api-ms-win-core-processthreads-l1-1-1.dll', | 139 'api-ms-win-core-processthreads-l1-1-1.dll', |
139 'api-ms-win-core-synch-l1-2-0.dll', | 140 'api-ms-win-core-synch-l1-2-0.dll', |
140 'api-ms-win-core-timezone-l1-1-0.dll', | 141 'api-ms-win-core-timezone-l1-1-0.dll', |
141 'api-ms-win-core-xstate-l2-1-0.dll', | 142 'api-ms-win-core-xstate-l2-1-0.dll', |
142 'api-ms-win-crt-conio-l1-1-0.dll', | 143 'api-ms-win-crt-conio-l1-1-0.dll', |
143 'api-ms-win-crt-convert-l1-1-0.dll', | 144 'api-ms-win-crt-convert-l1-1-0.dll', |
144 'api-ms-win-crt-environment-l1-1-0.dll', | 145 'api-ms-win-crt-environment-l1-1-0.dll', |
145 'api-ms-win-crt-filesystem-l1-1-0.dll', | 146 'api-ms-win-crt-filesystem-l1-1-0.dll', |
146 'api-ms-win-crt-heap-l1-1-0.dll', | 147 'api-ms-win-crt-heap-l1-1-0.dll', |
147 'api-ms-win-crt-locale-l1-1-0.dll', | 148 'api-ms-win-crt-locale-l1-1-0.dll', |
148 'api-ms-win-crt-math-l1-1-0.dll', | 149 'api-ms-win-crt-math-l1-1-0.dll', |
149 'api-ms-win-crt-multibyte-l1-1-0.dll', | 150 'api-ms-win-crt-multibyte-l1-1-0.dll', |
150 'api-ms-win-crt-private-l1-1-0.dll', | 151 'api-ms-win-crt-private-l1-1-0.dll', |
151 'api-ms-win-crt-process-l1-1-0.dll', | 152 'api-ms-win-crt-process-l1-1-0.dll', |
152 'api-ms-win-crt-runtime-l1-1-0.dll', | 153 'api-ms-win-crt-runtime-l1-1-0.dll', |
153 'api-ms-win-crt-stdio-l1-1-0.dll', | 154 'api-ms-win-crt-stdio-l1-1-0.dll', |
154 'api-ms-win-crt-string-l1-1-0.dll', | 155 'api-ms-win-crt-string-l1-1-0.dll', |
155 'api-ms-win-crt-time-l1-1-0.dll', | 156 'api-ms-win-crt-time-l1-1-0.dll', |
156 'api-ms-win-crt-utility-l1-1-0.dll', | 157 'api-ms-win-crt-utility-l1-1-0.dll', |
157 'api-ms-win-eventing-provider-l1-1-0.dll', | 158 'api-ms-win-eventing-provider-l1-1-0.dll', |
158 'ucrtbase.dll', | 159 'ucrtbase.dll', |
159 'ucrtbased.dll', | 160 'ucrtbased.dll', |
160 ] | 161 ] |
162 x64_path = r'C:\Windows\Sysnative' | |
scottmg
2015/12/07 20:58:04
Maybe rather that exists(), something like:
x64_p
| |
163 if not os.path.exists(x64_path): | |
164 # When running 64-bit python the x64 DLLs will be found here | |
165 x64_path = r'C:\Windows\System32' | |
161 for system_crt_file in system_crt_files: | 166 for system_crt_file in system_crt_files: |
162 result.append((os.path.join(r'C:\Windows\SysWOW64', system_crt_file), | 167 result.append((os.path.join(r'C:\Windows\SysWOW64', system_crt_file), |
163 os.path.join('sys32', system_crt_file))) | 168 os.path.join('sys32', system_crt_file))) |
164 result.append((os.path.join(r'C:\Windows\Sysnative', system_crt_file), | 169 result.append((os.path.join(x64_path, system_crt_file), |
165 os.path.join('sys64', system_crt_file))) | 170 os.path.join('sys64', system_crt_file))) |
166 | 171 |
167 # Generically drop all arm stuff that we don't need. | 172 # Generically drop all arm stuff that we don't need, and |
173 # drop .msi files because we don't need installers. | |
168 return [(f, t) for f, t in result if 'arm\\' not in f.lower() and | 174 return [(f, t) for f, t in result if 'arm\\' not in f.lower() and |
169 'arm64\\' not in f.lower()] | 175 'arm64\\' not in f.lower() and |
176 not f.lower().endswith('.msi')] | |
170 | 177 |
171 | 178 |
172 def GenerateSetEnvCmd(target_dir): | 179 def GenerateSetEnvCmd(target_dir): |
173 """Generate a batch file that gyp expects to exist to set up the compiler | 180 """Generate a batch file that gyp expects to exist to set up the compiler |
174 environment. | 181 environment. |
175 | 182 |
176 This is normally generated by a full install of the SDK, but we | 183 This is normally generated by a full install of the SDK, but we |
177 do it here manually since we do not do a full install.""" | 184 do it here manually since we do not do a full install.""" |
178 with open(os.path.join( | 185 with open(os.path.join( |
179 target_dir, r'win_sdk\bin\SetEnv.cmd'), 'w') as f: | 186 target_dir, r'win_sdk\bin\SetEnv.cmd'), 'w') as f: |
180 f.write('@echo off\n' | 187 f.write('@echo off\n' |
181 ':: Generated by win_toolchain\\package_from_installed.py.\n' | 188 ':: Generated by win_toolchain\\package_from_installed.py.\n' |
182 # Common to x86 and x64 | 189 # Common to x86 and x64 |
183 'set PATH=%~dp0..\\..\\Common7\\IDE;%PATH%\n' | 190 'set PATH=%~dp0..\\..\\Common7\\IDE;%PATH%\n' |
184 'set INCLUDE=%~dp0..\\..\\win_sdk\\Include\\10.0.10240.0\\um;' | 191 'set INCLUDE=%~dp0..\\..\\win_sdk\\Include\\WINVERSION\\um;' |
185 '%~dp0..\\..\\win_sdk\\Include\\10.0.10240.0\\shared;' | 192 '%~dp0..\\..\\win_sdk\\Include\\WINVERSION\\shared;' |
186 '%~dp0..\\..\\win_sdk\\Include\\10.0.10240.0\\winrt;' | 193 '%~dp0..\\..\\win_sdk\\Include\\WINVERSION\\winrt;' |
194 '%~dp0..\\..\\win_sdk\\Include\\WINVERSION\\ucrt;' # VS 2015 | |
scottmg
2015/12/07 20:58:04
I guess we're going to get a different package for
brucedawson
2015/12/08 01:13:49
It's true that the exact package we're using can't
| |
187 '%~dp0..\\..\\VC\\include;' | 195 '%~dp0..\\..\\VC\\include;' |
188 '%~dp0..\\..\\VC\\atlmfc\\include\n' | 196 '%~dp0..\\..\\VC\\atlmfc\\include\n' |
189 'if "%1"=="/x64" goto x64\n') | 197 'if "%1"=="/x64" goto x64\n'.replace("WINVERSION", WIN_VERSION)) |
190 | 198 |
191 # x86. Always use amd64_x86 cross, not x86 on x86. | 199 # x86. Always use amd64_x86 cross, not x86 on x86. |
192 f.write('set PATH=%~dp0..\\..\\win_sdk\\bin\\x86;' | 200 f.write('set PATH=%~dp0..\\..\\win_sdk\\bin\\x86;' |
193 '%~dp0..\\..\\VC\\bin\\amd64_x86;' | 201 '%~dp0..\\..\\VC\\bin\\amd64_x86;' |
194 '%~dp0..\\..\\VC\\bin\\amd64;' # Needed for mspdb1x0.dll. | 202 '%~dp0..\\..\\VC\\bin\\amd64;' # Needed for mspdb1x0.dll. |
195 '%PATH%\n') | 203 '%PATH%\n') |
196 f.write('set LIB=%~dp0..\\..\\VC\\lib;' | 204 f.write('set LIB=%~dp0..\\..\\VC\\lib;' |
197 '%~dp0..\\..\\win_sdk\\Lib\\10.0.10240.0\\um\\x86;' | 205 '%~dp0..\\..\\win_sdk\\Lib\\WINVERSION\\um\\x86;' |
206 '%~dp0..\\..\\win_sdk\\Lib\\WINVERSION\\ucrt\\x86;' # VS 2015 | |
198 '%~dp0..\\..\\VC\\atlmfc\\lib\n' | 207 '%~dp0..\\..\\VC\\atlmfc\\lib\n' |
199 'goto :EOF\n') | 208 'goto :EOF\n'.replace("WINVERSION", WIN_VERSION)) |
200 | 209 |
201 # x64. | 210 # x64. |
202 f.write(':x64\n' | 211 f.write(':x64\n' |
203 'set PATH=%~dp0..\\..\\win_sdk\\bin\\x64;' | 212 'set PATH=%~dp0..\\..\\win_sdk\\bin\\x64;' |
204 '%~dp0..\\..\\VC\\bin\\amd64;' | 213 '%~dp0..\\..\\VC\\bin\\amd64;' |
205 '%PATH%\n') | 214 '%PATH%\n') |
206 f.write('set LIB=%~dp0..\\..\\VC\\lib\\amd64;' | 215 f.write('set LIB=%~dp0..\\..\\VC\\lib\\amd64;' |
207 '%~dp0..\\..\\win_sdk\\Lib\\10.0.10240.0\\um\\x64;' | 216 '%~dp0..\\..\\win_sdk\\Lib\\WINVERSION\\um\\x64;' |
208 '%~dp0..\\..\\VC\\atlmfc\\lib\\amd64\n') | 217 '%~dp0..\\..\\win_sdk\\Lib\\WINVERSION\\ucrt\\x64;' # VS 2015 |
218 '%~dp0..\\..\\VC\\atlmfc\\lib\\amd64\n' | |
219 .replace("WINVERSION", WIN_VERSION)) | |
209 | 220 |
210 | 221 |
211 def AddEnvSetup(files): | 222 def AddEnvSetup(files): |
212 """We need to generate this file in the same way that the "from pieces" | 223 """We need to generate this file in the same way that the "from pieces" |
213 script does, so pull that in here.""" | 224 script does, so pull that in here.""" |
214 tempdir = tempfile.mkdtemp() | 225 tempdir = tempfile.mkdtemp() |
215 os.makedirs(os.path.join(tempdir, 'win_sdk', 'bin')) | 226 os.makedirs(os.path.join(tempdir, 'win_sdk', 'bin')) |
216 GenerateSetEnvCmd(tempdir) | 227 GenerateSetEnvCmd(tempdir) |
217 files.append((os.path.join(tempdir, 'win_sdk', 'bin', 'SetEnv.cmd'), | 228 files.append((os.path.join(tempdir, 'win_sdk', 'bin', 'SetEnv.cmd'), |
218 'win_sdk\\bin\\SetEnv.cmd')) | 229 'win_sdk\\bin\\SetEnv.cmd')) |
(...skipping 20 matching lines...) Expand all Loading... | |
239 print 'Hashing...' | 250 print 'Hashing...' |
240 sha1 = get_toolchain_if_necessary.CalculateHash(rel_dir) | 251 sha1 = get_toolchain_if_necessary.CalculateHash(rel_dir) |
241 os.chdir(old_dir) | 252 os.chdir(old_dir) |
242 shutil.rmtree(tempdir) | 253 shutil.rmtree(tempdir) |
243 final_name = sha1 + '.zip' | 254 final_name = sha1 + '.zip' |
244 os.rename(output, final_name) | 255 os.rename(output, final_name) |
245 print 'Renamed %s to %s.' % (output, final_name) | 256 print 'Renamed %s to %s.' % (output, final_name) |
246 | 257 |
247 | 258 |
248 def main(): | 259 def main(): |
249 if len(sys.argv) != 2 or sys.argv[1] not in ('2013', '2015'): | 260 if len(sys.argv) < 3 or sys.argv[1] not in ('2013', '2015'): |
scottmg
2015/12/07 20:58:04
This is a bit much once it's more than 1. Can you
| |
250 print 'Usage: package_from_installed.py 2013|2015' | 261 print 'Usage: package_from_installed.py 2013|2015 winversion dryrun' |
262 print 'winversion should be 10.0.10240.0 or similar' | |
scottmg
2015/12/07 20:58:04
Can we not default to 10586? (w/ optparse we can h
| |
263 print 'Specify dryrun to just scan for all files without packaging them.' | |
251 return 1 | 264 return 1 |
252 | 265 |
253 global VS_VERSION | 266 global VS_VERSION |
254 VS_VERSION = sys.argv[1] | 267 VS_VERSION = sys.argv[1] |
268 global WIN_VERSION | |
269 WIN_VERSION = sys.argv[2] | |
270 | |
271 dry_run = False | |
272 if len(sys.argv) > 3 and sys.argv[3].lower() == 'dryrun': | |
273 dry_run = True | |
255 | 274 |
256 print 'Building file list...' | 275 print 'Building file list...' |
257 files = BuildFileList() | 276 files = BuildFileList() |
258 | 277 |
259 AddEnvSetup(files) | 278 AddEnvSetup(files) |
260 | 279 |
261 if False: | 280 if False: |
262 for f in files: | 281 for f in files: |
263 print f[0], '->', f[1] | 282 print f[0], '->', f[1] |
264 return 0 | 283 return 0 |
265 | 284 |
266 output = 'out.zip' | 285 output = 'out.zip' |
267 if os.path.exists(output): | 286 if os.path.exists(output): |
268 os.unlink(output) | 287 os.unlink(output) |
269 count = 0 | 288 count = 0 |
289 version_match_count = 0 | |
290 total_size = 0 | |
291 missing_files = False | |
270 with zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED, True) as zf: | 292 with zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED, True) as zf: |
271 for disk_name, archive_name in files: | 293 for disk_name, archive_name in files: |
272 sys.stdout.write('\r%d/%d ...%s' % (count, len(files), disk_name[-40:])) | 294 sys.stdout.write('\r%d/%d ...%s' % (count, len(files), disk_name[-40:])) |
273 sys.stdout.flush() | 295 sys.stdout.flush() |
274 count += 1 | 296 count += 1 |
275 zf.write(disk_name, archive_name) | 297 if disk_name.count(WIN_VERSION) > 0: |
298 version_match_count += 1 | |
299 if os.path.exists(disk_name): | |
300 if dry_run: | |
301 total_size += os.path.getsize(disk_name) | |
302 else: | |
303 zf.write(disk_name, archive_name) | |
304 else: | |
305 missing_files = True | |
306 sys.stdout.write('\r%s does not exist.\n\n' % disk_name) | |
307 sys.stdout.flush() | |
308 if dry_run: | |
309 sys.stdout.write('\r%1.3f GB of data in %d files, %d files for %s.%s\n' % | |
310 (total_size / 1e9, count, version_match_count, WIN_VERSION, ' '*50)) | |
311 sys.stdout.flush() | |
scottmg
2015/12/07 20:58:04
No need to .flush() here, that's just because of t
brucedawson
2015/12/08 01:13:49
Done.
| |
312 return 0 | |
313 if missing_files: | |
314 raise "One or more files were missing - aborting" | |
315 if version_match_count == 0: | |
316 raise "No files found that match the specified winversion" | |
276 sys.stdout.write('\rWrote to %s.%s\n' % (output, ' '*50)) | 317 sys.stdout.write('\rWrote to %s.%s\n' % (output, ' '*50)) |
277 sys.stdout.flush() | 318 sys.stdout.flush() |
278 | 319 |
279 RenameToSha1(output) | 320 RenameToSha1(output) |
280 | 321 |
281 return 0 | 322 return 0 |
282 | 323 |
283 | 324 |
284 if __name__ == '__main__': | 325 if __name__ == '__main__': |
285 sys.exit(main()) | 326 sys.exit(main()) |
OLD | NEW |