1 # Copyright 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 # Extracts a Windows toolchain suitable for building Chrome from various
10 from optparse import OptionParser
22 def GetLongPathName(path):
23 """Converts any 8dot3 names in the path to the full name."""
24 buf = ctypes.create_unicode_buffer(260)
25 size = ctypes.windll.kernel32.GetLongPathNameW(unicode(path), buf, 260)
27 raise SystemExit('Long form of path longer than 260 chars: %s' % path)
31 def RunOrDie(command):
32 rc = subprocess.call(command, shell=True)
34 raise SystemExit('%s failed.' % command)
38 """Generate a temporary directory (for downloading or extracting to) and keep
39 track of the directory that's created for cleaning up later."""
41 temp = tempfile.mkdtemp()
42 g_temp_dirs.append(temp)
46 def DeleteAllTempDirs():
47 """Remove all temporary directories created by |TempDir()|."""
50 sys.stdout.write('Cleaning up temporaries...\n')
51 for temp in g_temp_dirs:
52 # shutil.rmtree errors out on read only attributes.
53 RunOrDie('rmdir /s/q "%s"' % temp)
57 def Download(url, local_path):
58 """Download a large-ish binary file and print some status information while
60 sys.stdout.write('Downloading %s...\n' % url)
61 req = urllib2.urlopen(url)
62 content_length = int(req.headers.get('Content-Length', 0))
64 terminator = '\r' if sys.stdout.isatty() else '\n'
65 with open(local_path, 'wb') as file:
67 chunk = req.read(1024 * 1024)
70 bytes_read += len(chunk)
72 sys.stdout.write('... %d/%d%s' % (bytes_read, content_length, terminator))
74 sys.stdout.write('\n')
75 if content_length and content_length != bytes_read:
76 raise SystemExit('Got incorrect number of bytes downloading %s' % url)
79 def DownloadSDK71Iso():
80 sdk7_temp_dir = TempDir()
81 target_path = os.path.join(sdk7_temp_dir, 'GRMSDKX_EN_DVD.iso')
83 ('http://download.microsoft.com/download/'
84 'F/1/0/F10113F5-B750-4969-A255-274341AC6BCE/GRMSDKX_EN_DVD.iso'),
90 wdk_temp_dir = TempDir()
91 target_path = os.path.join(wdk_temp_dir, 'GRMWDK_EN_7600_1.ISO')
93 ('http://download.microsoft.com/download/'
94 '4/A/2/4A25C7D5-EFBE-4182-B6A9-AE6850409A78/GRMWDK_EN_7600_1.ISO'),
99 def DownloadSDKUpdate():
100 sdk_update_temp_dir = TempDir()
101 target_path = os.path.join(sdk_update_temp_dir, 'VC-Compiler-KB2519277.exe')
103 ('http://download.microsoft.com/download/'
104 '7/5/0/75040801-126C-4591-BCE4-4CD1FD1499AA/VC-Compiler-KB2519277.exe'),
109 def DownloadDirectXSDK():
110 dxsdk_temp_dir = TempDir()
111 target_path = os.path.join(dxsdk_temp_dir, 'DXSDK_Jun10.exe')
113 ('http://download.microsoft.com/download/'
114 'A/E/7/AE743F1F-632B-4809-87A9-AA1BB3458E31/DXSDK_Jun10.exe'),
119 def DownloadVS2012ExIso():
120 ex_temp_dir = TempDir()
121 target_path = os.path.join(ex_temp_dir, 'VS2012_WDX_ENU.iso')
123 ('http://download.microsoft.com/download/'
124 '1/F/5/1F519CC5-0B90-4EA3-8159-33BFB97EF4D9/VS2012_WDX_ENU.iso'),
130 """Download the Win8 SDK. This one is slightly different than the simple
131 ones above. There is no .ISO distribution for the Windows 8 SDK. Rather, a
132 tool is provided that is a download manager. This is used to download the
133 various .msi files to a target location. Unfortunately, this tool requires
134 elevation for no obvious reason even when only downloading, so this function
135 will trigger a UAC elevation if the script is not run from an elevated
137 # Use the long path name here because because 8dot3 names don't seem to work.
138 sdk_temp_dir = GetLongPathName(TempDir())
139 target_path = os.path.join(sdk_temp_dir, 'sdksetup.exe')
140 standalone_path = os.path.join(sdk_temp_dir, 'Standalone')
142 ('http://download.microsoft.com/download/'
143 'F/1/3/F1300C9C-A120-4341-90DF-8A52509B23AC/standalonesdk/sdksetup.exe'),
146 'Running sdksetup.exe to download Win8 SDK (may request elevation)...\n')
149 rc = subprocess.call([target_path, '/quiet', '/features',
150 'OptionId.WindowsDesktopSoftwareDevelopmentKit',
151 '/layout', standalone_path])
153 return standalone_path
155 sys.stdout.write('Windows 8 SDK failed to download, retrying.\n')
156 raise SystemExit("After multiple retries, couldn't download Win8 SDK")
159 def DownloadVS2012Update3():
160 """Download Update3 to VS2012. See notes in DownloadSDK8."""
161 update3_dir = TempDir()
162 target_path = os.path.join(update3_dir, 'VS2012.3.iso')
164 ('http://download.microsoft.com/download/'
165 'D/4/8/D48D1AC2-A297-4C9E-A9D0-A218E6609F06/VS2012.3.iso'),
170 class SourceImages2010(object):
171 def __init__(self, sdk8_path, wdk_iso, sdk7_update, sdk7_path, dxsdk_path):
172 self.sdk8_path = sdk8_path
173 self.wdk_iso = wdk_iso
174 self.sdk7_update = sdk7_update
175 self.sdk7_path = sdk7_path
176 self.dxsdk_path = dxsdk_path
179 def GetSourceImages2010(local_dir):
180 """Download all distribution archives for the components we need."""
182 return SourceImages2010(
183 sdk8_path=os.path.join(local_dir, 'Standalone'),
184 wdk_iso=os.path.join(local_dir, 'GRMWDK_EN_7600_1.ISO'),
185 sdk7_update=os.path.join(local_dir, 'VC-Compiler-KB2519277.exe'),
186 sdk7_path=os.path.join(local_dir, 'GRMSDKX_EN_DVD.ISO'),
187 dxsdk_path=os.path.join(local_dir, 'DXSDK_Jun10.exe'))
189 # Note that we do the Win8 SDK first so that its silly UAC prompt
190 # happens before the user wanders off to get coffee.
191 sdk8_path = DownloadSDK8()
192 wdk_iso = DownloadWDKIso()
193 sdk7_update = DownloadSDKUpdate()
194 sdk7_path = DownloadSDK71Iso()
195 dxsdk_path = DownloadDirectXSDK()
196 return SourceImages2010(
197 sdk8_path, wdk_iso, sdk7_update, sdk7_path, dxsdk_path)
200 class SourceImages2012():
201 def __init__(self, ex_path, update_path, wdk_iso):
202 self.ex_path = ex_path
203 self.update_path = update_path
204 self.wdk_iso = wdk_iso
207 def GetSourceImages2012(local_dir):
208 """Download all distribution archives for the components we need."""
210 return SourceImages2012(
211 ex_path=os.path.join(local_dir, 'VS2012_WDX_ENU.iso'),
212 update_path=os.path.join(local_dir, 'VS2012.3.iso'),
213 wdk_iso=os.path.join(local_dir, 'GRMWDK_EN_7600_1.ISO'))
215 ex_path = DownloadVS2012ExIso()
216 wdk_iso = DownloadWDKIso()
217 update_path = DownloadVS2012Update3()
218 return SourceImages2012(
220 update_path=update_path,
224 def ExtractIso(iso_path):
225 """Use 7zip to extract the contents of the given .iso (or self-extracting
227 target_path = TempDir()
228 sys.stdout.write('Extracting %s...\n' % iso_path)
230 # TODO(scottmg): Do this (and exe) manually with python code.
231 # Note that at the beginning of main() we set the working directory to 7z's
233 RunOrDie('7z x "%s" -y "-o%s" >nul' % (iso_path, target_path))
237 ExtractExe = ExtractIso
240 def ExtractMsi(msi_path):
241 """Use msiexec to extract the contents of the given .msi file."""
242 sys.stdout.write('Extracting %s...\n' % msi_path)
243 target_path = TempDir()
244 RunOrDie('msiexec /a "%s" /qn TARGETDIR="%s"' % (msi_path, target_path))
248 class ExtractedComponents2010(object):
251 buildtools_x86, buildtools_x64, libs_x86, libs_x64, headers,
252 update_x86, update_x64,
253 sdk_path, metro_sdk_path,
257 self.buildtools_x86 = buildtools_x86
258 self.buildtools_x64 = buildtools_x64
259 self.libs_x86 = libs_x86
260 self.libs_x64 = libs_x64
261 self.headers = headers
262 self.update_x86 = update_x86
263 self.update_x64 = update_x64
264 self.sdk_path = sdk_path
265 self.metro_sdk_path = metro_sdk_path
269 def ExtractComponents2010(images):
270 """Given the paths to the images, extract the required parts, and return
271 an object containing paths to all the pieces."""
272 extracted_sdk7 = ExtractIso(images.sdk7_path)
274 ExtractMsi(os.path.join(extracted_sdk7,
275 r'Setup\vc_stdx86\vc_stdx86.msi'))
277 ExtractMsi(os.path.join(extracted_sdk7,
278 r'Setup\vc_stdamd64\vc_stdamd64.msi'))
280 extracted_wdk = ExtractIso(images.wdk_iso)
281 extracted_buildtools_x86 = \
282 ExtractMsi(os.path.join(extracted_wdk, r'WDK\buildtools_x86fre.msi'))
283 extracted_buildtools_x64 = \
284 ExtractMsi(os.path.join(extracted_wdk, r'WDK\buildtools_x64fre.msi'))
285 extracted_libs_x86 = \
286 ExtractMsi(os.path.join(extracted_wdk, r'WDK\libs_x86fre.msi'))
287 extracted_libs_x64 = \
288 ExtractMsi(os.path.join(extracted_wdk, r'WDK\libs_x64fre.msi'))
289 extracted_headers = \
290 ExtractMsi(os.path.join(extracted_wdk, r'WDK\headers.msi'))
292 extracted_update = ExtractExe(images.sdk7_update)
293 extracted_update_x86 = \
294 ExtractMsi(os.path.join(extracted_update, 'vc_stdx86.msi'))
295 extracted_update_x64 = \
296 ExtractMsi(os.path.join(extracted_update, 'vc_stdamd64.msi'))
298 sdk_msi_path = os.path.join(
300 r'Installers\Windows Software Development Kit-x86_en-us.msi')
301 extracted_sdk_path = ExtractMsi(sdk_msi_path)
303 sdk_metro_msi_path = os.path.join(
306 'Windows Software Development Kit for Metro style Apps-x86_en-us.msi')
307 extracted_metro_sdk_path = ExtractMsi(sdk_metro_msi_path)
309 extracted_dxsdk = ExtractExe(images.dxsdk_path)
311 return ExtractedComponents2010(
312 vc_x86=extracted_vc_x86,
313 vc_x64=extracted_vc_x64,
314 buildtools_x86=extracted_buildtools_x86,
315 buildtools_x64=extracted_buildtools_x64,
316 libs_x86=extracted_libs_x86,
317 libs_x64=extracted_libs_x64,
318 headers=extracted_headers,
319 update_x86=extracted_update_x86,
320 update_x64=extracted_update_x64,
321 sdk_path=extracted_sdk_path,
322 metro_sdk_path=extracted_metro_sdk_path,
323 dxsdk=extracted_dxsdk)
326 class ExtractedComponents2012(object):
328 vc_x86, vc_x86_res, librarycore,
329 vc_x86_update, vc_x86_res_update, librarycore_update,
330 sdk_path, metro_sdk_path,
331 buildtools_x86, buildtools_x64, libs_x86, libs_x64, headers):
333 self.vc_x86_res = vc_x86_res
334 self.librarycore = librarycore
335 self.vc_x86_update = vc_x86_update
336 self.vc_x86_res_update = vc_x86_res_update
337 self.librarycore_update = librarycore_update
338 self.buildtools_x86 = buildtools_x86
339 self.buildtools_x64 = buildtools_x64
340 self.libs_x86 = libs_x86
341 self.libs_x64 = libs_x64
342 self.headers = headers
343 self.sdk_path = sdk_path
344 self.metro_sdk_path = metro_sdk_path
347 def ExtractComponents2012(images):
348 """Given the paths to the images, extract the required parts and return an
349 object containing paths to all the pieces."""
350 extracted_ex = ExtractIso(images.ex_path)
352 extracted_compilercore = ExtractMsi(os.path.join(
354 r'packages\vc_compilerCore86\vc_compilerCore86.msi'))
356 extracted_compilercore_res = ExtractMsi(os.path.join(
358 r'packages\vc_compilerCore86res\vc_compilerCore86res.msi'))
360 extracted_librarycore = ExtractMsi(os.path.join(
362 r'packages\vc_librarycore86\vc_librarycore86.msi'))
364 extracted_wdk = ExtractIso(images.wdk_iso)
365 extracted_buildtools_x86 = \
366 ExtractMsi(os.path.join(extracted_wdk, r'WDK\buildtools_x86fre.msi'))
367 extracted_buildtools_x64 = \
368 ExtractMsi(os.path.join(extracted_wdk, r'WDK\buildtools_x64fre.msi'))
369 extracted_libs_x86 = \
370 ExtractMsi(os.path.join(extracted_wdk, r'WDK\libs_x86fre.msi'))
371 extracted_libs_x64 = \
372 ExtractMsi(os.path.join(extracted_wdk, r'WDK\libs_x64fre.msi'))
373 extracted_headers = \
374 ExtractMsi(os.path.join(extracted_wdk, r'WDK\headers.msi'))
376 sdk_msi_path = os.path.join(
377 extracted_ex, 'packages', 'Windows_SDK',
378 r'Windows Software Development Kit-x86_en-us.msi')
379 extracted_sdk_path = ExtractMsi(sdk_msi_path)
381 sdk_metro_msi_path = os.path.join(
382 extracted_ex, 'packages', 'Windows_SDK',
383 'Windows Software Development Kit for Metro style Apps-x86_en-us.msi')
384 extracted_metro_sdk_path = ExtractMsi(sdk_metro_msi_path)
386 extracted_update = ExtractIso(images.update_path)
388 extracted_compilercore_update = ExtractMsi(os.path.join(
389 extracted_update, r'packages\vc_compilercore86\vc_compilercore86.msi'))
391 extracted_compilercore_res_update = ExtractMsi(os.path.join(
393 r'packages\vc_compilercore86res\enu\vc_compilercore86res.msi'))
395 extracted_librarycore_update = ExtractMsi(os.path.join(
396 extracted_update, r'packages\vc_librarycore86\vc_librarycore86.msi'))
398 return ExtractedComponents2012(
399 vc_x86=extracted_compilercore,
400 vc_x86_res=extracted_compilercore_res,
401 librarycore=extracted_librarycore,
402 vc_x86_update=extracted_compilercore_update,
403 vc_x86_res_update=extracted_compilercore_res_update,
404 librarycore_update=extracted_compilercore_update,
405 sdk_path=extracted_sdk_path,
406 metro_sdk_path=extracted_metro_sdk_path,
407 buildtools_x86=extracted_buildtools_x86,
408 buildtools_x64=extracted_buildtools_x64,
409 libs_x86=extracted_libs_x86,
410 libs_x64=extracted_libs_x64,
411 headers=extracted_headers)
414 def PullFrom(list_of_path_pairs, source_root, target_dir):
415 """Each pair in |list_of_path_pairs| is (from, to). Join the 'from' with
416 |source_root| and the 'to' with |target_dir| and perform a recursive copy."""
417 for source, destination in list_of_path_pairs:
418 full_source = os.path.join(source_root, source)
419 full_target = os.path.join(target_dir, destination)
420 rc = os.system('robocopy /s "%s" "%s" >nul' % (full_source, full_target))
421 if (rc & 8) != 0 or (rc & 16) != 0:
422 # ref: http://ss64.com/nt/robocopy-exit.html
423 raise SystemExit("Couldn't copy %s to %s" % (full_source, full_target))
426 def CopyToFinalLocation2010(extracted, target_dir):
427 """Copy all the directories we need to the target location."""
428 sys.stdout.write('Pulling together required pieces...\n')
430 # Note that order is important because some of the older ones are
431 # overwritten by updates.
432 from_sdk = [(r'Windows Kits\8.0', r'win8sdk')]
433 PullFrom(from_sdk, extracted.sdk_path, target_dir)
435 from_metro_sdk = [(r'Windows Kits\8.0', r'win8sdk')]
436 PullFrom(from_sdk, extracted.metro_sdk_path, target_dir)
438 from_buildtools_x86 = [
439 (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\x86', r'WDK\bin'),
441 PullFrom(from_buildtools_x86, extracted.buildtools_x86, target_dir)
443 from_buildtools_x64 = [
444 (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\amd64', r'WDK\bin'),
446 PullFrom(from_buildtools_x64, extracted.buildtools_x64, target_dir)
449 (r'WinDDK\7600.16385.win7_wdk.100208-1538\lib', r'WDK\lib'),
451 PullFrom(from_libs_x86, extracted.libs_x86, target_dir)
454 (r'WinDDK\7600.16385.win7_wdk.100208-1538\lib', r'WDK\lib'),
456 PullFrom(from_libs_x64, extracted.libs_x64, target_dir)
459 (r'WinDDK\7600.16385.win7_wdk.100208-1538\inc', r'WDK\inc'),
461 PullFrom(from_headers, extracted.headers, target_dir)
463 # The compiler update to get the SP1 compiler is a bit of a mess. See
464 # http://goo.gl/n1DeO. The summary is that update for the standalone compiler
465 # binary installs a broken set of headers. So, add an empty ammintrin.h since
466 # we don't actually need the contents of it (for Chromium).
469 (r'Program Files\Microsoft Visual Studio 10.0', '.'),
470 (r'Win\System', r'VC\bin'),
472 PullFrom(from_sdk7_x86, extracted.vc_x86, target_dir)
475 (r'Program Files(64)\Microsoft Visual Studio 10.0', '.'),
476 (r'Win\System64', r'VC\bin\amd64'),
478 PullFrom(from_sdk7_x64, extracted.vc_x64, target_dir)
480 from_vcupdate_x86 = [
481 (r'Program Files\Microsoft Visual Studio 10.0', '.'),
482 (r'Win\System', r'VC\bin'),
484 PullFrom(from_vcupdate_x86, extracted.update_x86, target_dir)
486 from_vcupdate_x64 = [
487 (r'Program Files(64)\Microsoft Visual Studio 10.0', '.'),
488 (r'Win\System64', r'VC\bin\amd64'),
490 PullFrom(from_vcupdate_x64, extracted.update_x64, target_dir)
492 sys.stdout.write('Stubbing ammintrin.h...\n')
493 open(os.path.join(target_dir, r'VC\include\ammintrin.h'), 'w').close()
496 (r'DXSDK\Include', r'DXSDK\Include'),
497 (r'DXSDK\Lib', r'DXSDK\Lib'),
498 (r'DXSDK\Redist', r'DXSDK\Redist'),
500 PullFrom(from_dxsdk, extracted.dxsdk, target_dir)
503 def CopyToFinalLocation2012(extracted, target_dir):
504 """Copy all directories we need to the target location."""
505 sys.stdout.write('Pulling together required pieces...\n')
507 # Note that order is important because some of the older ones are
508 # overwritten by updates.
509 from_sdk = [(r'Windows Kits\8.0', r'win8sdk')]
510 PullFrom(from_sdk, extracted.sdk_path, target_dir)
512 from_metro_sdk = [(r'Windows Kits\8.0', r'win8sdk')]
513 PullFrom(from_sdk, extracted.metro_sdk_path, target_dir)
516 from_compiler = [(r'Program Files\Microsoft Visual Studio 11.0', '.')]
517 PullFrom(from_compiler, extracted.vc_x86, target_dir)
519 from_compiler_res = [(r'Program Files\Microsoft Visual Studio 11.0', '.')]
520 PullFrom(from_compiler_res, extracted.vc_x86_res, target_dir)
522 from_library = [(r'Program Files\Microsoft Visual Studio 11.0', '.')]
523 PullFrom(from_library, extracted.librarycore, target_dir)
526 from_buildtools_x86 = [
527 (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\x86', r'WDK\bin'),
529 PullFrom(from_buildtools_x86, extracted.buildtools_x86, target_dir)
531 from_buildtools_x64 = [
532 (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\amd64', r'WDK\bin'),
534 PullFrom(from_buildtools_x64, extracted.buildtools_x64, target_dir)
536 from_libs_x86 = [(r'WinDDK\7600.16385.win7_wdk.100208-1538\lib', r'WDK\lib')]
537 PullFrom(from_libs_x86, extracted.libs_x86, target_dir)
539 from_libs_x64 = [(r'WinDDK\7600.16385.win7_wdk.100208-1538\lib', r'WDK\lib')]
540 PullFrom(from_libs_x64, extracted.libs_x64, target_dir)
542 from_headers = [(r'WinDDK\7600.16385.win7_wdk.100208-1538\inc', r'WDK\inc')]
543 PullFrom(from_headers, extracted.headers, target_dir)
546 from_compiler = [(r'Program Files\Microsoft Visual Studio 11.0', '.')]
547 PullFrom(from_compiler, extracted.vc_x86_update, target_dir)
549 from_compiler_res = [(r'Program Files\Microsoft Visual Studio 11.0', '.')]
550 PullFrom(from_compiler_res, extracted.vc_x86_res_update, target_dir)
552 from_library = [(r'Program Files\Microsoft Visual Studio 11.0', '.')]
553 PullFrom(from_library, extracted.librarycore_update, target_dir)
556 def PatchAsyncInfo(target_dir):
558 http://www.chromium.org/developers/how-tos/build-instructions-windows for
560 # This is only required for the 2010 compiler.
561 sys.stdout.write('Patching asyncinfo.h...\n')
562 asyncinfo_h_path = os.path.join(
563 target_dir, r'win8sdk\Include\winrt\asyncinfo.h')
564 with open(asyncinfo_h_path, 'rb') as f:
565 asyncinfo_h = f.read()
566 patched = asyncinfo_h.replace(
567 'enum class AsyncStatus {', 'enum AsyncStatus {')
568 with open(asyncinfo_h_path, 'wb') as f:
572 def GenerateSetEnvCmd(target_dir, vsversion):
573 """Generate a batch file that gyp expects to exist to set up the compiler
574 environment. This is normally generated by a full install of the SDK, but we
575 do it here manually since we do not do a full install."""
576 with open(os.path.join(
577 target_dir, r'win8sdk\bin\SetEnv.cmd'), 'w') as file:
578 file.write('@echo off\n')
579 file.write(':: Generated by tools\\win\\toolchain\\toolchain.py.\n')
580 file.write(':: Targeting VS%s.\n' % vsversion)
581 # Common to x86 and x64
582 file.write('set PATH=%s;%%PATH%%\n' % (
583 os.path.join(target_dir, r'Common7\IDE')))
584 file.write('set INCLUDE=%s;%s;%s\n' % (
585 os.path.join(target_dir, r'win8sdk\Include\um'),
586 os.path.join(target_dir, r'win8sdk\Include\shared'),
587 os.path.join(target_dir, r'VC\include')))
588 file.write('if "%1"=="/x64" goto x64\n')
591 file.write('set PATH=%s;%s;%s;%%PATH%%\n' % (
592 os.path.join(target_dir, r'win8sdk\bin\x86'),
593 os.path.join(target_dir, r'VC\bin'),
594 os.path.join(target_dir, r'WDK\bin')))
595 file.write('set LIB=%s;%s\n' % (
596 os.path.join(target_dir, r'VC\lib'),
597 os.path.join(target_dir, r'win8sdk\Lib\win8\um\x86')))
598 file.write('goto done\n')
600 # Unfortunately, 2012 Express does not include a native 64 bit compiler,
601 # so we have to use the x86->x64 cross.
602 if vsversion == '2012':
605 file.write('set PATH=%s;%s;%s;%%PATH%%\n' % (
606 os.path.join(target_dir, r'win8sdk\bin\x64'),
607 os.path.join(target_dir, r'VC\bin\x86_amd64'),
608 os.path.join(target_dir, r'WDK\bin\amd64')))
609 file.write('set LIB=%s;%s\n' % (
610 os.path.join(target_dir, r'VC\lib\amd64'),
611 os.path.join(target_dir, r'win8sdk\Lib\win8\um\x64')))
615 file.write('set PATH=%s;%s;%s;%%PATH%%\n' % (
616 os.path.join(target_dir, r'win8sdk\bin\x64'),
617 os.path.join(target_dir, r'VC\bin\amd64'),
618 os.path.join(target_dir, r'WDK\bin\amd64')))
619 file.write('set LIB=%s;%s\n' % (
620 os.path.join(target_dir, r'VC\lib\amd64'),
621 os.path.join(target_dir, r'win8sdk\Lib\win8\um\x64')))
623 file.write(':done\n')
626 def GenerateTopLevelEnv(target_dir, vsversion):
627 """Generate a batch file that sets up various environment variables that let
628 the Chromium build files and gyp find SDKs and tools."""
629 with open(os.path.join(target_dir, r'env.bat'), 'w') as file:
630 file.write('@echo off\n')
631 file.write(':: Generated by tools\\win\\toolchain\\toolchain.py.\n')
632 file.write(':: Targeting VS%s.\n' % vsversion)
633 file.write('set GYP_DEFINES=windows_sdk_path="%s" '
634 'component=shared_library\n' % (
635 os.path.join(target_dir, 'win8sdk')))
636 file.write('set GYP_MSVS_VERSION=%se\n' % vsversion)
637 file.write('set GYP_MSVS_OVERRIDE_PATH=%s\n' % target_dir)
638 file.write('set GYP_GENERATORS=ninja\n')
639 file.write('set GYP_PARALLEL=1\n')
640 file.write('set WDK_DIR=%s\n' % os.path.join(target_dir, r'WDK'))
641 if vsversion == '2010':
642 file.write('set DXSDK_DIR=%s\n' % os.path.join(target_dir, r'DXSDK'))
643 file.write('set WindowsSDKDir=%s\n' %
644 os.path.join(target_dir, r'win8sdk'))
645 if vsversion == '2012':
646 # TODO: For 2010 too.
647 base = os.path.join(target_dir, r'VC\redist')
649 r'Debug_NonRedist\x64\Microsoft.VC110.DebugCRT',
650 r'Debug_NonRedist\x86\Microsoft.VC110.DebugCRT',
651 r'x64\Microsoft.VC110.CRT',
652 r'x86\Microsoft.VC110.CRT',
654 additions = ';'.join(os.path.join(base, x) for x in paths)
655 file.write('set PATH=%s;%%PATH%%\n' % additions)
656 file.write('echo Environment set for toolchain in %s.\n' % target_dir)
657 file.write('cd /d %s\\..\n' % target_dir)
661 parser = OptionParser()
662 parser.add_option('--targetdir', metavar='DIR',
663 help='put toolchain into DIR',
664 default=os.path.abspath('win_toolchain'))
665 parser.add_option('--vsversion', metavar='VSVERSION',
666 help='select VS version: 2010 or 2012', default='2010')
667 parser.add_option('--noclean', action='store_false', dest='clean',
668 help='do not remove temp files',
670 parser.add_option('--local', metavar='DIR',
671 help='use downloaded files from DIR')
672 options, args = parser.parse_args()
674 target_dir = os.path.abspath(options.targetdir)
675 if os.path.exists(target_dir):
676 sys.stderr.write('%s already exists. Please [re]move it or use '
677 '--targetdir to select a different target.\n' %
680 # Set the working directory to 7z subdirectory. 7-zip doesn't find its
681 # codec dll very well, so this is the simplest way to make sure it runs
682 # correctly, as we don't otherwise care about working directory.
683 os.chdir(os.path.join(os.path.dirname(os.path.abspath(__file__)), '7z'))
684 assert options.vsversion in ('2010', '2012')
685 if options.vsversion == '2012':
686 images = GetSourceImages2012(options.local)
687 extracted = ExtractComponents2012(images)
688 CopyToFinalLocation2012(extracted, target_dir)
690 images = GetSourceImages2010(options.local)
691 extracted = ExtractComponents2010(images)
692 CopyToFinalLocation2010(extracted, target_dir)
693 PatchAsyncInfo(target_dir)
695 GenerateSetEnvCmd(target_dir, options.vsversion)
696 GenerateTopLevelEnv(target_dir, options.vsversion)
702 '\nIn a (clean) cmd shell, you can now run\n\n'
705 " gclient runhooks (or gclient sync if you haven't pulled deps yet)\n"
706 ' ninja -C out\Debug chrome\n\n'
707 'Note that this script intentionally does not modify any global\n'
708 'settings like the registry, or system environment variables, so you\n'
709 'will need to run the above env.bat whenever you start a new\n'
710 'shell.\n\n' % target_dir)
713 if __name__ == '__main__':