blob: 3ca83b4a924029ecc11363f084c31fcf1e70f07d [file] [log] [blame]
[email protected]7cc7a1c2014-01-15 22:05:051#!/usr/bin/env python
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
4# found in the LICENSE file.
5
6"""Extracts a Windows VS2013 toolchain from various downloadable pieces."""
7
8
9import ctypes
[email protected]5d17b922014-02-22 01:47:5310import json
[email protected]7cc7a1c2014-01-15 22:05:0511import optparse
12import os
13import shutil
14import subprocess
15import sys
16import tempfile
17import urllib2
18
19
20BASEDIR = os.path.dirname(os.path.abspath(__file__))
[email protected]26cb8362014-02-04 00:07:0221WDK_ISO_URL = (
22 'http://download.microsoft.com/download/'
23 '4/A/2/4A25C7D5-EFBE-4182-B6A9-AE6850409A78/GRMWDK_EN_7600_1.ISO')
[email protected]7cc7a1c2014-01-15 22:05:0524g_temp_dirs = []
25
26
[email protected]79231292014-01-28 03:17:5427sys.path.append(os.path.join(BASEDIR, '..'))
28import download_from_google_storage
29
30
[email protected]7cc7a1c2014-01-15 22:05:0531def GetLongPathName(path):
32 """Converts any 8dot3 names in the path to the full name."""
33 buf = ctypes.create_unicode_buffer(260)
34 size = ctypes.windll.kernel32.GetLongPathNameW(unicode(path), buf, 260)
35 if (size > 260):
36 sys.exit('Long form of path longer than 260 chars: %s' % path)
37 return buf.value
38
39
40def RunOrDie(command):
41 subprocess.check_call(command, shell=True)
42
43
[email protected]40167ed2014-02-13 18:24:5244class ScopedSubstTempDir(object):
45 """Creates a |TempDir()| and subst's a drive to the path.
46
47 This is done to avoid exceedingly long names in some .msi packages which
48 fail to extract because they exceed _MAX_PATH. Only the "subst" part of this
49 is scoped, not the temp dir, which is left for use and cleanup by the
50 caller.
51 """
52 DefineDosDevice = ctypes.windll.kernel32.DefineDosDeviceW
53 DefineDosDevice.argtypes = [ctypes.c_int, ctypes.c_wchar_p, ctypes.c_wchar_p]
54 DDD_NO_BROADCAST_SYSTEM = 0x08
55 DDD_REMOVE_DEFINITION = 0x02
56
57 def __init__(self):
58 self.real_path = TempDir()
59 self.subst_drive = None
60
61 def __enter__(self):
62 """Tries to find a subst that we can use for the temporary directory, and
63 aborts on failure."""
64 for drive in range(ord('Z'), ord('A') - 1, -1):
65 candidate = '%c:' % drive
66 if self.DefineDosDevice(
67 self.DDD_NO_BROADCAST_SYSTEM, candidate, self.real_path) != 0:
68 self.subst_drive = candidate
69 return self
70 raise RuntimeError('Unable to find a subst path')
71
72 def __exit__(self, typ, value, traceback):
73 if self.subst_drive:
74 if self.DefineDosDevice(int(self.DDD_REMOVE_DEFINITION),
75 self.subst_drive,
76 self.real_path) == 0:
77 raise RuntimeError('Unable to remove subst')
78
79 def ShortenedPath(self):
80 return self.subst_drive + '\\'
81
82 def RealPath(self):
83 return self.real_path
84
85
[email protected]7cc7a1c2014-01-15 22:05:0586def TempDir():
87 """Generates a temporary directory (for downloading or extracting to) and keep
88 track of the directory that's created for cleaning up later.
89 """
[email protected]7cc7a1c2014-01-15 22:05:0590 temp = tempfile.mkdtemp()
91 g_temp_dirs.append(temp)
92 return temp
93
94
95def DeleteAllTempDirs():
96 """Removes all temporary directories created by |TempDir()|."""
97 global g_temp_dirs
98 if g_temp_dirs:
99 sys.stdout.write('Cleaning up temporaries...\n')
100 for temp in g_temp_dirs:
101 # shutil.rmtree errors out on read only attributes.
102 RunOrDie('rmdir /s/q "%s"' % temp)
103 g_temp_dirs = []
104
105
[email protected]26cb8362014-02-04 00:07:02106def GetMainIsoUrl(pro):
107 """Gets the main .iso URL.
[email protected]7cc7a1c2014-01-15 22:05:05108
[email protected]0d23d772014-03-07 20:17:49109 If |pro| is False, downloads the Express edition.
[email protected]7cc7a1c2014-01-15 22:05:05110 """
111 prefix = 'http://download.microsoft.com/download/'
112 if pro:
113 return (prefix +
114 'A/F/1/AF128362-A6A8-4DB3-A39A-C348086472CC/VS2013_RTM_PRO_ENU.iso')
115 else:
116 return (prefix +
117 '7/2/E/72E0F986-D247-4289-B9DC-C4FB07374894/VS2013_RTM_DskExp_ENU.iso')
118
119
120def Download(url, local_path):
121 """Downloads a large-ish binary file and print some status information while
122 doing so.
123 """
124 sys.stdout.write('Downloading %s...\n' % url)
125 req = urllib2.urlopen(url)
126 content_length = int(req.headers.get('Content-Length', 0))
127 bytes_read = 0L
128 terminator = '\r' if sys.stdout.isatty() else '\n'
[email protected]9eabb222014-01-16 02:42:43129 with open(local_path, 'wb') as file_handle:
[email protected]7cc7a1c2014-01-15 22:05:05130 while True:
131 chunk = req.read(1024 * 1024)
132 if not chunk:
133 break
134 bytes_read += len(chunk)
[email protected]9eabb222014-01-16 02:42:43135 file_handle.write(chunk)
[email protected]7cc7a1c2014-01-15 22:05:05136 sys.stdout.write('... %d/%d%s' % (bytes_read, content_length, terminator))
137 sys.stdout.flush()
138 sys.stdout.write('\n')
139 if content_length and content_length != bytes_read:
[email protected]22b2ec72014-01-28 18:10:06140 sys.exit('Got incorrect number of bytes downloading %s' % url)
[email protected]7cc7a1c2014-01-15 22:05:05141
142
143def ExtractIso(iso_path):
144 """Uses 7zip to extract the contents of the given .iso (or self-extracting
145 .exe).
146 """
147 target_path = TempDir()
148 sys.stdout.write('Extracting %s...\n' % iso_path)
149 sys.stdout.flush()
150 # TODO(scottmg): Do this (and exe) manually with python code.
151 # Note that at the beginning of main() we set the working directory to 7z's
152 # location so that 7z can find its codec dll.
153 RunOrDie('7z x "%s" -y "-o%s" >nul' % (iso_path, target_path))
154 return target_path
155
156
157def ExtractMsi(msi_path):
158 """Uses msiexec to extract the contents of the given .msi file."""
159 sys.stdout.write('Extracting %s...\n' % msi_path)
[email protected]40167ed2014-02-13 18:24:52160 with ScopedSubstTempDir() as temp_dir:
161 RunOrDie('msiexec /a "%s" /qn TARGETDIR="%s"' % (
162 msi_path, temp_dir.ShortenedPath()))
163 return temp_dir.RealPath()
[email protected]7cc7a1c2014-01-15 22:05:05164
165
166def DownloadMainIso(url):
167 temp_dir = TempDir()
168 target_path = os.path.join(temp_dir, os.path.basename(url))
169 Download(url, target_path)
170 return target_path
171
172
[email protected]dfaf79d2014-01-16 20:50:19173def DownloadSDK8():
174 """Downloads the Win8 SDK.
175
176 This one is slightly different than the simpler direct downloads. There is
177 no .ISO distribution for the Windows 8 SDK. Rather, a tool is provided that
178 is a download manager. This is used to download the various .msi files to a
179 target location. Unfortunately, this tool requires elevation for no obvious
180 reason even when only downloading, so this function will trigger a UAC
181 elevation if the script is not run from an elevated prompt. This is mostly
182 grabbed for windbg and cdb (See http://crbug.com/321187) as most of the SDK
183 is in VS2013, however we need a couple D3D related things from the SDK.
184 """
185 # Use the long path name here because because 8dot3 names don't seem to work.
186 sdk_temp_dir = GetLongPathName(TempDir())
187 target_path = os.path.join(sdk_temp_dir, 'sdksetup.exe')
188 standalone_path = os.path.join(sdk_temp_dir, 'Standalone')
189 Download(
190 ('http://download.microsoft.com/download/'
191 'F/1/3/F1300C9C-A120-4341-90DF-8A52509B23AC/standalonesdk/sdksetup.exe'),
192 target_path)
193 sys.stdout.write(
194 'Running sdksetup.exe to download Win8 SDK (may request elevation)...\n')
195 count = 0
196 while count < 5:
[email protected]5b9f90e2014-03-05 03:28:24197 rc = subprocess.call([target_path,
198 '/quiet',
199 '/features', 'OptionId.WindowsDesktopDebuggers',
200 'OptionId.WindowsDesktopSoftwareDevelopmentKit',
201 '/layout', standalone_path])
[email protected]dfaf79d2014-01-16 20:50:19202 if rc == 0:
203 return standalone_path
204 count += 1
205 sys.stdout.write('Windows 8 SDK failed to download, retrying.\n')
[email protected]22b2ec72014-01-28 18:10:06206 sys.exit('After multiple retries, couldn\'t download Win8 SDK')
[email protected]dfaf79d2014-01-16 20:50:19207
208
[email protected]26cb8362014-02-04 00:07:02209def DownloadWDKIso():
210 wdk_temp_dir = TempDir()
211 target_path = os.path.join(wdk_temp_dir, 'GRMWDK_EN_7600_1.ISO')
212 Download(WDK_ISO_URL, target_path)
213 return target_path
214
215
[email protected]79231292014-01-28 03:17:54216def DownloadUsingGsutil(filename):
217 """Downloads the given file from Google Storage chrome-wintoolchain bucket."""
218 temp_dir = TempDir()
219 assert os.path.basename(filename) == filename
220 target_path = os.path.join(temp_dir, filename)
221 gsutil = download_from_google_storage.Gsutil(
222 download_from_google_storage.GSUTIL_DEFAULT_PATH, boto_path=None)
223 code = gsutil.call('cp', 'gs://chrome-wintoolchain/' + filename, target_path)
224 if code != 0:
[email protected]22b2ec72014-01-28 18:10:06225 sys.exit('gsutil failed')
[email protected]79231292014-01-28 03:17:54226 return target_path
227
228
229def GetVSInternal():
230 """Uses gsutil to pull the toolchain from internal Google Storage bucket."""
231 return DownloadUsingGsutil('VS2013_RTM_PRO_ENU.iso')
232
233
234def GetSDKInternal():
235 """Downloads a zipped copy of the SDK from internal Google Storage bucket,
236 and extracts it."""
237 zip_file = DownloadUsingGsutil('Standalone.zip')
238 return ExtractIso(zip_file)
239
240
[email protected]dfaf79d2014-01-16 20:50:19241class SourceImages(object):
[email protected]26cb8362014-02-04 00:07:02242 """Local paths for components. |wdk_path| may be None if it's unnecessary for
243 the given configuration."""
244 def __init__(self, vs_path, sdk8_path, wdk_path):
[email protected]dfaf79d2014-01-16 20:50:19245 self.vs_path = vs_path
246 self.sdk8_path = sdk8_path
[email protected]26cb8362014-02-04 00:07:02247 self.wdk_path = wdk_path
[email protected]dfaf79d2014-01-16 20:50:19248
249
[email protected]71756322014-03-02 22:59:57250def GetSourceImages(local_dir, pro):
[email protected]26cb8362014-02-04 00:07:02251 """Downloads the various sources that we need.
252
253 Of note: Because Express does not include ATL, there's an additional download
254 of the 7.1 WDK which is the latest publically accessible source for ATL. When
255 |pro| this is not necessary (and CHROME_HEADLESS always implies Pro).
256 """
[email protected]0d23d772014-03-07 20:17:49257 if pro and not local_dir:
258 sys.exit('Non-Express must be used with --local')
[email protected]26cb8362014-02-04 00:07:02259 url = GetMainIsoUrl(pro)
[email protected]71756322014-03-02 22:59:57260 if local_dir:
[email protected]26cb8362014-02-04 00:07:02261 wdk_path = (os.path.join(local_dir, os.path.basename(WDK_ISO_URL))
262 if not pro else None)
[email protected]dfaf79d2014-01-16 20:50:19263 return SourceImages(os.path.join(local_dir, os.path.basename(url)),
[email protected]26cb8362014-02-04 00:07:02264 os.path.join(local_dir, 'Standalone'),
265 wdk_path=wdk_path)
[email protected]7cc7a1c2014-01-15 22:05:05266 else:
[email protected]dfaf79d2014-01-16 20:50:19267 # Note that we do the SDK first, as it might cause an elevation prompt.
268 sdk8_path = DownloadSDK8()
269 vs_path = DownloadMainIso(url)
[email protected]26cb8362014-02-04 00:07:02270 wdk_path = DownloadWDKIso() if not pro else None
271 return SourceImages(vs_path, sdk8_path, wdk_path=wdk_path)
[email protected]7cc7a1c2014-01-15 22:05:05272
273
[email protected]dfaf79d2014-01-16 20:50:19274def ExtractMsiList(root_dir, packages):
[email protected]7cc7a1c2014-01-15 22:05:05275 """Extracts the contents of a list of .msi files from an already extracted
276 .iso file.
277
278 |packages| is a list of pairs (msi, required). If required is not True, the
279 msi is optional (this is set for packages that are in Pro but not Express).
280 """
281 results = []
282 for (package, required) in packages:
[email protected]dfaf79d2014-01-16 20:50:19283 path_to_package = os.path.join(root_dir, package)
[email protected]7cc7a1c2014-01-15 22:05:05284 if not os.path.exists(path_to_package) and not required:
285 continue
286 results.append(ExtractMsi(path_to_package))
287 return results
288
289
290def ExtractComponents(image):
[email protected]dfaf79d2014-01-16 20:50:19291 vs_packages = [
[email protected]7cc7a1c2014-01-15 22:05:05292 (r'vcRuntimeAdditional_amd64\vc_runtimeAdditional_x64.msi', True),
293 (r'vcRuntimeAdditional_x86\vc_runtimeAdditional_x86.msi', True),
294 (r'vcRuntimeDebug_amd64\vc_runtimeDebug_x64.msi', True),
295 (r'vcRuntimeDebug_x86\vc_runtimeDebug_x86.msi', True),
296 (r'vcRuntimeMinimum_amd64\vc_runtimeMinimum_x64.msi', True),
297 (r'vcRuntimeMinimum_x86\vc_runtimeMinimum_x86.msi', True),
298 (r'vc_compilerCore86\vc_compilerCore86.msi', True),
299 (r'vc_compilerCore86res\vc_compilerCore86res.msi', True),
300 (r'vc_compilerx64nat\vc_compilerx64nat.msi', False),
301 (r'vc_compilerx64natres\vc_compilerx64natres.msi', False),
302 (r'vc_compilerx64x86\vc_compilerx64x86.msi', False),
303 (r'vc_compilerx64x86res\vc_compilerx64x86res.msi', False),
304 (r'vc_librarycore86\vc_librarycore86.msi', True),
305 (r'vc_libraryDesktop\x64\vc_LibraryDesktopX64.msi', True),
306 (r'vc_libraryDesktop\x86\vc_LibraryDesktopX86.msi', True),
307 (r'vc_libraryextended\vc_libraryextended.msi', False),
[email protected]40167ed2014-02-13 18:24:52308 (r'professionalcore\Setup\vs_professionalcore.msi', False),
[email protected]4a56efe2014-02-22 07:45:07309 (r'vc_libraryselectablemfc\vc_libraryselectablemfc.msi', False),
[email protected]7cc7a1c2014-01-15 22:05:05310 ]
[email protected]dfaf79d2014-01-16 20:50:19311 extracted_iso = ExtractIso(image.vs_path)
312 result = ExtractMsiList(os.path.join(extracted_iso, 'packages'), vs_packages)
313
314 sdk_packages = [
315 (r'X86 Debuggers And Tools-x86_en-us.msi', True),
316 (r'X64 Debuggers And Tools-x64_en-us.msi', True),
317 (r'SDK Debuggers-x86_en-us.msi', True),
[email protected]26cb8362014-02-04 00:07:02318 (r'Windows Software Development Kit-x86_en-us.msi', True),
319 (r'Windows Software Development Kit for Metro style Apps-x86_en-us.msi',
320 True),
[email protected]dfaf79d2014-01-16 20:50:19321 ]
322 result.extend(ExtractMsiList(os.path.join(image.sdk8_path, 'Installers'),
323 sdk_packages))
324
[email protected]26cb8362014-02-04 00:07:02325 if image.wdk_path:
326 # This image will only be set when using Express, when we need the WDK
327 # headers and libs to supplement Express with ATL.
328 wdk_packages = [
329 (r'headers.msi', True),
330 (r'libs_x86fre.msi', True),
331 (r'libs_x64fre.msi', True),
332 ]
333 extracted_iso = ExtractIso(image.wdk_path)
334 result.extend(ExtractMsiList(os.path.join(extracted_iso, 'WDK'),
335 wdk_packages))
336
[email protected]dfaf79d2014-01-16 20:50:19337 return result
[email protected]7cc7a1c2014-01-15 22:05:05338
339
340def CopyToFinalLocation(extracted_dirs, target_dir):
341 sys.stdout.write('Copying to final location...\n')
342 mappings = {
[email protected]40167ed2014-02-13 18:24:52343 'Program Files\\Microsoft Visual Studio 12.0\\VC\\': 'VC\\',
344 'Program Files\\Microsoft Visual Studio 12.0\\DIA SDK\\': 'DIA SDK\\',
[email protected]7cc7a1c2014-01-15 22:05:05345 'System64\\': 'sys64\\',
346 'System\\': 'sys32\\',
[email protected]c60ecf92014-11-14 22:51:23347 'Windows Kits\\8.1\\': 'win8sdk\\',
[email protected]26cb8362014-02-04 00:07:02348 'WinDDK\\7600.16385.win7_wdk.100208-1538\\': 'wdk\\',
[email protected]7cc7a1c2014-01-15 22:05:05349 }
350 matches = []
351 for extracted_dir in extracted_dirs:
[email protected]9eabb222014-01-16 02:42:43352 for root, _, filenames in os.walk(extracted_dir):
[email protected]7cc7a1c2014-01-15 22:05:05353 for filename in filenames:
354 matches.append((extracted_dir, os.path.join(root, filename)))
355
356 copies = []
357 for prefix, full_path in matches:
358 # +1 for trailing \.
359 partial_path = full_path[len(prefix) + 1:]
360 for map_from, map_to in mappings.iteritems():
361 if partial_path.startswith(map_from):
362 target_path = os.path.join(map_to, partial_path[len(map_from):])
363 copies.append((full_path, os.path.join(target_dir, target_path)))
364
365 for full_source, full_target in copies:
366 target_dir = os.path.dirname(full_target)
367 if not os.path.isdir(target_dir):
368 os.makedirs(target_dir)
369 shutil.copy2(full_source, full_target)
370
371
372def GenerateSetEnvCmd(target_dir, pro):
373 """Generate a batch file that gyp expects to exist to set up the compiler
374 environment.
375
376 This is normally generated by a full install of the SDK, but we
377 do it here manually since we do not do a full install."""
378 with open(os.path.join(
379 target_dir, r'win8sdk\bin\SetEnv.cmd'), 'w') as f:
380 f.write('@echo off\n'
381 ':: Generated by win_toolchain\\toolchain2013.py.\n'
382 # Common to x86 and x64
383 'set PATH=%~dp0..\\..\\Common7\\IDE;%PATH%\n'
384 'set INCLUDE=%~dp0..\\..\\win8sdk\\Include\\um;'
385 '%~dp0..\\..\\win8sdk\\Include\\shared;'
[email protected]7cc7a1c2014-01-15 22:05:05386 '%~dp0..\\..\\VC\\include;'
387 '%~dp0..\\..\\VC\\atlmfc\\include\n'
388 'if "%1"=="/x64" goto x64\n')
389
390 # x86. If we're Pro, then use the amd64_x86 cross (we don't support x86
391 # host at all).
392 if pro:
393 f.write('set PATH=%~dp0..\\..\\win8sdk\\bin\\x86;'
394 '%~dp0..\\..\\VC\\bin\\amd64_x86;'
395 '%~dp0..\\..\\VC\\bin\\amd64;' # Needed for mspdb120.dll.
396 '%PATH%\n')
397 else:
398 f.write('set PATH=%~dp0..\\..\\win8sdk\\bin\\x86;'
399 '%~dp0..\\..\\VC\\bin;%PATH%\n')
400 f.write('set LIB=%~dp0..\\..\\VC\\lib;'
[email protected]c60ecf92014-11-14 22:51:23401 '%~dp0..\\..\\win8sdk\\Lib\\winv6.3\\um\\x86;'
[email protected]7cc7a1c2014-01-15 22:05:05402 '%~dp0..\\..\\VC\\atlmfc\\lib\n'
403 'goto :EOF\n')
404
405 # Express does not include a native 64 bit compiler, so we have to use
406 # the x86->x64 cross.
407 if not pro:
408 # x86->x64 cross.
409 f.write(':x64\n'
410 'set PATH=%~dp0..\\..\\win8sdk\\bin\\x64;'
411 '%~dp0..\\..\\VC\\bin\\x86_amd64;'
[email protected]26cb8362014-02-04 00:07:02412 # Needed for mspdb120.dll. Must be after above though, so
413 # that cl.exe is the x86_amd64 one.
414 '%~dp0..\\..\\VC\\bin;'
[email protected]7cc7a1c2014-01-15 22:05:05415 '%PATH%\n')
416 else:
417 # x64 native.
418 f.write(':x64\n'
419 'set PATH=%~dp0..\\..\\win8sdk\\bin\\x64;'
420 '%~dp0..\\..\\VC\\bin\\amd64;'
421 '%PATH%\n')
422 f.write('set LIB=%~dp0..\\..\\VC\\lib\\amd64;'
[email protected]c60ecf92014-11-14 22:51:23423 '%~dp0..\\..\\win8sdk\\Lib\\winv6.3\\um\\x64;'
[email protected]7cc7a1c2014-01-15 22:05:05424 '%~dp0..\\..\\VC\\atlmfc\\lib\\amd64\n')
425
426
[email protected]71756322014-03-02 22:59:57427def DoTreeMirror(target_dir, tree_sha1):
428 """In order to save temporary space on bots that do not have enough space to
429 download ISOs, unpack them, and copy to the target location, the whole tree
430 is uploaded as a zip to internal storage, and then mirrored here."""
431 local_zip = DownloadUsingGsutil(tree_sha1 + '.zip')
432 sys.stdout.write('Extracting %s...\n' % local_zip)
433 sys.stdout.flush()
434 RunOrDie('7z x "%s" -y "-o%s" >nul' % (local_zip, target_dir))
435
436
[email protected]7cc7a1c2014-01-15 22:05:05437def main():
438 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
439 parser.add_option('--targetdir', metavar='DIR',
440 help='put toolchain into DIR',
441 default=os.path.join(BASEDIR, 'win_toolchain_2013'))
442 parser.add_option('--noclean', action='store_false', dest='clean',
443 help='do not remove temp files',
444 default=True)
445 parser.add_option('--local', metavar='DIR',
446 help='use downloaded files from DIR')
447 parser.add_option('--express',
448 help='use VS Express instead of Pro', action='store_true')
[email protected]71756322014-03-02 22:59:57449 parser.add_option('--sha1',
450 help='tree sha1 that can be used to mirror an internal '
[email protected]0d23d772014-03-07 20:17:49451 'copy (used if --use-gs)')
452 parser.add_option('--use-gs',
[email protected]26cb8362014-02-04 00:07:02453 help='Use internal servers to pull isos',
454 default=bool(int(os.environ.get('CHROME_HEADLESS', 0))),
455 action='store_true')
[email protected]9eabb222014-01-16 02:42:43456 options, _ = parser.parse_args()
[email protected]7cc7a1c2014-01-15 22:05:05457 try:
458 target_dir = os.path.abspath(options.targetdir)
459 if os.path.exists(target_dir):
460 parser.error('%s already exists. Please [re]move it or use '
[email protected]71756322014-03-02 22:59:57461 '--targetdir to select a different target.\n' %
462 target_dir)
[email protected]7cc7a1c2014-01-15 22:05:05463 # Set the working directory to 7z subdirectory. 7-zip doesn't find its
464 # codec dll very well, so this is the simplest way to make sure it runs
465 # correctly, as we don't otherwise care about working directory.
466 os.chdir(os.path.join(BASEDIR, '7z'))
[email protected]0d23d772014-03-07 20:17:49467 if options.use_gs and options.sha1:
[email protected]454f2ca2014-03-06 17:08:24468 options.express = False
[email protected]71756322014-03-02 22:59:57469 DoTreeMirror(target_dir, options.sha1)
470 else:
471 images = GetSourceImages(options.local, not options.express)
472 extracted = ExtractComponents(images)
473 CopyToFinalLocation(extracted, target_dir)
474 GenerateSetEnvCmd(target_dir, not options.express)
[email protected]7cc7a1c2014-01-15 22:05:05475
[email protected]5d17b922014-02-22 01:47:53476 data = {
477 'path': target_dir,
478 'version': '2013e' if options.express else '2013',
479 'win8sdk': os.path.join(target_dir, 'win8sdk'),
480 'wdk': os.path.join(target_dir, 'wdk'),
481 'runtime_dirs': [
482 os.path.join(target_dir, 'sys64'),
483 os.path.join(target_dir, 'sys32'),
484 ],
485 }
[email protected]360f0322014-02-22 03:21:23486 with open(os.path.join(target_dir, '..', 'data.json'), 'w') as f:
[email protected]5d17b922014-02-22 01:47:53487 json.dump(data, f)
[email protected]7cc7a1c2014-01-15 22:05:05488 finally:
489 if options.clean:
490 DeleteAllTempDirs()
491
492
493if __name__ == '__main__':
494 sys.exit(main())