OLD | NEW |
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 """Extracts a Windows VS2013 toolchain from various downloadable pieces.""" | 6 """Extracts a Windows VS2013 toolchain from various downloadable pieces.""" |
7 | 7 |
8 | 8 |
9 import ctypes | 9 import ctypes |
10 import optparse | 10 import optparse |
(...skipping 22 matching lines...) Expand all Loading... |
33 size = ctypes.windll.kernel32.GetLongPathNameW(unicode(path), buf, 260) | 33 size = ctypes.windll.kernel32.GetLongPathNameW(unicode(path), buf, 260) |
34 if (size > 260): | 34 if (size > 260): |
35 sys.exit('Long form of path longer than 260 chars: %s' % path) | 35 sys.exit('Long form of path longer than 260 chars: %s' % path) |
36 return buf.value | 36 return buf.value |
37 | 37 |
38 | 38 |
39 def RunOrDie(command): | 39 def RunOrDie(command): |
40 subprocess.check_call(command, shell=True) | 40 subprocess.check_call(command, shell=True) |
41 | 41 |
42 | 42 |
| 43 class ScopedSubstTempDir(object): |
| 44 """Creates a |TempDir()| and subst's a drive to the path. |
| 45 |
| 46 This is done to avoid exceedingly long names in some .msi packages which |
| 47 fail to extract because they exceed _MAX_PATH. Only the "subst" part of this |
| 48 is scoped, not the temp dir, which is left for use and cleanup by the |
| 49 caller. |
| 50 """ |
| 51 DefineDosDevice = ctypes.windll.kernel32.DefineDosDeviceW |
| 52 DefineDosDevice.argtypes = [ctypes.c_int, ctypes.c_wchar_p, ctypes.c_wchar_p] |
| 53 DDD_NO_BROADCAST_SYSTEM = 0x08 |
| 54 DDD_REMOVE_DEFINITION = 0x02 |
| 55 |
| 56 def __init__(self): |
| 57 self.real_path = TempDir() |
| 58 self.subst_drive = None |
| 59 |
| 60 def __enter__(self): |
| 61 """Tries to find a subst that we can use for the temporary directory, and |
| 62 aborts on failure.""" |
| 63 for drive in range(ord('Z'), ord('A') - 1, -1): |
| 64 candidate = '%c:' % drive |
| 65 if self.DefineDosDevice( |
| 66 self.DDD_NO_BROADCAST_SYSTEM, candidate, self.real_path) != 0: |
| 67 self.subst_drive = candidate |
| 68 return self |
| 69 raise RuntimeError('Unable to find a subst path') |
| 70 |
| 71 def __exit__(self, typ, value, traceback): |
| 72 if self.subst_drive: |
| 73 if self.DefineDosDevice(int(self.DDD_REMOVE_DEFINITION), |
| 74 self.subst_drive, |
| 75 self.real_path) == 0: |
| 76 raise RuntimeError('Unable to remove subst') |
| 77 |
| 78 def ShortenedPath(self): |
| 79 return self.subst_drive + '\\' |
| 80 |
| 81 def RealPath(self): |
| 82 return self.real_path |
| 83 |
| 84 |
43 def TempDir(): | 85 def TempDir(): |
44 """Generates a temporary directory (for downloading or extracting to) and keep | 86 """Generates a temporary directory (for downloading or extracting to) and keep |
45 track of the directory that's created for cleaning up later. | 87 track of the directory that's created for cleaning up later. |
46 """ | 88 """ |
47 temp = tempfile.mkdtemp() | 89 temp = tempfile.mkdtemp() |
48 g_temp_dirs.append(temp) | 90 g_temp_dirs.append(temp) |
49 return temp | 91 return temp |
50 | 92 |
51 | 93 |
52 def DeleteAllTempDirs(): | 94 def DeleteAllTempDirs(): |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 # TODO(scottmg): Do this (and exe) manually with python code. | 151 # TODO(scottmg): Do this (and exe) manually with python code. |
110 # Note that at the beginning of main() we set the working directory to 7z's | 152 # Note that at the beginning of main() we set the working directory to 7z's |
111 # location so that 7z can find its codec dll. | 153 # location so that 7z can find its codec dll. |
112 RunOrDie('7z x "%s" -y "-o%s" >nul' % (iso_path, target_path)) | 154 RunOrDie('7z x "%s" -y "-o%s" >nul' % (iso_path, target_path)) |
113 return target_path | 155 return target_path |
114 | 156 |
115 | 157 |
116 def ExtractMsi(msi_path): | 158 def ExtractMsi(msi_path): |
117 """Uses msiexec to extract the contents of the given .msi file.""" | 159 """Uses msiexec to extract the contents of the given .msi file.""" |
118 sys.stdout.write('Extracting %s...\n' % msi_path) | 160 sys.stdout.write('Extracting %s...\n' % msi_path) |
119 target_path = TempDir() | 161 with ScopedSubstTempDir() as temp_dir: |
120 RunOrDie('msiexec /a "%s" /qn TARGETDIR="%s"' % (msi_path, target_path)) | 162 RunOrDie('msiexec /a "%s" /qn TARGETDIR="%s"' % ( |
121 return target_path | 163 msi_path, temp_dir.ShortenedPath())) |
| 164 return temp_dir.RealPath() |
122 | 165 |
123 | 166 |
124 def DownloadMainIso(url): | 167 def DownloadMainIso(url): |
125 temp_dir = TempDir() | 168 temp_dir = TempDir() |
126 target_path = os.path.join(temp_dir, os.path.basename(url)) | 169 target_path = os.path.join(temp_dir, os.path.basename(url)) |
127 Download(url, target_path) | 170 Download(url, target_path) |
128 return target_path | 171 return target_path |
129 | 172 |
130 | 173 |
131 def DownloadSDK8(): | 174 def DownloadSDK8(): |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 (r'vc_compilerCore86\vc_compilerCore86.msi', True), | 298 (r'vc_compilerCore86\vc_compilerCore86.msi', True), |
256 (r'vc_compilerCore86res\vc_compilerCore86res.msi', True), | 299 (r'vc_compilerCore86res\vc_compilerCore86res.msi', True), |
257 (r'vc_compilerx64nat\vc_compilerx64nat.msi', False), | 300 (r'vc_compilerx64nat\vc_compilerx64nat.msi', False), |
258 (r'vc_compilerx64natres\vc_compilerx64natres.msi', False), | 301 (r'vc_compilerx64natres\vc_compilerx64natres.msi', False), |
259 (r'vc_compilerx64x86\vc_compilerx64x86.msi', False), | 302 (r'vc_compilerx64x86\vc_compilerx64x86.msi', False), |
260 (r'vc_compilerx64x86res\vc_compilerx64x86res.msi', False), | 303 (r'vc_compilerx64x86res\vc_compilerx64x86res.msi', False), |
261 (r'vc_librarycore86\vc_librarycore86.msi', True), | 304 (r'vc_librarycore86\vc_librarycore86.msi', True), |
262 (r'vc_libraryDesktop\x64\vc_LibraryDesktopX64.msi', True), | 305 (r'vc_libraryDesktop\x64\vc_LibraryDesktopX64.msi', True), |
263 (r'vc_libraryDesktop\x86\vc_LibraryDesktopX86.msi', True), | 306 (r'vc_libraryDesktop\x86\vc_LibraryDesktopX86.msi', True), |
264 (r'vc_libraryextended\vc_libraryextended.msi', False), | 307 (r'vc_libraryextended\vc_libraryextended.msi', False), |
| 308 (r'professionalcore\Setup\vs_professionalcore.msi', False), |
265 ] | 309 ] |
266 extracted_iso = ExtractIso(image.vs_path) | 310 extracted_iso = ExtractIso(image.vs_path) |
267 result = ExtractMsiList(os.path.join(extracted_iso, 'packages'), vs_packages) | 311 result = ExtractMsiList(os.path.join(extracted_iso, 'packages'), vs_packages) |
268 | 312 |
269 sdk_packages = [ | 313 sdk_packages = [ |
270 (r'X86 Debuggers And Tools-x86_en-us.msi', True), | 314 (r'X86 Debuggers And Tools-x86_en-us.msi', True), |
271 (r'X64 Debuggers And Tools-x64_en-us.msi', True), | 315 (r'X64 Debuggers And Tools-x64_en-us.msi', True), |
272 (r'SDK Debuggers-x86_en-us.msi', True), | 316 (r'SDK Debuggers-x86_en-us.msi', True), |
273 (r'Windows Software Development Kit-x86_en-us.msi', True), | 317 (r'Windows Software Development Kit-x86_en-us.msi', True), |
274 (r'Windows Software Development Kit for Metro style Apps-x86_en-us.msi', | 318 (r'Windows Software Development Kit for Metro style Apps-x86_en-us.msi', |
(...skipping 13 matching lines...) Expand all Loading... |
288 extracted_iso = ExtractIso(image.wdk_path) | 332 extracted_iso = ExtractIso(image.wdk_path) |
289 result.extend(ExtractMsiList(os.path.join(extracted_iso, 'WDK'), | 333 result.extend(ExtractMsiList(os.path.join(extracted_iso, 'WDK'), |
290 wdk_packages)) | 334 wdk_packages)) |
291 | 335 |
292 return result | 336 return result |
293 | 337 |
294 | 338 |
295 def CopyToFinalLocation(extracted_dirs, target_dir): | 339 def CopyToFinalLocation(extracted_dirs, target_dir): |
296 sys.stdout.write('Copying to final location...\n') | 340 sys.stdout.write('Copying to final location...\n') |
297 mappings = { | 341 mappings = { |
298 'Program Files\\Microsoft Visual Studio 12.0\\': '.\\', | 342 'Program Files\\Microsoft Visual Studio 12.0\\VC\\': 'VC\\', |
| 343 'Program Files\\Microsoft Visual Studio 12.0\\DIA SDK\\': 'DIA SDK\\', |
299 'System64\\': 'sys64\\', | 344 'System64\\': 'sys64\\', |
300 'System\\': 'sys32\\', | 345 'System\\': 'sys32\\', |
301 'Windows Kits\\8.0\\': 'win8sdk\\', | 346 'Windows Kits\\8.0\\': 'win8sdk\\', |
302 'WinDDK\\7600.16385.win7_wdk.100208-1538\\': 'wdk\\', | 347 'WinDDK\\7600.16385.win7_wdk.100208-1538\\': 'wdk\\', |
303 } | 348 } |
304 matches = [] | 349 matches = [] |
305 for extracted_dir in extracted_dirs: | 350 for extracted_dir in extracted_dirs: |
306 for root, _, filenames in os.walk(extracted_dir): | 351 for root, _, filenames in os.walk(extracted_dir): |
307 for filename in filenames: | 352 for filename in filenames: |
308 matches.append((extracted_dir, os.path.join(root, filename))) | 353 matches.append((extracted_dir, os.path.join(root, filename))) |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 GenerateSetEnvCmd(target_dir, not options.express) | 458 GenerateSetEnvCmd(target_dir, not options.express) |
414 with open(os.path.join(target_dir, '.version'), 'w') as f: | 459 with open(os.path.join(target_dir, '.version'), 'w') as f: |
415 f.write('express' if options.express else 'pro') | 460 f.write('express' if options.express else 'pro') |
416 finally: | 461 finally: |
417 if options.clean: | 462 if options.clean: |
418 DeleteAllTempDirs() | 463 DeleteAllTempDirs() |
419 | 464 |
420 | 465 |
421 if __name__ == '__main__': | 466 if __name__ == '__main__': |
422 sys.exit(main()) | 467 sys.exit(main()) |
OLD | NEW |