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 from optparse import OptionParser |
| 10 import os |
| 11 import shutil |
| 12 import subprocess |
| 13 import sys |
| 14 import tempfile |
| 15 import urllib2 |
| 16 |
| 17 |
| 18 g_temp_dirs = [] |
| 19 |
| 20 |
| 21 def RunOrDie(command): |
| 22 rc = subprocess.call(command, shell=True) |
| 23 if rc != 0: |
| 24 raise SystemExit('%s failed.' % command) |
| 25 |
| 26 |
| 27 def TempDir(): |
| 28 """Generate a temporary directory (for downloading or extracting to) and keep |
| 29 track of the directory that's created for cleaning up later.""" |
| 30 global g_temp_dirs |
| 31 temp = tempfile.mkdtemp() |
| 32 g_temp_dirs.append(temp) |
| 33 return temp |
| 34 |
| 35 |
| 36 def DeleteAllTempDirs(): |
| 37 """Remove all temporary directories created by |TempDir()|.""" |
| 38 global g_temp_dirs |
| 39 if g_temp_dirs: |
| 40 sys.stdout.write('Cleaning up temporaries...\n') |
| 41 for temp in g_temp_dirs: |
| 42 # shutil.rmtree errors out on read only attributes. |
| 43 RunOrDie('rmdir /s/q "%s"' % temp) |
| 44 g_temp_dirs = [] |
| 45 |
| 46 |
| 47 def Download(url, local_path): |
| 48 """Download a large-ish binary file and print some status information while |
| 49 doing so.""" |
| 50 sys.stdout.write('Downloading %s...' % url) |
| 51 req = urllib2.urlopen(url) |
| 52 content_length = int(req.headers.get('Content-Length', 0)) |
| 53 bytes_read = 0 |
| 54 with open(local_path, 'wb') as file: |
| 55 while True: |
| 56 chunk = req.read(1024 * 1024) |
| 57 if not chunk: |
| 58 break |
| 59 bytes_read += len(chunk) |
| 60 file.write(chunk) |
| 61 sys.stdout.write('.') |
| 62 sys.stdout.write('\n') |
| 63 if content_length and content_length != bytes_read: |
| 64 raise SystemExit('Got incorrect number of bytes downloading %s' % url) |
| 65 |
| 66 |
| 67 def DownloadSDK71Iso(): |
| 68 sdk7_temp_dir = TempDir() |
| 69 target_path = os.path.join(sdk7_temp_dir, 'GRMSDKX_EN_DVD.iso') |
| 70 Download( |
| 71 ('http://download.microsoft.com/download/' |
| 72 'F/1/0/F10113F5-B750-4969-A255-274341AC6BCE/GRMSDKX_EN_DVD.iso'), |
| 73 target_path) |
| 74 return target_path |
| 75 |
| 76 |
| 77 def DownloadWDKIso(): |
| 78 wdk_temp_dir = TempDir() |
| 79 target_path = os.path.join(wdk_temp_dir, 'GRMWDK_EN_7600_1.ISO') |
| 80 Download( |
| 81 ('http://download.microsoft.com/download/' |
| 82 '4/A/2/4A25C7D5-EFBE-4182-B6A9-AE6850409A78/GRMWDK_EN_7600_1.ISO'), |
| 83 target_path) |
| 84 return target_path |
| 85 |
| 86 |
| 87 def DownloadSDKUpdate(): |
| 88 sdk_update_temp_dir = TempDir() |
| 89 target_path = os.path.join(sdk_update_temp_dir, 'VC-Compiler-KB2519277.exe') |
| 90 Download( |
| 91 ('http://download.microsoft.com/download/' |
| 92 '7/5/0/75040801-126C-4591-BCE4-4CD1FD1499AA/VC-Compiler-KB2519277.exe'), |
| 93 target_path) |
| 94 return target_path |
| 95 |
| 96 |
| 97 def DownloadDirectXSDK(): |
| 98 dxsdk_temp_dir = TempDir() |
| 99 target_path = os.path.join(dxsdk_temp_dir, 'DXSDK_Jun10.exe') |
| 100 Download( |
| 101 ('http://download.microsoft.com/download/' |
| 102 'A/E/7/AE743F1F-632B-4809-87A9-AA1BB3458E31/DXSDK_Jun10.exe'), |
| 103 target_path) |
| 104 return target_path |
| 105 |
| 106 |
| 107 def DownloadSDK8(): |
| 108 """Download the Win8 SDK. This one is slightly different than the simple |
| 109 ones above. There is no .ISO distribution for the Windows 8 SDK. Rather, a |
| 110 tool is provided that is a download manager. This is used to download the |
| 111 various .msi files to a target location. Unfortunately, this tool requires |
| 112 elevation for no obvious reason even when only downloading, so this function |
| 113 will trigger a UAC elevation if the script is not run from an elevated |
| 114 prompt.""" |
| 115 sdk_temp_dir = TempDir() |
| 116 target_path = os.path.join(sdk_temp_dir, 'sdksetup.exe') |
| 117 standalone_path = os.path.join(sdk_temp_dir, 'Standalone') |
| 118 Download( |
| 119 ('http://download.microsoft.com/download/' |
| 120 'F/1/3/F1300C9C-A120-4341-90DF-8A52509B23AC/standalonesdk/sdksetup.exe'), |
| 121 target_path) |
| 122 sys.stdout.write( |
| 123 'Running sdksetup.exe to download Win8 SDK (may request elevation)...\n') |
| 124 count = 0 |
| 125 while count < 5: |
| 126 rc = RunOrDie(target_path + ' /quiet ' |
| 127 '/features OptionId.WindowsDesktopSoftwareDevelopmentKit ' |
| 128 '/layout ' + standalone_path) |
| 129 if rc == 0: |
| 130 return standalone_path |
| 131 break |
| 132 count += 1 |
| 133 sys.stdout.write('Windows 8 SDK failed to download, retrying.\n') |
| 134 raise SystemExit("After multiple retries, couldn't download Win8 SDK") |
| 135 |
| 136 |
| 137 class SourceImages(object): |
| 138 def __init__(self, sdk8_path, wdk_iso, sdk7_update, sdk7_path, dxsdk_path): |
| 139 self.sdk8_path = sdk8_path |
| 140 self.wdk_iso = wdk_iso |
| 141 self.sdk7_update = sdk7_update |
| 142 self.sdk7_path = sdk7_path |
| 143 self.dxsdk_path = dxsdk_path |
| 144 |
| 145 |
| 146 def GetSourceImages(): |
| 147 """Download all distribution archives for the components we need.""" |
| 148 if len(sys.argv) >= 2 and sys.argv[1] == 'local': |
| 149 return SourceImages( |
| 150 sdk8_path=r'C:\Users\Scott\Desktop\wee\Standalone', |
| 151 wdk_iso=r'c:\users\scott\desktop\wee\GRMWDK_EN_7600_1.ISO', |
| 152 sdk7_update=r'c:\users\scott\desktop\wee\VC-Compiler-KB2519277.exe', |
| 153 sdk7_path=r'C:\Users\Scott\Desktop\wee\GRMSDKX_EN_DVD.ISO', |
| 154 dxsdk_path=r'C:\Users\Scott\Desktop\wee\DXSDK_Jun10.exe') |
| 155 else: |
| 156 # Note that we do the Win8 SDK first so that its silly UAC prompt |
| 157 # happens before the user wanders off to get coffee. |
| 158 sdk8_path = DownloadSDK8() |
| 159 wdk_iso = DownloadWDKIso() |
| 160 sdk7_update = DownloadSDKUpdate() |
| 161 sdk7_path = DownloadSDK71Iso() |
| 162 dxsdk_path = DownloadDirectXSDK() |
| 163 return SourceImages(sdk8_path, wdk_iso, sdk7_update, sdk7_path, dxsdk_path) |
| 164 |
| 165 |
| 166 def ExtractIso(iso_path): |
| 167 """Use 7zip to extract the contents of the given .iso (or self-extracting |
| 168 .exe).""" |
| 169 target_path = TempDir() |
| 170 sys.stdout.write('Extracting %s...\n' % iso_path) |
| 171 # TODO(scottmg): Do this (and exe) manually with python code. |
| 172 # Note that at the beginning of main() we set the working directory to 7z's |
| 173 # location. |
| 174 RunOrDie('7z x "%s" -y "-o%s" >nul' % (iso_path, target_path)) |
| 175 return target_path |
| 176 |
| 177 |
| 178 ExtractExe = ExtractIso |
| 179 |
| 180 |
| 181 def ExtractMsi(msi_path): |
| 182 """Use msiexec to extract the contents of the given .msi file.""" |
| 183 sys.stdout.write('Extracting %s...\n' % msi_path) |
| 184 target_path = TempDir() |
| 185 RunOrDie('msiexec /a "%s" /qn TARGETDIR="%s"' % (msi_path, target_path)) |
| 186 return target_path |
| 187 |
| 188 |
| 189 class ExtractedComponents(object): |
| 190 def __init__(self, |
| 191 vc_x86, vc_x64, |
| 192 buildtools_x86, buildtools_x64, libs_x86, libs_x64, headers, |
| 193 update_x86, update_x64, |
| 194 sdk_path, metro_sdk_path, |
| 195 dxsdk): |
| 196 self.vc_x86 = vc_x86 |
| 197 self.vc_x64 = vc_x64 |
| 198 self.buildtools_x86 = buildtools_x86 |
| 199 self.buildtools_x64 = buildtools_x64 |
| 200 self.libs_x86 = libs_x86 |
| 201 self.libs_x64 = libs_x64 |
| 202 self.headers = headers |
| 203 self.update_x86 = update_x86 |
| 204 self.update_x64 = update_x64 |
| 205 self.sdk_path = sdk_path |
| 206 self.metro_sdk_path = metro_sdk_path |
| 207 self.dxsdk = dxsdk |
| 208 |
| 209 |
| 210 def ExtractComponents(images): |
| 211 """Given the paths to the images, extract the required parts, and return the |
| 212 an object containing paths to all the pieces.""" |
| 213 extracted_sdk7 = ExtractIso(images.sdk7_path) |
| 214 extracted_vc_x86 = \ |
| 215 ExtractMsi(os.path.join(extracted_sdk7, |
| 216 r'Setup\vc_stdx86\vc_stdx86.msi')) |
| 217 extracted_vc_x64 = \ |
| 218 ExtractMsi(os.path.join(extracted_sdk7, |
| 219 r'Setup\vc_stdamd64\vc_stdamd64.msi')) |
| 220 |
| 221 extracted_wdk = ExtractIso(images.wdk_iso) |
| 222 extracted_buildtools_x86 = \ |
| 223 ExtractMsi(os.path.join(extracted_wdk, r'WDK\buildtools_x86fre.msi')) |
| 224 extracted_buildtools_x64 = \ |
| 225 ExtractMsi(os.path.join(extracted_wdk, r'WDK\buildtools_x64fre.msi')) |
| 226 extracted_libs_x86 = \ |
| 227 ExtractMsi(os.path.join(extracted_wdk, r'WDK\libs_x86fre.msi')) |
| 228 extracted_libs_x64 = \ |
| 229 ExtractMsi(os.path.join(extracted_wdk, r'WDK\libs_x64fre.msi')) |
| 230 extracted_headers = \ |
| 231 ExtractMsi(os.path.join(extracted_wdk, r'WDK\headers.msi')) |
| 232 |
| 233 extracted_update = ExtractExe(images.sdk7_update) |
| 234 extracted_update_x86 = \ |
| 235 ExtractMsi(os.path.join(extracted_update, 'vc_stdx86.msi')) |
| 236 extracted_update_x64 = \ |
| 237 ExtractMsi(os.path.join(extracted_update, 'vc_stdamd64.msi')) |
| 238 |
| 239 sdk_msi_path = os.path.join( |
| 240 images.sdk8_path, |
| 241 r'Installers\Windows Software Development Kit-x86_en-us.msi') |
| 242 extracted_sdk_path = ExtractMsi(sdk_msi_path) |
| 243 |
| 244 sdk_metro_msi_path = os.path.join( |
| 245 images.sdk8_path, |
| 246 'Installers', |
| 247 'Windows Software Development Kit for Metro style Apps-x86_en-us.msi') |
| 248 extracted_metro_sdk_path = ExtractMsi(sdk_metro_msi_path) |
| 249 |
| 250 extracted_dxsdk = ExtractExe(images.dxsdk_path) |
| 251 |
| 252 return ExtractedComponents( |
| 253 vc_x86=extracted_vc_x86, |
| 254 vc_x64=extracted_vc_x64, |
| 255 buildtools_x86=extracted_buildtools_x86, |
| 256 buildtools_x64=extracted_buildtools_x64, |
| 257 libs_x86=extracted_libs_x86, |
| 258 libs_x64=extracted_libs_x64, |
| 259 headers=extracted_headers, |
| 260 update_x86=extracted_update_x86, |
| 261 update_x64=extracted_update_x64, |
| 262 sdk_path=extracted_sdk_path, |
| 263 metro_sdk_path=extracted_metro_sdk_path, |
| 264 dxsdk=extracted_dxsdk) |
| 265 |
| 266 |
| 267 def PullFrom(list_of_path_pairs, source_root, target_dir): |
| 268 """Each pair in |list_of_path_pairs| is (from, to). Join the 'from' with |
| 269 |source_root| and the 'to' with |target_dir| and perform a recursive copy.""" |
| 270 for source, destination in list_of_path_pairs: |
| 271 full_source = os.path.join(source_root, source) |
| 272 full_target = os.path.join(target_dir, destination) |
| 273 rc = os.system('robocopy /s "%s" "%s" >nul' % (full_source, full_target)) |
| 274 if (rc & 8) != 0 or (rc & 16) != 0: |
| 275 # ref: http://ss64.com/nt/robocopy-exit.html |
| 276 raise SystemExit("Couldn't copy %s to %s" % (full_source, full_target)) |
| 277 |
| 278 |
| 279 def CopyToFinalLocation(extracted, target_dir): |
| 280 """Copy all the directories we need to the target location.""" |
| 281 sys.stdout.write('Pulling together required pieces...\n') |
| 282 |
| 283 # Note that order is important because some of the older ones are |
| 284 # overwritten by updates. |
| 285 from_sdk = [(r'Windows Kits\8.0', r'win8sdk')] |
| 286 PullFrom(from_sdk, extracted.sdk_path, target_dir) |
| 287 |
| 288 from_metro_sdk = [(r'Windows Kits\8.0', r'win8sdk')] |
| 289 PullFrom(from_sdk, extracted.metro_sdk_path, target_dir) |
| 290 |
| 291 from_buildtools_x86 = [ |
| 292 (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\x86', r'WDK\bin'), |
| 293 (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\amd64', r'WDK\bin'), |
| 294 ] |
| 295 PullFrom(from_buildtools_x86, extracted.buildtools_x86, target_dir) |
| 296 |
| 297 from_buildtools_x64 = [ |
| 298 (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\amd64', r'WDK\bin'), |
| 299 ] |
| 300 PullFrom(from_buildtools_x64, extracted.buildtools_x64, target_dir) |
| 301 |
| 302 from_libs_x86 = [ |
| 303 (r'WinDDK\7600.16385.win7_wdk.100208-1538\lib', r'WDK\lib'), |
| 304 ] |
| 305 PullFrom(from_libs_x86, extracted.libs_x86, target_dir) |
| 306 |
| 307 from_libs_x64 = [ |
| 308 (r'WinDDK\7600.16385.win7_wdk.100208-1538\lib', r'WDK\lib'), |
| 309 ] |
| 310 PullFrom(from_libs_x64, extracted.libs_x64, target_dir) |
| 311 |
| 312 from_headers = [ |
| 313 (r'WinDDK\7600.16385.win7_wdk.100208-1538\inc', r'WDK\inc'), |
| 314 ] |
| 315 PullFrom(from_headers, extracted.headers, target_dir) |
| 316 |
| 317 # The compiler update to get the SP1 x86 compiler is a bit of a mess. See |
| 318 # http://goo.gl/n1DeO. The summary is that update for the standalone |
| 319 # compiler binary installs a broken set of headers. So, we need to pull the |
| 320 # new binaries from the update, but keep the older set of headers. |
| 321 |
| 322 from_vcupdate_x86 = [ |
| 323 (r'Program Files\Microsoft Visual Studio 10.0', '.'), |
| 324 (r'Win\System', r'VC\bin'), |
| 325 ] |
| 326 PullFrom(from_vcupdate_x86, extracted.update_x86, target_dir) |
| 327 |
| 328 from_vcupdate_x64 = [ |
| 329 (r'Program Files(64)\Microsoft Visual Studio 10.0', '.'), |
| 330 (r'Win\System64', r'VC\bin\amd64'), |
| 331 ] |
| 332 PullFrom(from_vcupdate_x64, extracted.update_x64, target_dir) |
| 333 |
| 334 from_sdk7_x86 = [ |
| 335 (r'Program Files\Microsoft Visual Studio 10.0', '.'), |
| 336 (r'Win\System', r'VC\bin'), |
| 337 ] |
| 338 PullFrom(from_sdk7_x86, extracted.vc_x86, target_dir) |
| 339 |
| 340 from_sdk7_x64 =[ |
| 341 (r'Program Files(64)\Microsoft Visual Studio 10.0', '.'), |
| 342 (r'Win\System64', r'VC\bin\amd64'), |
| 343 ] |
| 344 PullFrom(from_sdk7_x64, extracted.vc_x64, target_dir) |
| 345 |
| 346 # Now, re-get just the binaries from the update. |
| 347 from_vcupdate_x86 = [ |
| 348 (r'Program Files\Microsoft Visual Studio 10.0\VC\bin', r'VC\bin'), |
| 349 ] |
| 350 PullFrom(from_vcupdate_x86, extracted.update_x86, target_dir) |
| 351 |
| 352 from_vcupdate_x64 = [ |
| 353 (r'Program Files(64)\Microsoft Visual Studio 10.0\VC\bin', r'VC\bin'), |
| 354 ] |
| 355 PullFrom(from_vcupdate_x64, extracted.update_x64, 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 |
| 365 def PatchAsyncInfo(target_dir): |
| 366 """Apply patch from |
| 367 http://www.chromium.org/developers/how-tos/build-instructions-windows for |
| 368 asyncinfo.h.""" |
| 369 sys.stdout.write('Patching asyncinfo.h...\n') |
| 370 asyncinfo_h_path = os.path.join( |
| 371 target_dir, r'win8sdk\Include\winrt\asyncinfo.h') |
| 372 with open(asyncinfo_h_path, 'rb') as f: |
| 373 asyncinfo_h = f.read() |
| 374 patched = asyncinfo_h.replace( |
| 375 'enum class AsyncStatus {', 'enum AsyncStatus {') |
| 376 with open(asyncinfo_h_path, 'wb') as f: |
| 377 f.write(patched) |
| 378 |
| 379 |
| 380 def GenerateSetEnvCmd(target_dir): |
| 381 """Generate a batch file that gyp expects to exist to set up the compiler |
| 382 environment. This is normally generated by a full install of the SDK, but we |
| 383 do it here manually since we do not do a full install.""" |
| 384 with open(os.path.join( |
| 385 target_dir, r'win8sdk\bin\SetEnv.cmd'), 'w') as file: |
| 386 file.write('@echo off\n') |
| 387 file.write(':: Generated by tools\\win\\toolchain\\toolchain.py.\n') |
| 388 # Common to x86 and x64 |
| 389 file.write('set PATH=%s;%%PATH%%\n' % ( |
| 390 os.path.join(target_dir, r'Common7\IDE'))) |
| 391 file.write('set INCLUDE=%s;%s;%s\n' % ( |
| 392 os.path.join(target_dir, r'win8sdk\Include\um'), |
| 393 os.path.join(target_dir, r'win8sdk\Include\shared'), |
| 394 os.path.join(target_dir, r'VC\include'))) |
| 395 file.write('if "%1"=="/x64" goto x64\n') |
| 396 |
| 397 # x86 only. |
| 398 file.write('set PATH=%s;%s;%s;%%PATH%%\n' % ( |
| 399 os.path.join(target_dir, r'win8sdk\bin\x86'), |
| 400 os.path.join(target_dir, r'VC\bin'), |
| 401 os.path.join(target_dir, r'WDK\bin'))) |
| 402 file.write('set LIB=%s;%s\n' % ( |
| 403 os.path.join(target_dir, r'VC\lib'), |
| 404 os.path.join(target_dir, r'win8sdk\Lib\win8\um\x86'))) |
| 405 file.write('goto done\n') |
| 406 |
| 407 # x64 only. |
| 408 file.write(':x64\n') |
| 409 file.write('set PATH=%s;%s;%s;%%PATH%%\n' % ( |
| 410 os.path.join(target_dir, r'win8sdk\bin\x64'), |
| 411 os.path.join(target_dir, r'VC\bin\amd64'), |
| 412 os.path.join(target_dir, r'WDK\bin\amd64'))) |
| 413 file.write('set LIB=%s;%s\n' % ( |
| 414 os.path.join(target_dir, r'VC\lib\amd64'), |
| 415 os.path.join(target_dir, r'win8sdk\Lib\win8\um\x64'))) |
| 416 |
| 417 file.write(':done\n') |
| 418 |
| 419 |
| 420 def GenerateTopLevelEnv(target_dir): |
| 421 """Generate a batch file that sets up various environment variables that let |
| 422 the Chromium build files and gyp find SDKs and tools.""" |
| 423 with open(os.path.join(target_dir, r'env.bat'), 'w') as file: |
| 424 file.write('@echo off\n') |
| 425 file.write(':: Generated by tools\\win\\toolchain\\toolchain.py.\n') |
| 426 file.write('set GYP_DEFINES=windows_sdk_path="%s" ' |
| 427 'component=shared_library\n' % ( |
| 428 os.path.join(target_dir, 'win8sdk'))) |
| 429 file.write('set GYP_MSVS_VERSION=2010e\n') |
| 430 file.write('set GYP_MSVS_OVERRIDE_PATH=%s\n' % target_dir) |
| 431 file.write('set GYP_GENERATORS=ninja\n') |
| 432 file.write('set WDK_DIR=%s\n' % os.path.join(target_dir, r'WDK')) |
| 433 file.write('set DXSDK_DIR=%s\n' % os.path.join(target_dir, r'DXSDK')) |
| 434 file.write('set WindowsSDKDir=%s\n' % |
| 435 os.path.join(target_dir, r'win8sdk')) |
| 436 file.write('echo Environment set for toolchain in %s.\n' % target_dir) |
| 437 file.write('cd /d %s\\..\n' % target_dir) |
| 438 |
| 439 |
| 440 def main(): |
| 441 try: |
| 442 parser = OptionParser() |
| 443 parser.add_option('--targetdir', metavar='DIR', |
| 444 help='put toolchain into DIR', |
| 445 default=os.path.abspath('win_toolchain')) |
| 446 options, args = parser.parse_args() |
| 447 target_dir = os.path.abspath(options.targetdir) |
| 448 # Set the working directory to 7z subdirectory. 7-zip doesn't find its |
| 449 # codec dll very well, so this is the simplest way to make sure it runs |
| 450 # correctly, as we don't otherwise care about working directory. |
| 451 os.chdir(os.path.join(os.path.dirname(os.path.abspath(__file__)), '7z')) |
| 452 images = GetSourceImages() |
| 453 extracted = ExtractComponents(images) |
| 454 CopyToFinalLocation(extracted, target_dir) |
| 455 PatchAsyncInfo(target_dir) |
| 456 GenerateSetEnvCmd(target_dir) |
| 457 GenerateTopLevelEnv(target_dir) |
| 458 finally: |
| 459 DeleteAllTempDirs() |
| 460 |
| 461 sys.stdout.write( |
| 462 '\nIn a (clean) cmd shell, you can now run\n\n' |
| 463 ' %s\\env.bat\n\n' |
| 464 'then\n\n' |
| 465 " gclient runhooks (or gclient sync if you haven't pulled deps yet)\n" |
| 466 ' ninja -C out\Debug chrome\n\n' |
| 467 'Note that this script intentionally does not modify any global\n' |
| 468 'settings like the registry, or system environment variables, so you\n' |
| 469 'will need to run the above env.bat whenever you start a new\n' |
| 470 'shell.\n\n' % target_dir) |
| 471 |
| 472 |
| 473 if __name__ == '__main__': |
| 474 main() |
OLD | NEW |