Index: runtime/tools/utils.py |
diff --git a/runtime/tools/utils.py b/runtime/tools/utils.py |
index 7cf34bee553af2f9b10a63867971a8b966873b72..78b4993eb93bdfb0cbea06f0dd38f73a5707a231 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,113 @@ 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. |
+ command is a list of the command and its arguments. |
+ Input is an optional string of input to feed to the command, it should be |
+ short enough to fit in an i/o pipe buffer. |
+ The pollFn is called occasionally to check if the command should be finished |
Emily Fortuna
2012/08/28 16:49:14
Comment formatting:
"""
Function Description.
Ar
jackpal
2012/08/28 20:15:20
Done.
|
+ early. |
+ If pollFn returns True then the command will finish early. |
+ If outStream is not None, the stdout output of the command will be written to |
+ outStream. |
+ If errStream is not None, the stderr output of the command will be written to |
+ errStream. |
+ If pollFn returns True and killOnEarlyReturn is True, then the subprocess |
+ will be killed, otherwise the subprocess will be detached. |
+ If verbose is True, echos command arguments. |
+ If debug is True, prints debugging information. |
+ If printErrorInfo is True, prints error information when the command returns a |
+ non-zero exit code. |
+ Returns the output of the command. |
+ Raises an exception if the command 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): |