Mercurial > hg > truffle
diff pytools/gl.py @ 3607:de066dcbf607
Added Python scripts in new 'shell' project. The shell/commands.py script should replace all the existing run*.sh scripts in the top level Graal directory and is where new commands should go.
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Mon, 31 Oct 2011 21:06:04 +0100 |
parents | |
children | 3b2ab8970aa4 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pytools/gl.py Mon Oct 31 21:06:04 2011 +0100 @@ -0,0 +1,221 @@ +#!/usr/bin/python +# +# gl.py - shell interface for Graal source code +# +# ---------------------------------------------------------------------------------------------------- +# +# Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ---------------------------------------------------------------------------------------------------- +# +# A launcher for Graal executables and tools. +# + +import subprocess +from threading import Thread +from argparse import ArgumentParser, REMAINDER +from os.path import join, dirname, abspath, exists, isfile, isdir +import commands +import types +import sys +import os + +class Env(ArgumentParser): + + # Override parent to append the list of available commands + def format_help(self): + msg = ArgumentParser.format_help(self) + '\navailable commands:\n\n' + for cmd in sorted(commands.table.iterkeys()): + c, _ = commands.table[cmd][:2] + doc = c.__doc__ + if doc is None: + doc = '' + msg += ' {0:<20} {1}\n'.format(cmd, doc.split('\n', 1)[0]) + return msg + '\n' + + def __init__(self): + self.dacapo = os.getenv('DACAPO') + self.jdk7 = os.getenv('JDK7') + self.jdk7g = os.getenv('JDK7G') + self.maxine_home = os.getenv('MAXINE') + + ArgumentParser.__init__(self, prog='gl') + + self.add_argument('-v', action='store_true', dest='verbose', help='enable verbose output') + self.add_argument('--dacapo', help='path to DaCapo 91.12 jar file') + self.add_argument('--jdk7', help='JDK7 installation in which the GraalVM binary is installed', metavar='<path>') + self.add_argument('--jdk7g', help='JDK7G installation in which the GraalVM binary is installed', metavar='<path>') + self.add_argument('-M', '--maxine', dest='maxine_home', help='path to Maxine code base', metavar='<path>') + + def parse_cmd_line(self): + + self.add_argument('commandAndArgs', nargs=REMAINDER, metavar='command args...') + + self.parse_args(namespace=self) + + if not isdir(self.jdk7): + self.log('JDK7 is required. Use --jdk7 option or set JDK7 environment variable') + self.abort(1) + + if not isdir(self.jdk7g): + self.log('JDK7G is required. Use --jdk7g option or set JDK7G environment variable') + self.abort(1) + + self.graal_home = dirname(abspath(dirname(sys.argv[0]))) + + def load_config_file(self, configFile): + """ adds attributes to this object from a file containing key=value lines """ + if exists(configFile): + with open(configFile) as f: + self.log('[loading vars from ' + configFile + ']') + for line in f: + kv = line.split('=', 1) + if len(kv) == 2: + k = kv[0].strip().lower() + setattr(self, k, os.path.expandvars(kv[1].strip())) + + def get_os(self): + if sys.platform.startswith('darwin'): + return 'darwin' + elif sys.platform.startswith('linux'): + return 'linux' + elif sys.platform.startswith('sunos'): + return 'solaris' + elif sys.platform.startswith('win32') or sys.platform.startswith('cygwin'): + return 'windows' + else: + print 'Supported operating system could not be derived from', sys.platform + self.abort(1) + + + def exe(self, name): + if self.get_os() == 'windows': + return name + '.exe' + return name + + def run_dacapo(self, args): + if not isfile(self.dacapo) or not self.dacapo.endswith('.jar'): + self.log('Specified DaCapo jar file does not exist or is not a jar file: ' + self.dacapo) + self.abort(1) + return self.run_vm(['-Xms1g', '-Xmx2g', '-esa', '-XX:-GraalBailoutIsFatal', '-G:-QuietBailout', '-cp', self.dacapo] + args) + + def run_vm(self, args): + if self.maxine_home is None: + self.log('Path to Maxine code base must be specified with -M option of MAXINE environment variable') + self.abort(1) + if not exists(join(self.maxine_home, 'com.oracle.max.graal.hotspot', 'bin', 'com', 'oracle', 'max', 'graal', 'hotspot', 'VMEntriesNative.class')): + self.log('Maxine code base path specified -M option or MAXINE environment variable does not contain com.oracle.max.graal.hotspot/bin/com/oracle/max/graal/hotspot/VMEntriesNative.class: ' + self.maxine_home) + self.abort(1) + + os.environ['MAXINE'] = self.maxine_home + exe = join(self.jdk7, 'bin', self.exe('java')) + return self.run([exe, '-graal'] + args) + + def run(self, args, nonZeroIsFatal=True, out=None, err=None, cwd=None): + """ + + Run a command in a subprocess, wait for it to complete and return the exit status of the process. + If the exit status is non-zero and `nonZeroIsFatal` is true, then the program is exited with + the same exit status. + Each line of the standard output and error streams of the subprocess are redirected to the + provided out and err functions if they are not None. + + """ + + assert isinstance(args, types.ListType), "'args' must be a list: " + str(args) + for arg in args: + if not isinstance(arg, types.StringTypes): + self.log('argument is not a string: ' + str(arg)) + self.abort(1) + + if self.verbose: + self.log(' '.join(args)) + + try: + if out is None and err is None: + retcode = subprocess.call(args, cwd=cwd) + else: + def redirect(stream, f): + for line in iter(stream.readline, ''): + f(line) + stream.close() + p = subprocess.Popen(args, stdout=None if out is None else subprocess.PIPE, stderr=None if err is None else subprocess.PIPE) + if out is not None: + t = Thread(target=redirect, args=(p.stdout, out)) + t.daemon = True # thread dies with the program + t.start() + if err is not None: + t = Thread(target=redirect, args=(p.stderr, err)) + t.daemon = True # thread dies with the program + t.start() + retcode = p.wait() + except OSError as e: + self.log('Error executing \'' + ' '.join(args) + '\': ' + str(e)) + if self.verbose: + raise e + self.abort(e.errno) + + + if retcode and nonZeroIsFatal: + if self.verbose: + raise subprocess.CalledProcessError(retcode, ' '.join(args)) + self.abort(retcode) + + return retcode + + + def log(self, msg=None): + if msg is None: + print + else: + print msg + + def abort(self, code): + """ raises a SystemExit exception with the provided exit code """ + raise SystemExit(code) + +def main(env): + configFile = join(dirname(sys.argv[0]), 'glrc') + env.load_config_file(configFile) + env.parse_cmd_line() + + if len(env.commandAndArgs) == 0: + env.print_help() + return + + env.command = env.commandAndArgs[0] + env.command_args = env.commandAndArgs[1:] + + if not commands.table.has_key(env.command): + env.error('unknown command "' + env.command + '"') + + c, _ = commands.table[env.command][:2] + try: + retcode = c(env, env.command_args) + if retcode is not None and retcode != 0: + env.abort(retcode) + except KeyboardInterrupt: + env.abort(1) + +#This idiom means the below code only runs when executed from command line +if __name__ == '__main__': + main(Env())