|  | # 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 os | 
|  | import platform | 
|  | import queue | 
|  | import re | 
|  | import subprocess | 
|  | import sys | 
|  | import threading | 
|  | import time | 
|  |  | 
|  | from io import StringIO | 
|  | from subprocess import getoutput | 
|  |  | 
|  | # 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( | 
|  | getoutput( | 
|  | "GREP_OPTIONS= grep -E '^processor' /proc/cpuinfo | wc -l")) | 
|  | if os.path.exists("/usr/bin/hostinfo"): | 
|  | return int( | 
|  | 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, str): | 
|  | 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, str): | 
|  | 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) |