Index: win_toolchain/toolchain2013.py |
diff --git a/win_toolchain/toolchain2013.py b/win_toolchain/toolchain2013.py |
index cd91175086e81d54a9de4edad8c069432dc59fb1..147c9d3cf2a5af419f27076ca3912ab5679bba0f 100755 |
--- a/win_toolchain/toolchain2013.py |
+++ b/win_toolchain/toolchain2013.py |
@@ -40,6 +40,48 @@ def RunOrDie(command): |
subprocess.check_call(command, shell=True) |
+class ScopedSubstTempDir(object): |
+ """Creates a |TempDir()| and subst's a drive to the path. |
+ |
+ This is done to avoid exceedingly long names in some .msi packages which |
+ fail to extract because they exceed _MAX_PATH. Only the "subst" part of this |
+ is scoped, not the temp dir, which is left for use and cleanup by the |
+ caller. |
+ """ |
+ DefineDosDevice = ctypes.windll.kernel32.DefineDosDeviceW |
+ DefineDosDevice.argtypes = [ctypes.c_int, ctypes.c_wchar_p, ctypes.c_wchar_p] |
+ DDD_NO_BROADCAST_SYSTEM = 0x08 |
+ DDD_REMOVE_DEFINITION = 0x02 |
+ |
+ def __init__(self): |
+ self.real_path = TempDir() |
+ self.subst_drive = None |
+ |
+ def __enter__(self): |
+ """Tries to find a subst that we can use for the temporary directory, and |
+ aborts on failure.""" |
+ for drive in range(ord('Z'), ord('A') - 1, -1): |
+ candidate = '%c:' % drive |
+ if self.DefineDosDevice( |
+ self.DDD_NO_BROADCAST_SYSTEM, candidate, self.real_path) != 0: |
+ self.subst_drive = candidate |
+ return self |
+ raise RuntimeError('Unable to find a subst path') |
+ |
+ def __exit__(self, typ, value, traceback): |
+ if self.subst_drive: |
+ if self.DefineDosDevice(int(self.DDD_REMOVE_DEFINITION), |
+ self.subst_drive, |
+ self.real_path) == 0: |
+ raise RuntimeError('Unable to remove subst') |
+ |
+ def ShortenedPath(self): |
+ return self.subst_drive + '\\' |
+ |
+ def RealPath(self): |
+ return self.real_path |
+ |
+ |
def TempDir(): |
"""Generates a temporary directory (for downloading or extracting to) and keep |
track of the directory that's created for cleaning up later. |
@@ -116,9 +158,10 @@ def ExtractIso(iso_path): |
def ExtractMsi(msi_path): |
"""Uses msiexec to extract the contents of the given .msi file.""" |
sys.stdout.write('Extracting %s...\n' % msi_path) |
- target_path = TempDir() |
- RunOrDie('msiexec /a "%s" /qn TARGETDIR="%s"' % (msi_path, target_path)) |
- return target_path |
+ with ScopedSubstTempDir() as temp_dir: |
+ RunOrDie('msiexec /a "%s" /qn TARGETDIR="%s"' % ( |
+ msi_path, temp_dir.ShortenedPath())) |
+ return temp_dir.RealPath() |
def DownloadMainIso(url): |
@@ -262,6 +305,7 @@ def ExtractComponents(image): |
(r'vc_libraryDesktop\x64\vc_LibraryDesktopX64.msi', True), |
(r'vc_libraryDesktop\x86\vc_LibraryDesktopX86.msi', True), |
(r'vc_libraryextended\vc_libraryextended.msi', False), |
+ (r'professionalcore\Setup\vs_professionalcore.msi', False), |
] |
extracted_iso = ExtractIso(image.vs_path) |
result = ExtractMsiList(os.path.join(extracted_iso, 'packages'), vs_packages) |
@@ -295,7 +339,8 @@ def ExtractComponents(image): |
def CopyToFinalLocation(extracted_dirs, target_dir): |
sys.stdout.write('Copying to final location...\n') |
mappings = { |
- 'Program Files\\Microsoft Visual Studio 12.0\\': '.\\', |
+ 'Program Files\\Microsoft Visual Studio 12.0\\VC\\': 'VC\\', |
+ 'Program Files\\Microsoft Visual Studio 12.0\\DIA SDK\\': 'DIA SDK\\', |
'System64\\': 'sys64\\', |
'System\\': 'sys32\\', |
'Windows Kits\\8.0\\': 'win8sdk\\', |