| # 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) |