waf

FORK: waf with some random patches
git clone https://git.neptards.moe/neptards/waf.git
Log | Files | Refs | README

build_logs.py (2824B)


      1 #!/usr/bin/env python
      2 # encoding: utf-8
      3 # Thomas Nagy, 2013 (ita)
      4 
      5 """
      6 A system for recording all outputs to a log file. Just add the following to your wscript file::
      7 
      8   def init(ctx):
      9     ctx.load('build_logs')
     10 """
     11 
     12 import atexit, sys, time, os, shutil, threading
     13 from waflib import ansiterm, Logs, Context
     14 
     15 # adding the logs under the build/ directory will clash with the clean/ command
     16 try:
     17 	up = os.path.dirname(Context.g_module.__file__)
     18 except AttributeError:
     19 	up = '.'
     20 LOGFILE = os.path.join(up, 'logs', time.strftime('%Y_%m_%d_%H_%M.log'))
     21 
     22 wlock = threading.Lock()
     23 class log_to_file(object):
     24 	def __init__(self, stream, fileobj, filename):
     25 		self.stream = stream
     26 		self.encoding = self.stream.encoding
     27 		self.fileobj = fileobj
     28 		self.filename = filename
     29 		self.is_valid = True
     30 	def replace_colors(self, data):
     31 		for x in Logs.colors_lst.values():
     32 			if isinstance(x, str):
     33 				data = data.replace(x, '')
     34 		return data
     35 	def write(self, data):
     36 		try:
     37 			wlock.acquire()
     38 			self.stream.write(data)
     39 			self.stream.flush()
     40 			if self.is_valid:
     41 				self.fileobj.write(self.replace_colors(data))
     42 		finally:
     43 			wlock.release()
     44 	def fileno(self):
     45 		return self.stream.fileno()
     46 	def flush(self):
     47 		self.stream.flush()
     48 		if self.is_valid:
     49 			self.fileobj.flush()
     50 	def isatty(self):
     51 		return self.stream.isatty()
     52 
     53 def init(ctx):
     54 	global LOGFILE
     55 	filename = os.path.abspath(LOGFILE)
     56 	try:
     57 		os.makedirs(os.path.dirname(os.path.abspath(filename)))
     58 	except OSError:
     59 		pass
     60 
     61 	if hasattr(os, 'O_NOINHERIT'):
     62 		fd = os.open(LOGFILE, os.O_CREAT | os.O_TRUNC | os.O_WRONLY | os.O_NOINHERIT)
     63 		fileobj = os.fdopen(fd, 'w')
     64 	else:
     65 		fileobj = open(LOGFILE, 'w')
     66 	old_stderr = sys.stderr
     67 
     68 	# sys.stdout has already been replaced, so __stdout__ will be faster
     69 	#sys.stdout = log_to_file(sys.stdout, fileobj, filename)
     70 	#sys.stderr = log_to_file(sys.stderr, fileobj, filename)
     71 	def wrap(stream):
     72 		if stream.isatty():
     73 			return ansiterm.AnsiTerm(stream)
     74 		return stream
     75 	sys.stdout = log_to_file(wrap(sys.__stdout__), fileobj, filename)
     76 	sys.stderr = log_to_file(wrap(sys.__stderr__), fileobj, filename)
     77 
     78 	# now mess with the logging module...
     79 	for x in Logs.log.handlers:
     80 		try:
     81 			stream = x.stream
     82 		except AttributeError:
     83 			pass
     84 		else:
     85 			if id(stream) == id(old_stderr):
     86 				x.stream = sys.stderr
     87 
     88 def exit_cleanup():
     89 	try:
     90 		fileobj = sys.stdout.fileobj
     91 	except AttributeError:
     92 		pass
     93 	else:
     94 		sys.stdout.is_valid = False
     95 		sys.stderr.is_valid = False
     96 		fileobj.close()
     97 		filename = sys.stdout.filename
     98 
     99 		Logs.info('Output logged to %r', filename)
    100 
    101 		# then copy the log file to "latest.log" if possible
    102 		up = os.path.dirname(os.path.abspath(filename))
    103 		try:
    104 			shutil.copy(filename, os.path.join(up, 'latest.log'))
    105 		except OSError:
    106 			# this may fail on windows due to processes spawned
    107 			pass
    108 
    109 atexit.register(exit_cleanup)
    110