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