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

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