comparison 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
comparison
equal deleted inserted replaced
3606:f2fd47582524 3607:de066dcbf607
1 #!/usr/bin/python
2 #
3 # gl.py - shell interface for Graal source code
4 #
5 # ----------------------------------------------------------------------------------------------------
6 #
7 # Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
8 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9 #
10 # This code is free software; you can redistribute it and/or modify it
11 # under the terms of the GNU General Public License version 2 only, as
12 # published by the Free Software Foundation.
13 #
14 # This code is distributed in the hope that it will be useful, but WITHOUT
15 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 # version 2 for more details (a copy is included in the LICENSE file that
18 # accompanied this code).
19 #
20 # You should have received a copy of the GNU General Public License version
21 # 2 along with this work; if not, write to the Free Software Foundation,
22 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23 #
24 # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
25 # or visit www.oracle.com if you need additional information or have any
26 # questions.
27 #
28 # ----------------------------------------------------------------------------------------------------
29 #
30 # A launcher for Graal executables and tools.
31 #
32
33 import subprocess
34 from threading import Thread
35 from argparse import ArgumentParser, REMAINDER
36 from os.path import join, dirname, abspath, exists, isfile, isdir
37 import commands
38 import types
39 import sys
40 import os
41
42 class Env(ArgumentParser):
43
44 # Override parent to append the list of available commands
45 def format_help(self):
46 msg = ArgumentParser.format_help(self) + '\navailable commands:\n\n'
47 for cmd in sorted(commands.table.iterkeys()):
48 c, _ = commands.table[cmd][:2]
49 doc = c.__doc__
50 if doc is None:
51 doc = ''
52 msg += ' {0:<20} {1}\n'.format(cmd, doc.split('\n', 1)[0])
53 return msg + '\n'
54
55 def __init__(self):
56 self.dacapo = os.getenv('DACAPO')
57 self.jdk7 = os.getenv('JDK7')
58 self.jdk7g = os.getenv('JDK7G')
59 self.maxine_home = os.getenv('MAXINE')
60
61 ArgumentParser.__init__(self, prog='gl')
62
63 self.add_argument('-v', action='store_true', dest='verbose', help='enable verbose output')
64 self.add_argument('--dacapo', help='path to DaCapo 91.12 jar file')
65 self.add_argument('--jdk7', help='JDK7 installation in which the GraalVM binary is installed', metavar='<path>')
66 self.add_argument('--jdk7g', help='JDK7G installation in which the GraalVM binary is installed', metavar='<path>')
67 self.add_argument('-M', '--maxine', dest='maxine_home', help='path to Maxine code base', metavar='<path>')
68
69 def parse_cmd_line(self):
70
71 self.add_argument('commandAndArgs', nargs=REMAINDER, metavar='command args...')
72
73 self.parse_args(namespace=self)
74
75 if not isdir(self.jdk7):
76 self.log('JDK7 is required. Use --jdk7 option or set JDK7 environment variable')
77 self.abort(1)
78
79 if not isdir(self.jdk7g):
80 self.log('JDK7G is required. Use --jdk7g option or set JDK7G environment variable')
81 self.abort(1)
82
83 self.graal_home = dirname(abspath(dirname(sys.argv[0])))
84
85 def load_config_file(self, configFile):
86 """ adds attributes to this object from a file containing key=value lines """
87 if exists(configFile):
88 with open(configFile) as f:
89 self.log('[loading vars from ' + configFile + ']')
90 for line in f:
91 kv = line.split('=', 1)
92 if len(kv) == 2:
93 k = kv[0].strip().lower()
94 setattr(self, k, os.path.expandvars(kv[1].strip()))
95
96 def get_os(self):
97 if sys.platform.startswith('darwin'):
98 return 'darwin'
99 elif sys.platform.startswith('linux'):
100 return 'linux'
101 elif sys.platform.startswith('sunos'):
102 return 'solaris'
103 elif sys.platform.startswith('win32') or sys.platform.startswith('cygwin'):
104 return 'windows'
105 else:
106 print 'Supported operating system could not be derived from', sys.platform
107 self.abort(1)
108
109
110 def exe(self, name):
111 if self.get_os() == 'windows':
112 return name + '.exe'
113 return name
114
115 def run_dacapo(self, args):
116 if not isfile(self.dacapo) or not self.dacapo.endswith('.jar'):
117 self.log('Specified DaCapo jar file does not exist or is not a jar file: ' + self.dacapo)
118 self.abort(1)
119 return self.run_vm(['-Xms1g', '-Xmx2g', '-esa', '-XX:-GraalBailoutIsFatal', '-G:-QuietBailout', '-cp', self.dacapo] + args)
120
121 def run_vm(self, args):
122 if self.maxine_home is None:
123 self.log('Path to Maxine code base must be specified with -M option of MAXINE environment variable')
124 self.abort(1)
125 if not exists(join(self.maxine_home, 'com.oracle.max.graal.hotspot', 'bin', 'com', 'oracle', 'max', 'graal', 'hotspot', 'VMEntriesNative.class')):
126 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)
127 self.abort(1)
128
129 os.environ['MAXINE'] = self.maxine_home
130 exe = join(self.jdk7, 'bin', self.exe('java'))
131 return self.run([exe, '-graal'] + args)
132
133 def run(self, args, nonZeroIsFatal=True, out=None, err=None, cwd=None):
134 """
135
136 Run a command in a subprocess, wait for it to complete and return the exit status of the process.
137 If the exit status is non-zero and `nonZeroIsFatal` is true, then the program is exited with
138 the same exit status.
139 Each line of the standard output and error streams of the subprocess are redirected to the
140 provided out and err functions if they are not None.
141
142 """
143
144 assert isinstance(args, types.ListType), "'args' must be a list: " + str(args)
145 for arg in args:
146 if not isinstance(arg, types.StringTypes):
147 self.log('argument is not a string: ' + str(arg))
148 self.abort(1)
149
150 if self.verbose:
151 self.log(' '.join(args))
152
153 try:
154 if out is None and err is None:
155 retcode = subprocess.call(args, cwd=cwd)
156 else:
157 def redirect(stream, f):
158 for line in iter(stream.readline, ''):
159 f(line)
160 stream.close()
161 p = subprocess.Popen(args, stdout=None if out is None else subprocess.PIPE, stderr=None if err is None else subprocess.PIPE)
162 if out is not None:
163 t = Thread(target=redirect, args=(p.stdout, out))
164 t.daemon = True # thread dies with the program
165 t.start()
166 if err is not None:
167 t = Thread(target=redirect, args=(p.stderr, err))
168 t.daemon = True # thread dies with the program
169 t.start()
170 retcode = p.wait()
171 except OSError as e:
172 self.log('Error executing \'' + ' '.join(args) + '\': ' + str(e))
173 if self.verbose:
174 raise e
175 self.abort(e.errno)
176
177
178 if retcode and nonZeroIsFatal:
179 if self.verbose:
180 raise subprocess.CalledProcessError(retcode, ' '.join(args))
181 self.abort(retcode)
182
183 return retcode
184
185
186 def log(self, msg=None):
187 if msg is None:
188 print
189 else:
190 print msg
191
192 def abort(self, code):
193 """ raises a SystemExit exception with the provided exit code """
194 raise SystemExit(code)
195
196 def main(env):
197 configFile = join(dirname(sys.argv[0]), 'glrc')
198 env.load_config_file(configFile)
199 env.parse_cmd_line()
200
201 if len(env.commandAndArgs) == 0:
202 env.print_help()
203 return
204
205 env.command = env.commandAndArgs[0]
206 env.command_args = env.commandAndArgs[1:]
207
208 if not commands.table.has_key(env.command):
209 env.error('unknown command "' + env.command + '"')
210
211 c, _ = commands.table[env.command][:2]
212 try:
213 retcode = c(env, env.command_args)
214 if retcode is not None and retcode != 0:
215 env.abort(retcode)
216 except KeyboardInterrupt:
217 env.abort(1)
218
219 #This idiom means the below code only runs when executed from command line
220 if __name__ == '__main__':
221 main(Env())