| # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
| # for details. All rights reserved. Use of this source code is governed by a | |
| # BSD-style license that can be found in the LICENSE file. | |
| # 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 StringIO | |
| import subprocess | |
| import sys | |
| import threading | |
| import time | |
| # Try to guess the host operating system. | |
| def GuessOS(): | |
| id = platform.system() | |
| if id == "Linux": | |
| return "linux" | |
| elif id == "Darwin": | |
| return "macos" | |
| elif id == "Windows" or id == "Microsoft": | |
| # On Windows Vista platform.system() can return "Microsoft" with some | |
| # versions of Python, see http://bugs.python.org/issue1082 for details. | |
| return "win32" | |
| elif id == 'FreeBSD': | |
| return 'freebsd' | |
| elif id == 'OpenBSD': | |
| return 'openbsd' | |
| elif id == 'SunOS': | |
| return 'solaris' | |
| else: | |
| return None | |
| # Try to guess the host architecture. | |
| def GuessArchitecture(): | |
| id = platform.machine() | |
| if id.startswith('arm'): | |
| return 'arm' | |
| elif (not id) or (not re.match('(x|i[3-6])86', id) is None): | |
| return 'ia32' | |
| elif id == 'i86pc': | |
| return 'ia32' | |
| else: | |
| return None | |
| # Try to guess the number of cpus on this machine. | |
| def GuessCpus(): | |
| if os.path.exists("/proc/cpuinfo"): | |
| return int( | |
| commands.getoutput( | |
| "GREP_OPTIONS= grep -E '^processor' /proc/cpuinfo | wc -l")) | |
| if os.path.exists("/usr/bin/hostinfo"): | |
| return int( | |
| commands.getoutput( | |
| '/usr/bin/hostinfo | GREP_OPTIONS= grep "processors are logically available." | awk "{ print \$1 }"' | |
| )) | |
| win_cpu_count = os.getenv("NUMBER_OF_PROCESSORS") | |
| if win_cpu_count: | |
| return int(win_cpu_count) | |
| return int(os.getenv("DART_NUMBER_OF_CORES", 2)) | |
| # Returns true if we're running under Windows. | |
| def IsWindows(): | |
| return GuessOS() == 'win32' | |
| # Reads a text file into an array of strings - one for each | |
| # line. Strips comments in the process. | |
| def ReadLinesFrom(name): | |
| result = [] | |
| for line in open(name): | |
| if '#' in line: | |
| line = line[:line.find('#')] | |
| line = line.strip() | |
| if len(line) == 0: | |
| continue | |
| result.append(line) | |
| return result | |
| # Filters out all arguments until the next '--' argument | |
| # occurs. | |
| def ListArgCallback(option, opt_str, value, parser): | |
| if value is None: | |
| value = [] | |
| for arg in parser.rargs: | |
| if arg[:2].startswith('--'): | |
| break | |
| value.append(arg) | |
| del parser.rargs[:len(value)] | |
| setattr(parser.values, option.dest, value) | |
| # Filters out all argument until the first non '-' or the | |
| # '--' argument occurs. | |
| def ListDashArgCallback(option, opt_str, value, parser): | |
| if value is None: | |
| value = [] | |
| for arg in parser.rargs: | |
| if arg[:2].startswith('--') or arg[0] != '-': | |
| break | |
| value.append(arg) | |
| del parser.rargs[:len(value)] | |
| setattr(parser.values, option.dest, value) | |
| # Mapping table between build mode and build configuration. | |
| BUILD_MODES = { | |
| 'debug': 'Debug', | |
| 'release': 'Release', | |
| } | |
| # Mapping table between OS and build output location. | |
| BUILD_ROOT = { | |
| 'linux': os.path.join('out'), | |
| 'freebsd': os.path.join('out'), | |
| 'macos': os.path.join('xcodebuild'), | |
| } | |
| def GetBuildMode(mode): | |
| global BUILD_MODES | |
| return BUILD_MODES[mode] | |
| def GetBuildConf(mode, arch): | |
| return GetBuildMode(mode) + arch.upper() | |
| def GetBuildRoot(host_os, mode=None, arch=None, sanitizer=None): | |
| global BUILD_ROOT | |
| if mode: | |
| return os.path.join(BUILD_ROOT[host_os], | |
| GetBuildConf(mode, arch, sanitizer)) | |
| else: | |
| 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. | |
| Exceptions: | |
| Raises Error if the subprocess returns an error code. | |
| Raises ValueError if called with invalid arguments. | |
| """ | |
| if verbose: | |
| sys.stderr.write("command %s\n" % command) | |
| stdin = None | |
| if input: | |
| stdin = subprocess.PIPE | |
| try: | |
| process = subprocess.Popen( | |
| args=command, | |
| stdin=stdin, | |
| bufsize=1, | |
| stdout=subprocess.PIPE, | |
| stderr=subprocess.PIPE) | |
| except OSError as e: | |
| if not isinstance(command, basestring): | |
| command = ' '.join(command) | |
| if printErrorInfo: | |
| sys.stderr.write("Command failed: '%s'\n" % command) | |
| raise Error(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: | |
| 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: | |
| 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 Error("Command failed: %s" % command) | |
| if debug: | |
| sys.stderr.write("output: %s\n" % out) | |
| return out | |
| def Main(argv): | |
| print "GuessOS() -> ", GuessOS() | |
| print "GuessArchitecture() -> ", GuessArchitecture() | |
| print "GuessCpus() -> ", GuessCpus() | |
| print "IsWindows() -> ", IsWindows() | |
| class Error(Exception): | |
| pass | |
| if __name__ == "__main__": | |
| import sys | |
| Main(sys.argv) |