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

Side by Side Diff: lib/naclports/source_package.py

Issue 839083003: Add initial support for color output in the build system (Closed) Base URL: https://chromium.googlesource.com/external/naclports.git@master
Patch Set: Created 5 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
« no previous file with comments | « lib/naclports/package.py ('k') | lib/naclports/util.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2014 The Native Client Authors. All rights reserved. 1 # Copyright (c) 2014 The Native Client Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import contextlib 5 import contextlib
6 import os 6 import os
7 import re 7 import re
8 import shutil 8 import shutil
9 import subprocess 9 import subprocess
10 import sys 10 import sys
(...skipping 16 matching lines...) Expand all
27 27
28 28
29 @contextlib.contextmanager 29 @contextlib.contextmanager
30 def RedirectStdoutStderr(filename): 30 def RedirectStdoutStderr(filename):
31 """Context manager that replaces stdout and stderr streams.""" 31 """Context manager that replaces stdout and stderr streams."""
32 if filename is None: 32 if filename is None:
33 yield 33 yield
34 return 34 return
35 35
36 with open(filename, 'a') as stream: 36 with open(filename, 'a') as stream:
37 old_stdout = sys.stdout
38 old_stderr = sys.stderr
37 sys.stdout = stream 39 sys.stdout = stream
38 sys.stderr = stream 40 sys.stderr = stream
41 util.CheckStdoutForColorSupport()
39 try: 42 try:
40 yield 43 yield
41 finally: 44 finally:
42 sys.stdout = sys.__stdout__ 45 sys.stdout = old_stdout
43 sys.stderr = sys.__stdout__ 46 sys.stderr = old_stderr
47 util.CheckStdoutForColorSupport()
44 48
45 49
46 def FormatTimeDelta(delta): 50 def FormatTimeDelta(delta):
47 """Converts a duration in seconds to a human readable string. 51 """Converts a duration in seconds to a human readable string.
48 52
49 Args: 53 Args:
50 delta: the amount of time in seconds. 54 delta: the amount of time in seconds.
51 55
52 Returns: A string desribing the ammount of time passed in. 56 Returns: A string desribing the ammount of time passed in.
53 """ 57 """
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 except PkgFormatError: 230 except PkgFormatError:
227 # If the package is malformed in some way or in some old format 231 # If the package is malformed in some way or in some old format
228 # then treat it as not built. 232 # then treat it as not built.
229 return False 233 return False
230 return pkg.IsInstallable() 234 return pkg.IsInstallable()
231 235
232 def Install(self, build_deps, force=None, from_source=False): 236 def Install(self, build_deps, force=None, from_source=False):
233 self.CheckInstallable() 237 self.CheckInstallable()
234 238
235 if force is None and self.IsInstalled(): 239 if force is None and self.IsInstalled():
236 Log('Already installed %s' % self.InfoString()) 240 self.LogStatus('Already installed')
237 return 241 return
238 242
239 if build_deps: 243 if build_deps:
240 self.InstallDeps(force, from_source) 244 self.InstallDeps(force, from_source)
241 245
242 if force: 246 if force:
243 from_source = True 247 from_source = True
244 248
245 package_file = self.PackageFile() 249 package_file = self.PackageFile()
246 if not self.IsBuilt() and not from_source: 250 if not self.IsBuilt() and not from_source:
247 index = package_index.GetCurrentIndex() 251 index = package_index.GetCurrentIndex()
248 if index.Installable(self.NAME, self.config): 252 if index.Installable(self.NAME, self.config):
249 package_file = index.Download(self.NAME, self.config) 253 package_file = index.Download(self.NAME, self.config)
250 else: 254 else:
251 from_source = True 255 from_source = True
252 256
253 if from_source: 257 if from_source:
254 self.Build(build_deps, force) 258 self.Build(build_deps, force)
255 259
256 if self.IsAnyVersionInstalled(): 260 if self.IsAnyVersionInstalled():
257 Log('Uninstalling existing %s' % self.InfoString()) 261 self.LogStatus('Uninstalling existing')
258 self.GetInstalledPackage().DoUninstall() 262 self.GetInstalledPackage().DoUninstall()
259 263
260 binary_package.BinaryPackage(package_file).Install() 264 binary_package.BinaryPackage(package_file).Install()
261 265
262 def GetInstalledPackage(self): 266 def GetInstalledPackage(self):
263 return package.CreateInstalledPackage(self.NAME, self.config) 267 return package.CreateInstalledPackage(self.NAME, self.config)
264 268
265 def Build(self, build_deps, force=None): 269 def Build(self, build_deps, force=None):
266 self.CheckBuildable() 270 self.CheckBuildable()
267 271
268 if build_deps: 272 if build_deps:
269 self.InstallDeps(force) 273 self.InstallDeps(force)
270 274
271 if not force and self.IsBuilt(): 275 if not force and self.IsBuilt():
272 Log('Already built %s' % self.InfoString()) 276 self.LogStatus('Already built')
273 return 277 return
274 278
275 log_root = os.path.join(paths.OUT_DIR, 'logs') 279 log_root = os.path.join(paths.OUT_DIR, 'logs')
276 util.Makedirs(log_root) 280 util.Makedirs(log_root)
277 281
278 if util.verbose: 282 self.LogStatus('Building')
279 prefix = '*** '
280 else:
281 prefix = ''
282 Log('%sBuilding %s' % (prefix, self.InfoString()))
283 283
284 if util.verbose: 284 if util.verbose:
285 log_filename = None 285 log_filename = None
286 else: 286 else:
287 log_filename = os.path.join(log_root, '%s_%s.log' % (self.NAME, 287 log_filename = os.path.join(log_root, '%s_%s.log' % (self.NAME,
288 str(self.config).replace('/', '_'))) 288 str(self.config).replace('/', '_')))
289 if os.path.exists(log_filename): 289 if os.path.exists(log_filename):
290 os.remove(log_filename) 290 os.remove(log_filename)
291 291
292 start = time.time() 292 start = time.time()
293 with util.BuildLock(): 293 with util.BuildLock():
294 with RedirectStdoutStderr(log_filename): 294 with RedirectStdoutStderr(log_filename):
295 old_verbose = util.verbose 295 old_verbose = util.verbose
296 try: 296 try:
297 util.verbose = True 297 util.verbose = True
298 self.Download() 298 self.Download()
299 self.Extract() 299 self.Extract()
300 self.Patch() 300 self.Patch()
301 self.RunBuildSh() 301 self.RunBuildSh()
302 finally: 302 finally:
303 util.verbose = old_verbose 303 util.verbose = old_verbose
304 304
305 duration = FormatTimeDelta(time.time() - start) 305 duration = FormatTimeDelta(time.time() - start)
306 Log('Build complete %s [took %s]' % (self.InfoString(), duration)) 306 util.LogHeading('Build complete', ' [took %s]' % duration)
307 307
308 def RunBuildSh(self): 308 def RunBuildSh(self):
309 build_port = os.path.join(paths.TOOLS_DIR, 'build_port.sh') 309 build_port = os.path.join(paths.TOOLS_DIR, 'build_port.sh')
310 cmd = [build_port] 310 cmd = [build_port]
311 311
312 env = os.environ.copy() 312 env = os.environ.copy()
313 env['TOOLCHAIN'] = self.config.toolchain 313 env['TOOLCHAIN'] = self.config.toolchain
314 env['NACL_ARCH'] = self.config.arch 314 env['NACL_ARCH'] = self.config.arch
315 env['NACL_DEBUG'] = self.config.debug and '1' or '0' 315 env['NACL_DEBUG'] = self.config.debug and '1' or '0'
316 rtn = subprocess.call(cmd, 316 rtn = subprocess.call(cmd,
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 stamp_file = self.GetExtractStamp() 374 stamp_file = self.GetExtractStamp()
375 stamp_contents = self.GetExtractStampContent() 375 stamp_contents = self.GetExtractStampContent()
376 if os.path.exists(dest): 376 if os.path.exists(dest):
377 if StampContentsMatch(stamp_file, stamp_contents): 377 if StampContentsMatch(stamp_file, stamp_contents):
378 Log('Already up-to-date: %s' % util.RelPath(dest)) 378 Log('Already up-to-date: %s' % util.RelPath(dest))
379 return 379 return
380 380
381 raise Error("Upstream archive or patch has changed.\n" + 381 raise Error("Upstream archive or patch has changed.\n" +
382 "Please remove existing checkout and try again: '%s'" % dest) 382 "Please remove existing checkout and try again: '%s'" % dest)
383 383
384 self.Banner('Extracting') 384 util.LogHeading('Extracting')
385 util.Makedirs(paths.OUT_DIR) 385 util.Makedirs(paths.OUT_DIR)
386 tmp_output_path = tempfile.mkdtemp(dir=paths.OUT_DIR) 386 tmp_output_path = tempfile.mkdtemp(dir=paths.OUT_DIR)
387 try: 387 try:
388 ExtractArchive(archive, tmp_output_path) 388 ExtractArchive(archive, tmp_output_path)
389 src = os.path.join(tmp_output_path, new_foldername) 389 src = os.path.join(tmp_output_path, new_foldername)
390 if not os.path.isdir(src): 390 if not os.path.isdir(src):
391 raise Error('Archive contents not found: %s' % src) 391 raise Error('Archive contents not found: %s' % src)
392 Trace("renaming '%s' -> '%s'" % (src, dest)) 392 Trace("renaming '%s' -> '%s'" % (src, dest))
393 os.rename(src, dest) 393 os.rename(src, dest)
394 finally: 394 finally:
395 shutil.rmtree(tmp_output_path) 395 shutil.rmtree(tmp_output_path)
396 396
397 self.RemoveStamps() 397 self.RemoveStamps()
398 WriteStamp(stamp_file, stamp_contents) 398 WriteStamp(stamp_file, stamp_contents)
399 399
400 def RunCmd(self, cmd, **args): 400 def RunCmd(self, cmd, **args):
401 try: 401 try:
402 subprocess.check_call(cmd, 402 subprocess.check_call(cmd,
403 stdout=sys.stdout, 403 stdout=sys.stdout,
404 stderr=sys.stderr, 404 stderr=sys.stderr,
405 cwd=self.GetBuildLocation(), 405 cwd=self.GetBuildLocation(),
406 **args) 406 **args)
407 except subprocess.CalledProcessError as e: 407 except subprocess.CalledProcessError as e:
408 raise Error(e) 408 raise Error(e)
409 409
410 def Log(self, message): 410 def Log(self, message):
411 Log('%s: %s' % (message, self.InfoString())) 411 Log('%s: %s' % (message, self.InfoString()))
412 412
413 def Banner(self, message):
414 Log("#####################################################################")
415 self.Log(message)
416 Log("#####################################################################")
417
418 def GetStampDir(self): 413 def GetStampDir(self):
419 return os.path.join(paths.STAMP_DIR, self.NAME) 414 return os.path.join(paths.STAMP_DIR, self.NAME)
420 415
421 def RemoveStamps(self): 416 def RemoveStamps(self):
422 util.RemoveTree(self.GetStampDir()) 417 util.RemoveTree(self.GetStampDir())
423 418
424 def Patch(self): 419 def Patch(self):
425 stamp_file = os.path.join(self.GetStampDir(), 'nacl_patch') 420 stamp_file = os.path.join(self.GetStampDir(), 'nacl_patch')
426 src_dir = self.GetBuildLocation() 421 src_dir = self.GetBuildLocation()
427 if self.URL is None: 422 if self.URL is None:
428 return 423 return
429 424
430 if os.path.exists(stamp_file): 425 if os.path.exists(stamp_file):
431 self.Log('Skipping patch step (cleaning source tree)') 426 self.Log('Skipping patch step (cleaning source tree)')
432 cmd = ['git', 'clean', '-f', '-d'] 427 cmd = ['git', 'clean', '-f', '-d']
433 if not util.verbose: 428 if not util.verbose:
434 cmd.append('-q') 429 cmd.append('-q')
435 self.RunCmd(cmd) 430 self.RunCmd(cmd)
436 return 431 return
437 432
438 self.Banner('Patching') 433 util.LogHeading('Patching')
439 Log('Init git repo: %s' % src_dir) 434 Log('Init git repo: %s' % src_dir)
440 try: 435 try:
441 InitGitRepo(src_dir) 436 InitGitRepo(src_dir)
442 except subprocess.CalledProcessError as e: 437 except subprocess.CalledProcessError as e:
443 raise Error(e) 438 raise Error(e)
444 if os.path.exists(self.GetPatchFile()): 439 if os.path.exists(self.GetPatchFile()):
445 Trace('applying patch to: %s' % src_dir) 440 Trace('applying patch to: %s' % src_dir)
446 cmd = ['patch', '-p1', '-g0', '--no-backup-if-mismatch'] 441 cmd = ['patch', '-p1', '-g0', '--no-backup-if-mismatch']
447 with open(self.GetPatchFile()) as f: 442 with open(self.GetPatchFile()) as f:
448 self.RunCmd(cmd, stdin=f) 443 self.RunCmd(cmd, stdin=f)
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 stamp_content += '\n' 559 stamp_content += '\n'
565 560
566 dest = self.GetBuildLocation() 561 dest = self.GetBuildLocation()
567 if os.path.exists(self.GetBuildLocation()): 562 if os.path.exists(self.GetBuildLocation()):
568 if StampContentsMatch(stamp_file, stamp_content): 563 if StampContentsMatch(stamp_file, stamp_content):
569 return 564 return
570 565
571 raise Error('Upstream archive or patch has changed.\n' + 566 raise Error('Upstream archive or patch has changed.\n' +
572 "Please remove existing checkout and try again: '%s'" % dest) 567 "Please remove existing checkout and try again: '%s'" % dest)
573 568
574 self.Banner('Cloning') 569 util.LogHeading('Cloning')
575 # Ensure local mirror is up-to-date 570 # Ensure local mirror is up-to-date
576 git_mirror, git_commit = self.GitCloneToMirror() 571 git_mirror, git_commit = self.GitCloneToMirror()
577 # Clone from the local mirror. 572 # Clone from the local mirror.
578 RunGitCmd(None, ['clone', git_mirror, dest]) 573 RunGitCmd(None, ['clone', git_mirror, dest])
579 RunGitCmd(dest, ['reset', '--hard', git_commit]) 574 RunGitCmd(dest, ['reset', '--hard', git_commit])
580 575
581 # Set the origing to the original URL so it is possible to push directly 576 # Set the origing to the original URL so it is possible to push directly
582 # from the build tree. 577 # from the build tree.
583 RunGitCmd(dest, ['remote', 'set-url', 'origin', '${GIT_URL}']) 578 RunGitCmd(dest, ['remote', 'set-url', 'origin', '${GIT_URL}'])
584 579
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
692 if os.path.isdir(package_name): 687 if os.path.isdir(package_name):
693 return SourcePackage(package_name, config) 688 return SourcePackage(package_name, config)
694 689
695 for subdir in DEFAULT_LOCATIONS: 690 for subdir in DEFAULT_LOCATIONS:
696 pkg_root = os.path.join(paths.NACLPORTS_ROOT, subdir, package_name) 691 pkg_root = os.path.join(paths.NACLPORTS_ROOT, subdir, package_name)
697 info = os.path.join(pkg_root, 'pkg_info') 692 info = os.path.join(pkg_root, 'pkg_info')
698 if os.path.exists(info): 693 if os.path.exists(info):
699 return SourcePackage(pkg_root, config) 694 return SourcePackage(pkg_root, config)
700 695
701 raise Error("Package not found: %s" % package_name) 696 raise Error("Package not found: %s" % package_name)
OLDNEW
« no previous file with comments | « lib/naclports/package.py ('k') | lib/naclports/util.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698