| 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\\',
|
|
|