| Index: runtime/tools/utils.py
 | 
| diff --git a/runtime/tools/utils.py b/runtime/tools/utils.py
 | 
| index 7cf34bee553af2f9b10a63867971a8b966873b72..72312c59302352770a3679d3d7dae88ff22881f9 100644
 | 
| --- a/runtime/tools/utils.py
 | 
| +++ b/runtime/tools/utils.py
 | 
| @@ -5,10 +5,16 @@
 | 
|  # This file contains a set of utilities functions used by other Python-based
 | 
|  # scripts.
 | 
|  
 | 
| +import commands
 | 
| +import os
 | 
|  import platform
 | 
| +import Queue
 | 
|  import re
 | 
| -import os
 | 
| -import commands
 | 
| +import StringIO
 | 
| +import subprocess
 | 
| +import sys
 | 
| +import threading
 | 
| +import time
 | 
|  
 | 
|  
 | 
|  # Try to guess the host operating system.
 | 
| @@ -128,12 +134,116 @@ def GetBuildConf(mode, arch):
 | 
|    return GetBuildMode(mode) + arch.upper()
 | 
|  
 | 
|  
 | 
| -def GetBuildRoot(target_os, mode=None, arch=None):
 | 
| +def GetBuildRoot(host_os, mode=None, arch=None):
 | 
|    global BUILD_ROOT
 | 
|    if mode:
 | 
| -    return os.path.join(BUILD_ROOT[target_os], GetBuildConf(mode, arch))
 | 
| +    return os.path.join(BUILD_ROOT[host_os], GetBuildConf(mode, arch))
 | 
|    else:
 | 
| -    return BUILD_ROOT[target_os]
 | 
| +    return BUILD_ROOT[host_os]
 | 
| +
 | 
| +
 | 
| +def RunCommand(command, input=None, pollFn=None, outStream=None, errStream=None,
 | 
| +               killOnEarlyReturn=True, verbose=False, debug=False,
 | 
| +               printErrorInfo=False):
 | 
| +  """
 | 
| +  Run a command, with optional input and polling function.
 | 
| +
 | 
| +  Args:
 | 
| +    command: list of the command and its arguments.
 | 
| +    input: optional string of input to feed to the command, it should be
 | 
| +        short enough to fit in an i/o pipe buffer.
 | 
| +    pollFn: if present will be called occasionally to check if the command
 | 
| +        should be finished early. If pollFn() returns true then the command
 | 
| +        will finish early.
 | 
| +    outStream: if present, the stdout output of the command will be written to
 | 
| +        outStream.
 | 
| +    errStream: if present, the stderr output of the command will be written to
 | 
| +        errStream.
 | 
| +    killOnEarlyReturn: if true and pollFn returns true, then the subprocess will
 | 
| +        be killed, otherwise the subprocess will be detached.
 | 
| +    verbose: if true, the command is echoed to stderr.
 | 
| +    debug: if true, prints debugging information to stderr.
 | 
| +    printErrorInfo: if true, prints error information when the subprocess
 | 
| +    returns a non-zero exit code.
 | 
| +  Returns: the output of the subprocess.
 | 
| +
 | 
| +  Raises an exception if the subprocess returns an error code.
 | 
| +  """
 | 
| +  if verbose:
 | 
| +    sys.stderr.write("command %s\n" % command)
 | 
| +  stdin = None
 | 
| +  if input is not None:
 | 
| +    stdin = subprocess.PIPE
 | 
| +  try:
 | 
| +    process = subprocess.Popen(args=command,
 | 
| +                               stdin=stdin,
 | 
| +                               bufsize=1,
 | 
| +                               stdout=subprocess.PIPE,
 | 
| +                               stderr=subprocess.PIPE)
 | 
| +  except Exception as e:
 | 
| +    if not isinstance(command, basestring):
 | 
| +      command = ' '.join(command)
 | 
| +    if printErrorInfo:
 | 
| +      sys.stderr.write("Command failed: '%s'\n" % command)
 | 
| +    raise e
 | 
| +
 | 
| +  def StartThread(out):
 | 
| +    queue = Queue.Queue()
 | 
| +    def EnqueueOutput(out, queue):
 | 
| +      for line in iter(out.readline, b''):
 | 
| +        queue.put(line)
 | 
| +      out.close()
 | 
| +    thread = threading.Thread(target=EnqueueOutput, args=(out, queue))
 | 
| +    thread.daemon = True
 | 
| +    thread.start()
 | 
| +    return queue
 | 
| +  outQueue = StartThread(process.stdout)
 | 
| +  errQueue = StartThread(process.stderr)
 | 
| +
 | 
| +  def ReadQueue(queue, out, out2):
 | 
| +    try:
 | 
| +      while True:
 | 
| +        line = queue.get(False)
 | 
| +        out.write(line)
 | 
| +        if out2 != None:
 | 
| +          out2.write(line)
 | 
| +    except Queue.Empty:
 | 
| +      pass
 | 
| +
 | 
| +  outBuf = StringIO.StringIO()
 | 
| +  errorBuf = StringIO.StringIO()
 | 
| +  if input != None:
 | 
| +    process.stdin.write(input)
 | 
| +  while True:
 | 
| +    returncode = process.poll()
 | 
| +    if returncode != None:
 | 
| +      break
 | 
| +    ReadQueue(errQueue, errorBuf, errStream)
 | 
| +    ReadQueue(outQueue, outBuf, outStream)
 | 
| +    if pollFn != None and pollFn():
 | 
| +      returncode = 0
 | 
| +      if killOnEarlyReturn:
 | 
| +        process.kill()
 | 
| +      break
 | 
| +    time.sleep(0.1)
 | 
| +  # Drain queue
 | 
| +  ReadQueue(errQueue, errorBuf, errStream)
 | 
| +  ReadQueue(outQueue, outBuf, outStream)
 | 
| +
 | 
| +  out = outBuf.getvalue();
 | 
| +  error = errorBuf.getvalue();
 | 
| +  if returncode != 0:
 | 
| +    if not isinstance(command, basestring):
 | 
| +      command = ' '.join(command)
 | 
| +    if printErrorInfo:
 | 
| +      sys.stderr.write("Command failed: '%s'\n" % command)
 | 
| +      sys.stderr.write("        stdout: '%s'\n" % out)
 | 
| +      sys.stderr.write("        stderr: '%s'\n" % error)
 | 
| +      sys.stderr.write("    returncode: %d\n" % returncode)
 | 
| +    raise Exception("Command failed: %s" % command)
 | 
| +  if debug:
 | 
| +    sys.stderr.write("output: %s\n" % out)
 | 
| +  return out
 | 
|  
 | 
|  
 | 
|  def Main(argv):
 | 
| 
 |