OLD | NEW |
| (Empty) |
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. | |
4 | |
5 # Extracts a Windows toolchain suitable for building Chrome from various | |
6 # downloadable pieces. | |
7 | |
8 | |
9 import ctypes | |
10 from optparse import OptionParser | |
11 import os | |
12 import shutil | |
13 import subprocess | |
14 import sys | |
15 import tempfile | |
16 import urllib2 | |
17 | |
18 | |
19 g_temp_dirs = [] | |
20 | |
21 | |
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) | |
26 if (size > 260): | |
27 raise SystemExit('Long form of path longer than 260 chars: %s' % path) | |
28 return buf.value | |
29 | |
30 | |
31 def RunOrDie(command): | |
32 rc = subprocess.call(command, shell=True) | |
33 if rc != 0: | |
34 raise SystemExit('%s failed.' % command) | |
35 | |
36 | |
37 def TempDir(): | |
38 """Generate a temporary directory (for downloading or extracting to) and keep | |
39 track of the directory that's created for cleaning up later.""" | |
40 global g_temp_dirs | |
41 temp = tempfile.mkdtemp() | |
42 g_temp_dirs.append(temp) | |
43 return temp | |
44 | |
45 | |
46 def DeleteAllTempDirs(): | |
47 """Remove all temporary directories created by |TempDir()|.""" | |
48 global g_temp_dirs | |
49 if g_temp_dirs: | |
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) | |
54 g_temp_dirs = [] | |
55 | |
56 | |
57 def Download(url, local_path): | |
58 """Download a large-ish binary file and print some status information while | |
59 doing so.""" | |
60 sys.stdout.write('Downloading %s...\n' % url) | |
61 req = urllib2.urlopen(url) | |
62 content_length = int(req.headers.get('Content-Length', 0)) | |
63 bytes_read = 0 | |
64 terminator = '\r' if sys.stdout.isatty() else '\n' | |
65 with open(local_path, 'wb') as file: | |
66 while True: | |
67 chunk = req.read(1024 * 1024) | |
68 if not chunk: | |
69 break | |
70 bytes_read += len(chunk) | |
71 file.write(chunk) | |
72 sys.stdout.write('... %d/%d%s' % (bytes_read, content_length, terminator)) | |
73 sys.stdout.flush() | |
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) | |
77 | |
78 | |
79 def DownloadSDK71Iso(): | |
80 sdk7_temp_dir = TempDir() | |
81 target_path = os.path.join(sdk7_temp_dir, 'GRMSDKX_EN_DVD.iso') | |
82 Download( | |
83 ('http://download.microsoft.com/download/' | |
84 'F/1/0/F10113F5-B750-4969-A255-274341AC6BCE/GRMSDKX_EN_DVD.iso'), | |
85 target_path) | |
86 return target_path | |
87 | |
88 | |
89 def DownloadWDKIso(): | |
90 wdk_temp_dir = TempDir() | |
91 target_path = os.path.join(wdk_temp_dir, 'GRMWDK_EN_7600_1.ISO') | |
92 Download( | |
93 ('http://download.microsoft.com/download/' | |
94 '4/A/2/4A25C7D5-EFBE-4182-B6A9-AE6850409A78/GRMWDK_EN_7600_1.ISO'), | |
95 target_path) | |
96 return target_path | |
97 | |
98 | |
99 def DownloadSDKUpdate(): | |
100 sdk_update_temp_dir = TempDir() | |
101 target_path = os.path.join(sdk_update_temp_dir, 'VC-Compiler-KB2519277.exe') | |
102 Download( | |
103 ('http://download.microsoft.com/download/' | |
104 '7/5/0/75040801-126C-4591-BCE4-4CD1FD1499AA/VC-Compiler-KB2519277.exe'), | |
105 target_path) | |
106 return target_path | |
107 | |
108 | |
109 def DownloadDirectXSDK(): | |
110 dxsdk_temp_dir = TempDir() | |
111 target_path = os.path.join(dxsdk_temp_dir, 'DXSDK_Jun10.exe') | |
112 Download( | |
113 ('http://download.microsoft.com/download/' | |
114 'A/E/7/AE743F1F-632B-4809-87A9-AA1BB3458E31/DXSDK_Jun10.exe'), | |
115 target_path) | |
116 return target_path | |
117 | |
118 | |
119 def DownloadVS2012ExIso(): | |
120 ex_temp_dir = TempDir() | |
121 target_path = os.path.join(ex_temp_dir, 'VS2012_WDX_ENU.iso') | |
122 Download( | |
123 ('http://download.microsoft.com/download/' | |
124 '1/F/5/1F519CC5-0B90-4EA3-8159-33BFB97EF4D9/VS2012_WDX_ENU.iso'), | |
125 target_path) | |
126 return target_path | |
127 | |
128 | |
129 def DownloadSDK8(): | |
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 | |
136 prompt.""" | |
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') | |
141 Download( | |
142 ('http://download.microsoft.com/download/' | |
143 'F/1/3/F1300C9C-A120-4341-90DF-8A52509B23AC/standalonesdk/sdksetup.exe'), | |
144 target_path) | |
145 sys.stdout.write( | |
146 'Running sdksetup.exe to download Win8 SDK (may request elevation)...\n') | |
147 count = 0 | |
148 while count < 5: | |
149 rc = subprocess.call([target_path, '/quiet', '/features', | |
150 'OptionId.WindowsDesktopSoftwareDevelopmentKit', | |
151 '/layout', standalone_path]) | |
152 if rc == 0: | |
153 return standalone_path | |
154 count += 1 | |
155 sys.stdout.write('Windows 8 SDK failed to download, retrying.\n') | |
156 raise SystemExit("After multiple retries, couldn't download Win8 SDK") | |
157 | |
158 | |
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') | |
163 Download( | |
164 ('http://download.microsoft.com/download/' | |
165 'D/4/8/D48D1AC2-A297-4C9E-A9D0-A218E6609F06/VS2012.3.iso'), | |
166 target_path) | |
167 return target_path | |
168 | |
169 | |
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 | |
177 | |
178 | |
179 def GetSourceImages2010(local_dir): | |
180 """Download all distribution archives for the components we need.""" | |
181 if local_dir: | |
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')) | |
188 else: | |
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) | |
198 | |
199 | |
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 | |
205 | |
206 | |
207 def GetSourceImages2012(local_dir): | |
208 """Download all distribution archives for the components we need.""" | |
209 if local_dir: | |
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')) | |
214 else: | |
215 ex_path = DownloadVS2012ExIso() | |
216 wdk_iso = DownloadWDKIso() | |
217 update_path = DownloadVS2012Update3() | |
218 return SourceImages2012( | |
219 ex_path=ex_path, | |
220 update_path=update_path, | |
221 wdk_iso=wdk_iso) | |
222 | |
223 | |
224 def ExtractIso(iso_path): | |
225 """Use 7zip to extract the contents of the given .iso (or self-extracting | |
226 .exe).""" | |
227 target_path = TempDir() | |
228 sys.stdout.write('Extracting %s...\n' % iso_path) | |
229 sys.stdout.flush() | |
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 | |
232 # location. | |
233 RunOrDie('7z x "%s" -y "-o%s" >nul' % (iso_path, target_path)) | |
234 return target_path | |
235 | |
236 | |
237 ExtractExe = ExtractIso | |
238 | |
239 | |
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)) | |
245 return target_path | |
246 | |
247 | |
248 class ExtractedComponents2010(object): | |
249 def __init__(self, | |
250 vc_x86, vc_x64, | |
251 buildtools_x86, buildtools_x64, libs_x86, libs_x64, headers, | |
252 update_x86, update_x64, | |
253 sdk_path, metro_sdk_path, | |
254 dxsdk): | |
255 self.vc_x86 = vc_x86 | |
256 self.vc_x64 = vc_x64 | |
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 | |
266 self.dxsdk = dxsdk | |
267 | |
268 | |
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) | |
273 extracted_vc_x86 = \ | |
274 ExtractMsi(os.path.join(extracted_sdk7, | |
275 r'Setup\vc_stdx86\vc_stdx86.msi')) | |
276 extracted_vc_x64 = \ | |
277 ExtractMsi(os.path.join(extracted_sdk7, | |
278 r'Setup\vc_stdamd64\vc_stdamd64.msi')) | |
279 | |
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')) | |
291 | |
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')) | |
297 | |
298 sdk_msi_path = os.path.join( | |
299 images.sdk8_path, | |
300 r'Installers\Windows Software Development Kit-x86_en-us.msi') | |
301 extracted_sdk_path = ExtractMsi(sdk_msi_path) | |
302 | |
303 sdk_metro_msi_path = os.path.join( | |
304 images.sdk8_path, | |
305 'Installers', | |
306 'Windows Software Development Kit for Metro style Apps-x86_en-us.msi') | |
307 extracted_metro_sdk_path = ExtractMsi(sdk_metro_msi_path) | |
308 | |
309 extracted_dxsdk = ExtractExe(images.dxsdk_path) | |
310 | |
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) | |
324 | |
325 | |
326 class ExtractedComponents2012(object): | |
327 def __init__(self, | |
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): | |
332 self.vc_x86 = vc_x86 | |
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 | |
345 | |
346 | |
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) | |
351 | |
352 extracted_compilercore = ExtractMsi(os.path.join( | |
353 extracted_ex, | |
354 r'packages\vc_compilerCore86\vc_compilerCore86.msi')) | |
355 | |
356 extracted_compilercore_res = ExtractMsi(os.path.join( | |
357 extracted_ex, | |
358 r'packages\vc_compilerCore86res\vc_compilerCore86res.msi')) | |
359 | |
360 extracted_librarycore = ExtractMsi(os.path.join( | |
361 extracted_ex, | |
362 r'packages\vc_librarycore86\vc_librarycore86.msi')) | |
363 | |
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')) | |
375 | |
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) | |
380 | |
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) | |
385 | |
386 extracted_update = ExtractIso(images.update_path) | |
387 | |
388 extracted_compilercore_update = ExtractMsi(os.path.join( | |
389 extracted_update, r'packages\vc_compilercore86\vc_compilercore86.msi')) | |
390 | |
391 extracted_compilercore_res_update = ExtractMsi(os.path.join( | |
392 extracted_update, | |
393 r'packages\vc_compilercore86res\enu\vc_compilercore86res.msi')) | |
394 | |
395 extracted_librarycore_update = ExtractMsi(os.path.join( | |
396 extracted_update, r'packages\vc_librarycore86\vc_librarycore86.msi')) | |
397 | |
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) | |
412 | |
413 | |
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)) | |
424 | |
425 | |
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') | |
429 | |
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) | |
434 | |
435 from_metro_sdk = [(r'Windows Kits\8.0', r'win8sdk')] | |
436 PullFrom(from_sdk, extracted.metro_sdk_path, target_dir) | |
437 | |
438 from_buildtools_x86 = [ | |
439 (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\x86', r'WDK\bin'), | |
440 ] | |
441 PullFrom(from_buildtools_x86, extracted.buildtools_x86, target_dir) | |
442 | |
443 from_buildtools_x64 = [ | |
444 (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\amd64', r'WDK\bin'), | |
445 ] | |
446 PullFrom(from_buildtools_x64, extracted.buildtools_x64, target_dir) | |
447 | |
448 from_libs_x86 = [ | |
449 (r'WinDDK\7600.16385.win7_wdk.100208-1538\lib', r'WDK\lib'), | |
450 ] | |
451 PullFrom(from_libs_x86, extracted.libs_x86, target_dir) | |
452 | |
453 from_libs_x64 = [ | |
454 (r'WinDDK\7600.16385.win7_wdk.100208-1538\lib', r'WDK\lib'), | |
455 ] | |
456 PullFrom(from_libs_x64, extracted.libs_x64, target_dir) | |
457 | |
458 from_headers = [ | |
459 (r'WinDDK\7600.16385.win7_wdk.100208-1538\inc', r'WDK\inc'), | |
460 ] | |
461 PullFrom(from_headers, extracted.headers, target_dir) | |
462 | |
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). | |
467 | |
468 from_sdk7_x86 = [ | |
469 (r'Program Files\Microsoft Visual Studio 10.0', '.'), | |
470 (r'Win\System', r'VC\bin'), | |
471 ] | |
472 PullFrom(from_sdk7_x86, extracted.vc_x86, target_dir) | |
473 | |
474 from_sdk7_x64 =[ | |
475 (r'Program Files(64)\Microsoft Visual Studio 10.0', '.'), | |
476 (r'Win\System64', r'VC\bin\amd64'), | |
477 ] | |
478 PullFrom(from_sdk7_x64, extracted.vc_x64, target_dir) | |
479 | |
480 from_vcupdate_x86 = [ | |
481 (r'Program Files\Microsoft Visual Studio 10.0', '.'), | |
482 (r'Win\System', r'VC\bin'), | |
483 ] | |
484 PullFrom(from_vcupdate_x86, extracted.update_x86, target_dir) | |
485 | |
486 from_vcupdate_x64 = [ | |
487 (r'Program Files(64)\Microsoft Visual Studio 10.0', '.'), | |
488 (r'Win\System64', r'VC\bin\amd64'), | |
489 ] | |
490 PullFrom(from_vcupdate_x64, extracted.update_x64, target_dir) | |
491 | |
492 sys.stdout.write('Stubbing ammintrin.h...\n') | |
493 open(os.path.join(target_dir, r'VC\include\ammintrin.h'), 'w').close() | |
494 | |
495 from_dxsdk = [ | |
496 (r'DXSDK\Include', r'DXSDK\Include'), | |
497 (r'DXSDK\Lib', r'DXSDK\Lib'), | |
498 (r'DXSDK\Redist', r'DXSDK\Redist'), | |
499 ] | |
500 PullFrom(from_dxsdk, extracted.dxsdk, target_dir) | |
501 | |
502 | |
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') | |
506 | |
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) | |
511 | |
512 from_metro_sdk = [(r'Windows Kits\8.0', r'win8sdk')] | |
513 PullFrom(from_sdk, extracted.metro_sdk_path, target_dir) | |
514 | |
515 # Stock compiler. | |
516 from_compiler = [(r'Program Files\Microsoft Visual Studio 11.0', '.')] | |
517 PullFrom(from_compiler, extracted.vc_x86, target_dir) | |
518 | |
519 from_compiler_res = [(r'Program Files\Microsoft Visual Studio 11.0', '.')] | |
520 PullFrom(from_compiler_res, extracted.vc_x86_res, target_dir) | |
521 | |
522 from_library = [(r'Program Files\Microsoft Visual Studio 11.0', '.')] | |
523 PullFrom(from_library, extracted.librarycore, target_dir) | |
524 | |
525 # WDK. | |
526 from_buildtools_x86 = [ | |
527 (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\x86', r'WDK\bin'), | |
528 ] | |
529 PullFrom(from_buildtools_x86, extracted.buildtools_x86, target_dir) | |
530 | |
531 from_buildtools_x64 = [ | |
532 (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\amd64', r'WDK\bin'), | |
533 ] | |
534 PullFrom(from_buildtools_x64, extracted.buildtools_x64, target_dir) | |
535 | |
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) | |
538 | |
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) | |
541 | |
542 from_headers = [(r'WinDDK\7600.16385.win7_wdk.100208-1538\inc', r'WDK\inc')] | |
543 PullFrom(from_headers, extracted.headers, target_dir) | |
544 | |
545 # Update bits. | |
546 from_compiler = [(r'Program Files\Microsoft Visual Studio 11.0', '.')] | |
547 PullFrom(from_compiler, extracted.vc_x86_update, target_dir) | |
548 | |
549 from_compiler_res = [(r'Program Files\Microsoft Visual Studio 11.0', '.')] | |
550 PullFrom(from_compiler_res, extracted.vc_x86_res_update, target_dir) | |
551 | |
552 from_library = [(r'Program Files\Microsoft Visual Studio 11.0', '.')] | |
553 PullFrom(from_library, extracted.librarycore_update, target_dir) | |
554 | |
555 | |
556 def PatchAsyncInfo(target_dir): | |
557 """Apply patch from | |
558 http://www.chromium.org/developers/how-tos/build-instructions-windows for | |
559 asyncinfo.h.""" | |
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: | |
569 f.write(patched) | |
570 | |
571 | |
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') | |
589 | |
590 # x86 only. | |
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') | |
599 | |
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': | |
603 # x64 only. | |
604 file.write(':x64\n') | |
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'))) | |
612 else: | |
613 # x64 only. | |
614 file.write(':x64\n') | |
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'))) | |
622 | |
623 file.write(':done\n') | |
624 | |
625 | |
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') | |
648 paths = [ | |
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', | |
653 ] | |
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) | |
658 | |
659 | |
660 def main(): | |
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', | |
669 default=True) | |
670 parser.add_option('--local', metavar='DIR', | |
671 help='use downloaded files from DIR') | |
672 options, args = parser.parse_args() | |
673 try: | |
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' % | |
678 target_dir) | |
679 return 1 | |
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) | |
689 else: | |
690 images = GetSourceImages2010(options.local) | |
691 extracted = ExtractComponents2010(images) | |
692 CopyToFinalLocation2010(extracted, target_dir) | |
693 PatchAsyncInfo(target_dir) | |
694 | |
695 GenerateSetEnvCmd(target_dir, options.vsversion) | |
696 GenerateTopLevelEnv(target_dir, options.vsversion) | |
697 finally: | |
698 if options.clean: | |
699 DeleteAllTempDirs() | |
700 | |
701 sys.stdout.write( | |
702 '\nIn a (clean) cmd shell, you can now run\n\n' | |
703 ' %s\\env.bat\n\n' | |
704 'then\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) | |
711 | |
712 | |
713 if __name__ == '__main__': | |
714 main() | |
OLD | NEW |