Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(798)

Side by Side Diff: tools/win/toolchain/toolchain.py

Issue 11633012: tools addition to automate setting up windows toolchain (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: some review fixes Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/win/toolchain/7z.exe ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 os
10 import shutil
11 import sys
12 import tempfile
13 import urllib2
14
15
16 g_temp_dirs = []
17
18
19 def TempDir():
20 """Generate a temporary directory (for downloading or extracting to) and keep
21 track of the directory that's created for cleaning up later."""
22 global g_temp_dirs
23 temp = tempfile.mkdtemp()
24 g_temp_dirs.append(temp)
25 return temp
26
27
28 def DeleteAllTempDirs():
29 """Remove all temporary directories created by |TempDir()|."""
30 global g_temp_dirs
31 sys.stdout.write('Cleaning up temporaries...\n')
32 for temp in g_temp_dirs:
33 # shutil.rmtree errors out on read only attributes.
34 os.system('rmdir /s/q "%s"' % temp)
35 g_temp_dirs = []
36
37
38 def Download(url, local_path):
39 """Download a large-ish binary file and print some status information while
40 doing so."""
41 sys.stdout.write('Downloading %s...' % url)
42 req = urllib2.urlopen(url)
43 content_length = int(req.headers.get('Content-Length', 0))
44 bytes_read = 0
45 with open(local_path, 'wb') as file:
46 while True:
47 chunk = req.read(1024 * 1024)
48 if not chunk:
49 break
50 bytes_read = len(chunk)
51 file.write(chunk)
52 sys.stdout.write('.')
53 sys.stdout.write('\n')
54 if content_length and content_length != bytes_read:
55 raise SystemExit('Got incorrect number of bytes downloading %s' % url)
56
57
58 def DownloadSDK71Iso():
59 sdk7_temp_dir = TempDir()
60 target_path = os.path.join(sdk7_temp_dir, 'GRMSDKX_EN_DVD.iso')
61 Download(
62 ('http://download.microsoft.com/download/'
63 'F/1/0/F10113F5-B750-4969-A255-274341AC6BCE/GRMSDKX_EN_DVD.iso'),
64 target_path)
65 return target_path
66
67
68 def DownloadWDKIso():
69 wdk_temp_dir = TempDir()
70 target_path = os.path.join(wdk_temp_dir, 'GRMWDK_EN_7600_1.ISO')
71 Download(
72 ('http://download.microsoft.com/download/'
73 '4/A/2/4A25C7D5-EFBE-4182-B6A9-AE6850409A78/GRMWDK_EN_7600_1.ISO'),
74 target_path)
75 return target_path
76
77
78 def DownloadWDKUpdate():
alexeypa (please no reviews) 2013/01/02 19:33:57 nit: This is not WDK update. This is SDK 7.1 updat
scottmg 2013/01/02 21:00:48 Oops, thanks. Done.
79 wdk_update_temp_dir = TempDir()
80 target_path = os.path.join(wdk_update_temp_dir, 'VC-Compiler-KB2519277.exe')
81 Download(
82 ('http://download.microsoft.com/download/'
83 '7/5/0/75040801-126C-4591-BCE4-4CD1FD1499AA/VC-Compiler-KB2519277.exe'),
84 target_path)
85 return target_path
86
87
88 def DownloadDirectXSDK():
89 dxsdk_temp_dir = TempDir()
90 target_path = os.path.join(dxsdk_temp_dir, 'DXSDK_Jun10.exe')
91 Download(
92 ('http://download.microsoft.com/download/'
93 'A/E/7/AE743F1F-632B-4809-87A9-AA1BB3458E31/DXSDK_Jun10.exe'),
94 target_path)
95 return target_path
96
97
98 def DownloadSDK8():
99 """Download the Win8 SDK. This one is slightly different than the simple
100 ones above. There is no .ISO distribution for the Windows 8 SDK. Rather, a
101 tool is provided that is a download manager. This is used to download the
102 various .msi files to a target location. Unfortunately, this tool requires
103 elevation for no obvious reason even when only downloading, so this function
104 will trigger a UAC elevation if the script is not run from an elevated
105 prompt."""
106 sdk_temp_dir = TempDir()
107 target_path = os.path.join(sdk_temp_dir, 'sdksetup.exe')
108 standalone_path = os.path.join(sdk_temp_dir, 'Standalone')
109 Download(
110 ('http://download.microsoft.com/download/'
111 'F/1/3/F1300C9C-A120-4341-90DF-8A52509B23AC/standalonesdk/sdksetup.exe'),
112 target_path)
113 count = 0
114 while count < 5:
115 rc = os.system(target_path + ' /quiet '
116 '/features OptionId.WindowsDesktopSoftwareDevelopmentKit '
117 '/layout ' + standalone_path)
118 if rc == 0:
119 return standalone_path
120 break
121 count += 1
122 sys.stdout.write('Windows 8 SDK failed to download, retrying.\n')
123 raise SystemExit("After multiple retries, couldn't download Win8 SDK")
124
125
126 def ExtractIso(iso_path):
127 """Use 7zip to extract the contents of the given .iso (or self-extracting
128 .exe)."""
129 target_path = TempDir()
130 sys.stdout.write('Extracting %s...\n' % iso_path)
131 # TODO(scottmg): Do this (and exe) manually with python code.
132 if os.system('7z x "%s" -y "-o%s" > nul' % (iso_path, target_path)) != 0:
133 raise SystemExit("Couldn't extract %s" % iso_path)
134 return target_path
135
136
137 ExtractExe = ExtractIso
138
139
140 def ExtractMsi(msi_path):
141 """Use msiexec to extract the contents of the given .msi file."""
142 sys.stdout.write('Extracting %s...\n' % msi_path)
143 target_path = TempDir()
144 if os.system(
145 'msiexec /a "%s" /qn TARGETDIR=%s' % (msi_path, target_path)) != 0:
146 raise SystemExit("Couldn't extract %s" % msi_path)
147 os.unlink(os.path.join(target_path, os.path.basename(msi_path)))
alexeypa (please no reviews) 2013/01/02 19:33:57 Is this needed? The script deletes all temporary f
scottmg 2013/01/02 21:00:48 Done.
148 return target_path
149
150
151 def PullFrom(list_of_path_pairs, source_root, target_dir):
152 """Each pair in |list_of_path_pairs| is (from, to). Join the 'from' with
153 |source_root| and the 'to' with |target_dir| and perform a recursive copy."""
154 for source, destination in list_of_path_pairs:
155 full_source = os.path.join(source_root, source)
156 full_target = os.path.join(target_dir, destination)
157 rc = os.system('robocopy /s "%s" "%s" >nul' % (full_source, full_target))
158 if (rc & 8) != 0 or (rc & 16) != 0:
159 # ref: http://ss64.com/nt/robocopy-exit.html
160 raise SystemExit("Couldn't copy %s to %s" % (full_source, full_target))
161
162
163 def PatchAsyncInfo(target_dir):
164 """Apply patch from
165 http://www.chromium.org/developers/how-tos/build-instructions-windows for
166 asyncinfo.h."""
167 sys.stdout.write('Patching asyncinfo.h...\n')
168 asyncinfo_h_path = os.path.join(
169 target_dir, r'win8sdk\Include\winrt\asyncinfo.h')
170 with open(asyncinfo_h_path, 'rb') as f:
171 asyncinfo_h = f.read()
172 patched = asyncinfo_h.replace(
173 'enum class AsyncStatus {', 'enum AsyncStatus {')
174 with open(asyncinfo_h_path, 'wb') as f:
175 f.write(patched)
176
177
178
179 def GenerateSetEnvCmd(target_dir):
180 """Generate a batch file that gyp expects to exist to set up the compiler
181 environment. This is normally generated by a full install of the SDK, but we
182 do it here manually since we do not do a full install."""
183 with open(os.path.join(
184 target_dir, r'win8sdk\bin\SetEnv.cmd'), 'w') as file:
185 file.write('@echo off\n')
186 file.write(':: Generated by tools\\win\\toolchain\\toolchain.py.\n')
187 # Common to x86 and x64
188 file.write('set PATH=%s;%%PATH%%\n' % (
189 os.path.join(target_dir, r'Common7\IDE')))
190 file.write('set INCLUDE=%s;%s;%s\n' % (
191 os.path.join(target_dir, r'win8sdk\Include\um'),
192 os.path.join(target_dir, r'win8sdk\Include\shared'),
193 os.path.join(target_dir, r'VC\include')))
194 file.write('if "%1"=="/x64" goto x64\n')
195
196 # x86 only.
197 file.write('set PATH=%s;%s;%s;%%PATH%%\n' % (
198 os.path.join(target_dir, r'win8sdk\bin\x86'),
199 os.path.join(target_dir, r'VC\bin'),
200 os.path.join(target_dir, r'WDK\bin')))
201 file.write('set LIB=%s;%s\n' % (
202 os.path.join(target_dir, r'VC\lib'),
203 os.path.join(target_dir, r'win8sdk\Lib\win8\um\x86')))
204 file.write('goto done\n')
205
206 # x64 only.
207 file.write(':x64\n')
208 file.write('set PATH=%s;%s;%s;%%PATH%%\n' % (
209 os.path.join(target_dir, r'win8sdk\bin\x64'),
210 os.path.join(target_dir, r'VC\bin\amd64'),
211 os.path.join(target_dir, r'WDK\bin\amd64')))
212 file.write('set LIB=%s;%s\n' % (
213 os.path.join(target_dir, r'VC\lib\amd64'),
214 os.path.join(target_dir, r'win8sdk\Lib\win8\um\x64')))
215
216 file.write(':done\n')
217
218
219 def GenerateTopLevelEnv(target_dir):
220 """Generate a batch file that sets up various environment variables that let
221 the Chromium build files and gyp find SDKs and tools."""
222 with open(os.path.join(target_dir, r'env.bat'), 'w') as file:
223 file.write('@echo off\n')
224 file.write(':: Generated by tools\\win\\toolchain\\toolchain.py.\n')
225 file.write('set GYP_DEFINES=windows_sdk_path="%s" '
226 'component=shared_library\n' % (
227 os.path.join(target_dir, 'win8sdk')))
228 file.write('set GYP_MSVS_VERSION=2010e\n')
229 file.write('set GYP_MSVS_OVERRIDE_PATH=%s\n' % target_dir)
230 file.write('set GYP_GENERATORS=ninja\n')
231 file.write('set WDK_DIR=%s\n' % os.path.join(target_dir, r'WDK'))
232 file.write('set DXSDK_DIR=%s\n' % os.path.join(target_dir, r'DXSDK'))
233 file.write('set WindowsSDKDir=%s\n' %
234 os.path.join(target_dir, r'win8sdk'))
235 file.write('echo Environment set for toolchain in %s.\n' % target_dir)
236 file.write('cd /d %s\\..\n' % target_dir)
237
238
239 def main():
240 try:
241 target_dir = os.path.abspath('win_toolchain')
242 os.chdir(os.path.dirname(os.path.abspath(__file__)))
243
244 if len(sys.argv) == 2 and sys.argv[1] == 'local':
245 sdk_path = r'C:\Users\Scott\Desktop\wee\Standalone'
246 wdk_iso = r'c:\users\scott\desktop\wee\GRMWDK_EN_7600_1.ISO'
247 wdk_update = r'c:\users\scott\desktop\wee\VC-Compiler-KB2519277.exe'
248 sdk7_path = r'C:\Users\Scott\Desktop\wee\GRMSDKX_EN_DVD.ISO'
249 dxsdk_path = r'C:\Users\Scott\Desktop\wee\DXSDK_Jun10.exe'
250 else:
251 # Note that we do the Win8 SDK first so that its silly UAC prompt
252 # happens before the user wanders off to get coffee.
253 sdk_path = DownloadSDK8()
254 wdk_iso = DownloadWDKIso()
255 wdk_update = DownloadWDKUpdate()
256 sdk7_path = DownloadSDK71Iso()
257 dxsdk_path = DownloadDirectXSDK()
258
259 extracted_sdk7 = ExtractIso(sdk7_path)
260 extracted_vc_x86 = \
261 ExtractMsi(os.path.join(extracted_sdk7,
262 r'Setup\vc_stdx86\vc_stdx86.msi'))
263 extracted_vc_x64 = \
264 ExtractMsi(os.path.join(extracted_sdk7,
265 r'Setup\\vc_stdamd64\vc_stdamd64.msi'))
266
267 extracted_wdk = ExtractIso(wdk_iso)
268 extracted_buildtools_x86 = \
269 ExtractMsi(os.path.join(extracted_wdk, 'WDK\\buildtools_x86fre.msi'))
270 extracted_buildtools_x64 = \
271 ExtractMsi(os.path.join(extracted_wdk, 'WDK\\buildtools_x64fre.msi'))
272 extracted_libs_x86 = \
273 ExtractMsi(os.path.join(extracted_wdk, 'WDK\\libs_x86fre.msi'))
274 extracted_libs_x64 = \
275 ExtractMsi(os.path.join(extracted_wdk, 'WDK\\libs_x64fre.msi'))
276 extracted_headers = \
277 ExtractMsi(os.path.join(extracted_wdk, 'WDK\\headers.msi'))
278
279 extracted_update = ExtractExe(wdk_update)
280 extracted_update_x86 = \
281 ExtractMsi(os.path.join(extracted_update, 'vc_stdx86.msi'))
282 extracted_update_x64 = \
283 ExtractMsi(os.path.join(extracted_update, 'vc_stdamd64.msi'))
284
285 sdk_msi_path = os.path.join(
286 sdk_path, 'Installers\\Windows Software Development Kit-x86_en-us.msi')
287 extracted_sdk_path = ExtractMsi(sdk_msi_path)
288
289 sdk_metro_msi_path = os.path.join(
290 sdk_path,
291 'Installers',
292 'Windows Software Development Kit for Metro style Apps-x86_en-us.msi')
293 extracted_metro_sdk_path = ExtractMsi(sdk_metro_msi_path)
294
295 extracted_dxsdk = ExtractExe(dxsdk_path)
296
297 sys.stdout.write('Pulling together required pieces...\n')
298
299 # Note that order is important because some of the older ones are
300 # overwritten by updates.
301 from_vcupdate_x86 = [
302 (r'Program Files\Microsoft Visual Studio 10.0', '.'),
303 (r'Win\System', r'VC\bin'),
304 ]
305 PullFrom(from_vcupdate_x86, extracted_update_x86, target_dir)
306
307 from_vcupdate_x64 = [
308 (r'Program Files(64)\Microsoft Visual Studio 10.0', '.'),
309 (r'Win\System64', r'VC\bin\amd64'),
310 ]
311 PullFrom(from_vcupdate_x64, extracted_update_x64, target_dir)
alexeypa (please no reviews) 2013/01/02 19:33:57 nit: One small concern I have is that PullFrom() d
scottmg 2013/01/02 21:00:48 It took me a while to figure out what was going on
312
313 from_sdk7_x86 =[
314 (r'Program Files\Microsoft Visual Studio 10.0', '.'),
315 (r'Win\System', r'VC\bin'),
316 ]
317 PullFrom(from_sdk7_x86, extracted_vc_x86, target_dir)
318
319 from_sdk7_x64 =[
320 (r'Program Files(64)\Microsoft Visual Studio 10.0', '.'),
321 (r'Win\System64', r'VC\bin\amd64'),
322 ]
323 PullFrom(from_sdk7_x64, extracted_vc_x64, target_dir)
324
325 from_sdk = [(r'Windows Kits\8.0', r'win8sdk')]
326 PullFrom(from_sdk, extracted_sdk_path, target_dir)
327
328 from_metro_sdk = [(r'Windows Kits\8.0', r'win8sdk')]
329 PullFrom(from_sdk, extracted_metro_sdk_path, target_dir)
330
331 from_buildtools_x86 = [
332 (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\x86', r'WDK\bin'),
333 (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\amd64', r'WDK\bin'),
334 ]
335 PullFrom(from_buildtools_x86, extracted_buildtools_x86, target_dir)
336
337 from_buildtools_x64 = [
338 (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\amd64', r'WDK\bin'),
339 ]
340 PullFrom(from_buildtools_x64, extracted_buildtools_x64, target_dir)
341
342 from_libs_x86 = [
343 (r'WinDDK\7600.16385.win7_wdk.100208-1538\lib', r'WDK\lib'),
344 ]
345 PullFrom(from_libs_x86, extracted_libs_x86, target_dir)
346
347 from_libs_x64 = [
348 (r'WinDDK\7600.16385.win7_wdk.100208-1538\lib', r'WDK\lib'),
349 ]
350 PullFrom(from_libs_x64, extracted_libs_x64, target_dir)
351
352 from_headers = [
353 (r'WinDDK\7600.16385.win7_wdk.100208-1538\inc', r'WDK\inc'),
354 ]
355 PullFrom(from_headers, extracted_headers, target_dir)
356
357 from_dxsdk = [
358 (r'DXSDK\Include', r'DXSDK\Include'),
359 (r'DXSDK\Lib', r'DXSDK\Lib'),
360 (r'DXSDK\Redist', r'DXSDK\Redist'),
361 ]
362 PullFrom(from_dxsdk, extracted_dxsdk, target_dir)
363
364 PatchAsyncInfo()
365
366 GenerateSetEnvCmd(target_dir)
367 GenerateTopLevelEnv(target_dir)
368 finally:
369 DeleteAllTempDirs()
370
371 sys.stdout.write(
372 '\nIn a (clean) cmd shell, you can now run\n\n'
373 ' %s\\env.bat\n\n'
374 'then\n\n'
375 " gclient runhooks (or gclient sync if you haven't pulled deps yet)\n"
376 ' ninja -C out\Debug chrome\n\n'
377 'Note that this script intentionally does not modify any global\n'
378 'settings like the registry, or system environment variables, so you\n'
379 'will need to run the above env.bat whenever you start a new\n'
380 'shell.\n\n' % target_dir)
381
382
383 if __name__ == '__main__':
384 main()
OLDNEW
« no previous file with comments | « tools/win/toolchain/7z.exe ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698