# HG changeset patch # User Mick Jordan # Date 1384313965 28800 # Node ID 6cdf3b17316d4c9ea1ebcc45741191744be00dea # Parent bff24aae46402ba065e9cbd80db3583d66777546 mx: rename commands.py as mx_graal.py diff -r bff24aae4640 -r 6cdf3b17316d mx/commands.py --- a/mx/commands.py Tue Nov 12 16:22:18 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1427 +0,0 @@ -# -# commands.py - the GraalVM specific commands -# -# ---------------------------------------------------------------------------------------------------- -# -# Copyright (c) 2007, 2012, 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. -# -# ---------------------------------------------------------------------------------------------------- - -import os, sys, shutil, zipfile, tempfile, re, time, datetime, platform, subprocess, multiprocessing -from os.path import join, exists, dirname, basename, getmtime -from argparse import ArgumentParser, REMAINDER -import mx -import sanitycheck -import itertools -import json, textwrap - -# This works because when mx loads this file, it makes sure __file__ gets an absolute path -_graal_home = dirname(dirname(__file__)) - -""" Used to distinguish an exported GraalVM (see 'mx export'). """ -_vmSourcesAvailable = exists(join(_graal_home, 'make')) and exists(join(_graal_home, 'src')) - -""" The VMs that can be built and run along with an optional description. Only VMs with a - description are listed in the dialogue for setting the default VM (see _get_vm()). """ -_vmChoices = { - 'graal' : 'All compilation is performed with Graal. This includes bootstrapping Graal itself unless -XX:-BootstrapGraal is used.', - 'server' : 'Normal compilation is performed with the tiered system (i.e., client + server), Truffle compilation is performed with Graal. Use this for optimal Truffle performance.', - 'client' : None, # normal compilation with client compiler, explicit compilation (e.g., by Truffle) with Graal - 'server-nograal' : None, # all compilation with tiered system (i.e., client + server), Graal omitted - 'client-nograal' : None, # all compilation with client compiler, Graal omitted - 'original' : None, # default VM copied from bootstrap JDK -} - -""" The VM that will be run by the 'vm' command and built by default by the 'build' command. - This can be set via the global '--vm' option or the DEFAULT_VM environment variable. - It can also be temporarily set by using of a VM context manager object in a 'with' statement. """ -_vm = None - -""" The VM builds that will be run by the 'vm' command - default is first in list """ -_vmbuildChoices = ['product', 'fastdebug', 'debug', 'optimized'] - -""" The VM build that will be run by the 'vm' command. - This can be set via the global '--vmbuild' option. - It can also be temporarily set by using of a VM context manager object in a 'with' statement. """ -_vmbuild = _vmbuildChoices[0] - -_jacoco = 'off' - -""" The current working directory to switch to before running the VM. """ -_vm_cwd = None - -""" The base directory in which the JDKs cloned from $JAVA_HOME exist. """ -_installed_jdks = None - -""" Prefix for running the VM. """ -_vm_prefix = None - -_make_eclipse_launch = False - -_minVersion = mx.JavaVersion('1.7.0_04') - -def _get_vm(): - """ - Gets the configured VM, presenting a dialogue if there is no currently configured VM. - """ - global _vm - if _vm: - return _vm - vm = mx.get_env('DEFAULT_VM') - if vm is None: - if not sys.stdout.isatty(): - mx.abort('Need to specify VM with --vm option or DEFAULT_VM environment variable') - envPath = join(_graal_home, 'mx', 'env') - mx.log('Please select the VM to be executed from the following: ') - items = [k for k in _vmChoices.keys() if _vmChoices[k] is not None] - descriptions = [_vmChoices[k] for k in _vmChoices.keys() if _vmChoices[k] is not None] - vm = mx.select_items(items, descriptions, allowMultiple=False) - if mx.ask_yes_no('Persist this choice by adding "DEFAULT_VM=' + vm + '" to ' + envPath, 'y'): - with open(envPath, 'a') as fp: - print >> fp, 'DEFAULT_VM=' + vm - _vm = vm - return vm - -""" -A context manager that can be used with the 'with' statement to set the VM -used by all VM executions within the scope of the 'with' statement. For example: - - with VM('server'): - dacapo(['pmd']) -""" -class VM: - def __init__(self, vm=None, build=None): - assert vm is None or vm in _vmChoices.keys() - assert build is None or build in _vmbuildChoices - self.vm = vm if vm else _vm - self.build = build if build else _vmbuild - self.previousVm = _vm - self.previousBuild = _vmbuild - - def __enter__(self): - global _vm, _vmbuild - _vm = self.vm - _vmbuild = self.build - - def __exit__(self, exc_type, exc_value, traceback): - global _vm, _vmbuild - _vm = self.previousVm - _vmbuild = self.previousBuild - -def _chmodDir(chmodFlags, dirname, fnames): - os.chmod(dirname, chmodFlags) - for name in fnames: - os.chmod(os.path.join(dirname, name), chmodFlags) - -def chmodRecursive(dirname, chmodFlags): - os.path.walk(dirname, _chmodDir, chmodFlags) - -def clean(args): - """clean the GraalVM source tree""" - opts = mx.clean(args, parser=ArgumentParser(prog='mx clean')) - if opts.native: - def rmIfExists(name): - if os.path.isdir(name): - shutil.rmtree(name) - elif os.path.isfile(name): - os.unlink(name) - - rmIfExists(join(_graal_home, 'build')) - rmIfExists(join(_graal_home, 'build-nograal')) - rmIfExists(_jdksDir()) - rmIfExists(mx.distribution('GRAAL').path) - -def export(args): - """create a GraalVM zip file for distribution""" - - parser = ArgumentParser(prog='mx export') - parser.add_argument('--omit-vm-build', action='store_false', dest='vmbuild', help='omit VM build step') - parser.add_argument('--omit-dist-init', action='store_false', dest='distInit', help='omit class files and IDE configurations from distribution') - parser.add_argument('zipfile', nargs=REMAINDER, metavar='zipfile') - - args = parser.parse_args(args) - - tmp = tempfile.mkdtemp(prefix='tmp', dir=_graal_home) - if args.vmbuild: - # Make sure the product VM binary is up to date - with VM(vmbuild='product'): - build([]) - - mx.log('Copying Java sources and mx files...') - mx.run(('hg archive -I graal -I mx -I mxtool -I mx.sh ' + tmp).split()) - - # Copy the GraalVM JDK - mx.log('Copying GraalVM JDK...') - src = _jdk() - dst = join(tmp, basename(src)) - shutil.copytree(src, dst) - zfName = join(_graal_home, 'graalvm-' + mx.get_os() + '.zip') - zf = zipfile.ZipFile(zfName, 'w') - for root, _, files in os.walk(tmp): - for f in files: - name = join(root, f) - arcname = name[len(tmp) + 1:] - zf.write(join(tmp, name), arcname) - - # create class files and IDE configurations - if args.distInit: - mx.log('Creating class files...') - mx.run('mx build'.split(), cwd=tmp) - mx.log('Creating IDE configurations...') - mx.run('mx ideinit'.split(), cwd=tmp) - - # clean up temp directory - mx.log('Cleaning up...') - shutil.rmtree(tmp) - - mx.log('Created distribution in ' + zfName) - -def _run_benchmark(args, availableBenchmarks, runBenchmark): - - vmOpts, benchmarksAndOptions = _extract_VM_args(args, useDoubleDash=availableBenchmarks is None) - - if availableBenchmarks is None: - harnessArgs = benchmarksAndOptions - return runBenchmark(None, harnessArgs, vmOpts) - - if len(benchmarksAndOptions) == 0: - mx.abort('at least one benchmark name or "all" must be specified') - benchmarks = list(itertools.takewhile(lambda x: not x.startswith('-'), benchmarksAndOptions)) - harnessArgs = benchmarksAndOptions[len(benchmarks):] - - if 'all' in benchmarks: - benchmarks = availableBenchmarks - else: - for bm in benchmarks: - if bm not in availableBenchmarks: - mx.abort('unknown benchmark: ' + bm + '\nselect one of: ' + str(availableBenchmarks)) - - failed = [] - for bm in benchmarks: - if not runBenchmark(bm, harnessArgs, vmOpts): - failed.append(bm) - - if len(failed) != 0: - mx.abort('Benchmark failures: ' + str(failed)) - -def dacapo(args): - """run one or more DaCapo benchmarks""" - - def launcher(bm, harnessArgs, extraVmOpts): - return sanitycheck.getDacapo(bm, harnessArgs).test(_get_vm(), extraVmOpts=extraVmOpts) - - _run_benchmark(args, sanitycheck.dacapoSanityWarmup.keys(), launcher) - -def scaladacapo(args): - """run one or more Scala DaCapo benchmarks""" - - def launcher(bm, harnessArgs, extraVmOpts): - return sanitycheck.getScalaDacapo(bm, harnessArgs).test(_get_vm(), extraVmOpts=extraVmOpts) - - _run_benchmark(args, sanitycheck.dacapoScalaSanityWarmup.keys(), launcher) - -def _arch(): - machine = platform.uname()[4] - if machine in ['amd64', 'AMD64', 'x86_64', 'i86pc']: - return 'amd64' - if machine in ['sun4v', 'sun4u']: - return 'sparcv9' - if machine == 'i386' and mx.get_os() == 'darwin': - try: - # Support for Snow Leopard and earlier version of MacOSX - if subprocess.check_output(['sysctl', '-n', 'hw.cpu64bit_capable']).strip() == '1': - return 'amd64' - except OSError: - # sysctl is not available - pass - mx.abort('unknown or unsupported architecture: os=' + mx.get_os() + ', machine=' + machine) - -def _vmLibDirInJdk(jdk): - """ - Get the directory within a JDK where the server and client - subdirectories are located. - """ - if platform.system() == 'Darwin': - return join(jdk, 'jre', 'lib') - if platform.system() == 'Windows': - return join(jdk, 'jre', 'bin') - return join(jdk, 'jre', 'lib', _arch()) - -def _vmCfgInJdk(jdk): - """ - Get the jvm.cfg file. - """ - if platform.system() == 'Windows': - return join(jdk, 'jre', 'lib', _arch(), 'jvm.cfg') - return join(_vmLibDirInJdk(jdk), 'jvm.cfg') - -def _jdksDir(): - return os.path.abspath(join(_installed_jdks if _installed_jdks else _graal_home, 'jdk' + str(mx.java().version))) - -def _handle_missing_VM(bld, vm): - mx.log('The ' + bld + ' ' + vm + ' VM has not been created') - if sys.stdout.isatty(): - if mx.ask_yes_no('Build it now', 'y'): - with VM(vm, bld): - build([]) - return - mx.abort('You need to run "mx --vm ' + vm + ' --vmbuild ' + bld + ' build" to build the selected VM') - -def _jdk(build='product', vmToCheck=None, create=False, installGraalJar=True): - """ - Get the JDK into which Graal is installed, creating it first if necessary. - """ - jdk = join(_jdksDir(), build) - if create: - srcJdk = mx.java().jdk - jdkContents = ['bin', 'include', 'jre', 'lib'] - if exists(join(srcJdk, 'db')): - jdkContents.append('db') - if mx.get_os() != 'windows' and exists(join(srcJdk, 'man')): - jdkContents.append('man') - if not exists(jdk): - mx.log('Creating ' + jdk + ' from ' + srcJdk) - os.makedirs(jdk) - for d in jdkContents: - src = join(srcJdk, d) - dst = join(jdk, d) - if not exists(src): - mx.abort('Host JDK directory is missing: ' + src) - shutil.copytree(src, dst) - - # Make a copy of the default VM so that this JDK can be - # reliably used as the bootstrap for a HotSpot build. - jvmCfg = _vmCfgInJdk(jdk) - if not exists(jvmCfg): - mx.abort(jvmCfg + ' does not exist') - - defaultVM = None - jvmCfgLines = [] - with open(jvmCfg) as f: - for line in f: - if line.startswith('-') and defaultVM is None: - parts = line.split() - if len(parts) == 2: - assert parts[1] == 'KNOWN', parts[1] - defaultVM = parts[0][1:] - jvmCfgLines += ['# default VM is a copy of the unmodified ' + defaultVM + ' VM\n'] - jvmCfgLines += ['-original KNOWN\n'] - else: - # skip lines which we cannot parse (e.g. '-hotspot ALIASED_TO -client') - mx.log("WARNING: skipping not parsable line \"" + line + "\"") - else: - jvmCfgLines += [line] - - assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg - if mx.get_os() != 'windows': - chmodRecursive(jdk, 0755) - shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'original')) - - - with open(jvmCfg, 'w') as fp: - for line in jvmCfgLines: - fp.write(line) - - # Install a copy of the disassembler library - try: - hsdis([], copyToDir=_vmLibDirInJdk(jdk)) - except SystemExit: - pass - else: - if not exists(jdk): - if _installed_jdks: - mx.log("The selected JDK directory does not (yet) exist: " + jdk) - _handle_missing_VM(build, vmToCheck if vmToCheck else 'graal') - - if installGraalJar: - _installGraalJarInJdks(mx.distribution('GRAAL')) - - if vmToCheck is not None: - jvmCfg = _vmCfgInJdk(jdk) - found = False - with open(jvmCfg) as f: - for line in f: - if line.strip() == '-' + vmToCheck + ' KNOWN': - found = True - break - if not found: - _handle_missing_VM(build, vmToCheck) - - return jdk - -def _updateInstalledGraalOptionsFile(jdk): - graalOptions = join(_graal_home, 'graal.options') - jreLibDir = join(jdk, 'jre', 'lib') - if exists(graalOptions): - shutil.copy(graalOptions, join(jreLibDir, 'graal.options')) - else: - toDelete = join(jreLibDir, 'graal.options') - if exists(toDelete): - os.unlink(toDelete) - -def _installGraalJarInJdks(graalDist): - graalJar = graalDist.path - jdks = _jdksDir() - if exists(jdks): - for e in os.listdir(jdks): - jreLibDir = join(jdks, e, 'jre', 'lib') - if exists(jreLibDir): - # do a copy and then a move to get atomic updating (on Unix) of graal.jar in the JRE - fd, tmp = tempfile.mkstemp(suffix='', prefix='graal.jar', dir=jreLibDir) - shutil.copyfile(graalJar, tmp) - os.close(fd) - shutil.move(tmp, join(jreLibDir, 'graal.jar')) - -# run a command in the windows SDK Debug Shell -def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None): - if respondTo is None: - respondTo = {} - newLine = os.linesep - startToken = 'RUNINDEBUGSHELL_STARTSEQUENCE' - endToken = 'RUNINDEBUGSHELL_ENDSEQUENCE' - - winSDK = mx.get_env('WIN_SDK', 'C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\') - - if not exists(winSDK): - mx.abort("Could not find Windows SDK : '" + winSDK + "' does not exist") - - if not exists(join(winSDK, 'Bin', 'SetEnv.cmd')): - mx.abort("Invalid Windows SDK path (" + winSDK + ") : could not find Bin/SetEnv.cmd (you can use the WIN_SDK environment variable to specify an other path)") - - p = subprocess.Popen('cmd.exe /E:ON /V:ON /K ""' + winSDK + '/Bin/SetEnv.cmd" & echo ' + startToken + '"', \ - shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP) - stdout = p.stdout - stdin = p.stdin - if logFile: - log = open(logFile, 'w') - ret = False - while True: - - # encoding may be None on windows plattforms - if sys.stdout.encoding is None: - encoding = 'utf-8' - else: - encoding = sys.stdout.encoding - - line = stdout.readline().decode(encoding) - if logFile: - log.write(line.encode('utf-8')) - line = line.strip() - mx.log(line) - if line == startToken: - stdin.write('cd /D ' + workingDir + ' & ' + cmd + ' & echo ' + endToken + newLine) - for regex in respondTo.keys(): - match = regex.search(line) - if match: - stdin.write(respondTo[regex] + newLine) - if findInOutput: - match = findInOutput.search(line) - if match: - ret = True - if line == endToken: - if not findInOutput: - stdin.write('echo ERRXXX%errorlevel%' + newLine) - else: - break - if line.startswith('ERRXXX'): - if line == 'ERRXXX0': - ret = True - break - stdin.write('exit' + newLine) - if logFile: - log.close() - return ret - -def jdkhome(vm=None): - """return the JDK directory selected for the 'vm' command""" - build = _vmbuild if _vmSourcesAvailable else 'product' - return _jdk(build, installGraalJar=False) - -def print_jdkhome(args, vm=None): - """print the JDK directory selected for the 'vm' command""" - print jdkhome(vm) - -def buildvars(args): - """describe the variables that can be set by the -D option to the 'mx build' commmand""" - - buildVars = { - 'ALT_BOOTDIR' : 'The location of the bootstrap JDK installation (default: ' + mx.java().jdk + ')', - 'ALT_OUTPUTDIR' : 'Build directory', - 'HOTSPOT_BUILD_JOBS' : 'Number of CPUs used by make (default: ' + str(multiprocessing.cpu_count()) + ')', - 'INSTALL' : 'Install the built VM into the JDK? (default: y)', - 'ZIP_DEBUGINFO_FILES' : 'Install zipped debug symbols file? (default: 0)', - } - - mx.log('HotSpot build variables that can be set by the -D option to "mx build":') - mx.log('') - for n in sorted(buildVars.iterkeys()): - mx.log(n) - mx.log(textwrap.fill(buildVars[n], initial_indent=' ', subsequent_indent=' ', width=200)) - - mx.log('') - mx.log('Note that these variables can be given persistent values in the file ' + join(_graal_home, 'mx', 'env') + ' (see \'mx about\').') - -def build(args, vm=None): - """build the VM binary - - The global '--vm' and '--vmbuild' options select which VM type and build target to build.""" - - # Override to fail quickly if extra arguments are given - # at the end of the command line. This allows for a more - # helpful error message. - class AP(ArgumentParser): - def __init__(self): - ArgumentParser.__init__(self, prog='mx build') - def parse_args(self, args): - result = ArgumentParser.parse_args(self, args) - if len(result.remainder) != 0: - firstBuildTarget = result.remainder[0] - mx.abort('To specify the ' + firstBuildTarget + ' VM build target, you need to use the global "--vmbuild" option. For example:\n' + - ' mx --vmbuild ' + firstBuildTarget + ' build') - return result - - # Call mx.build to compile the Java sources - parser = AP() - parser.add_argument('--export-dir', help='directory to which graal.jar and graal.options will be copied', metavar='') - parser.add_argument('-D', action='append', help='set a HotSpot build variable (run \'mx buildvars\' to list variables)', metavar='name=value') - opts2 = mx.build(['--source', '1.7'] + args, parser=parser) - assert len(opts2.remainder) == 0 - - if opts2.export_dir is not None: - if not exists(opts2.export_dir): - os.makedirs(opts2.export_dir) - else: - assert os.path.isdir(opts2.export_dir), '{} is not a directory'.format(opts2.export_dir) - - shutil.copy(mx.distribution('GRAAL').path, opts2.export_dir) - graalOptions = join(_graal_home, 'graal.options') - if exists(graalOptions): - shutil.copy(graalOptions, opts2.export_dir) - - if not _vmSourcesAvailable or not opts2.native: - return - - builds = [_vmbuild] - - if vm is None: - vm = _get_vm() - - if vm == 'original': - pass - elif vm.startswith('server'): - buildSuffix = '' - elif vm.startswith('client'): - buildSuffix = '1' - else: - assert vm == 'graal', vm - buildSuffix = 'graal' - - if _installed_jdks and _installed_jdks != _graal_home: - if not mx.ask_yes_no("Warning: building while --installed-jdks is set (" + _installed_jdks + ") is not recommanded - are you sure you want to continue", 'n'): - mx.abort(1) - - for build in builds: - if build == 'ide-build-target': - build = os.environ.get('IDE_BUILD_TARGET', None) - if build is None or len(build) == 0: - continue - - jdk = _jdk(build, create=True) - - if vm == 'original': - if build != 'product': - mx.log('only product build of original VM exists') - continue - - vmDir = join(_vmLibDirInJdk(jdk), vm) - if not exists(vmDir): - if mx.get_os() != 'windows': - chmodRecursive(jdk, 0755) - mx.log('Creating VM directory in JDK7: ' + vmDir) - os.makedirs(vmDir) - - def filterXusage(line): - if not 'Xusage.txt' in line: - sys.stderr.write(line + os.linesep) - - # Check if a build really needs to be done - timestampFile = join(vmDir, '.build-timestamp') - if opts2.force or not exists(timestampFile): - mustBuild = True - else: - mustBuild = False - timestamp = os.path.getmtime(timestampFile) - sources = [] - for d in ['src', 'make']: - for root, dirnames, files in os.walk(join(_graal_home, d)): - # ignore /src/share/tools - if root == join(_graal_home, 'src', 'share'): - dirnames.remove('tools') - sources += [join(root, name) for name in files] - for f in sources: - if len(f) != 0 and os.path.getmtime(f) > timestamp: - mustBuild = True - break - - if not mustBuild: - mx.logv('[all files in src and make directories are older than ' + timestampFile[len(_graal_home) + 1:] + ' - skipping native build]') - continue - - if platform.system() == 'Windows': - compilelogfile = _graal_home + '/graalCompile.log' - mksHome = mx.get_env('MKS_HOME', 'C:\\cygwin\\bin') - - variant = {'client': 'compiler1', 'server': 'compiler2'}.get(vm, vm) - project_config = variant + '_' + build - _runInDebugShell('msbuild ' + _graal_home + r'\build\vs-amd64\jvm.vcproj /p:Configuration=' + project_config + ' /target:clean', _graal_home) - winCompileCmd = r'set HotSpotMksHome=' + mksHome + r'& set OUT_DIR=' + jdk + r'& set JAVA_HOME=' + jdk + r'& set path=%JAVA_HOME%\bin;%path%;%HotSpotMksHome%& cd /D "' + _graal_home + r'\make\windows"& call create.bat ' + _graal_home - print(winCompileCmd) - winCompileSuccess = re.compile(r"^Writing \.vcxproj file:") - if not _runInDebugShell(winCompileCmd, _graal_home, compilelogfile, winCompileSuccess): - mx.log('Error executing create command') - return - winBuildCmd = 'msbuild ' + _graal_home + r'\build\vs-amd64\jvm.vcxproj /p:Configuration=' + project_config + ' /p:Platform=x64' - if not _runInDebugShell(winBuildCmd, _graal_home, compilelogfile): - mx.log('Error building project') - return - else: - cpus = multiprocessing.cpu_count() - runCmd = [mx.gmake_cmd()] - runCmd.append(build + buildSuffix) - env = os.environ.copy() - - if opts2.D: - for nv in opts2.D: - name, value = nv.split('=', 1) - env[name.strip()] = value - - env.setdefault('ARCH_DATA_MODEL', '64') - env.setdefault('LANG', 'C') - env.setdefault('HOTSPOT_BUILD_JOBS', str(cpus)) - env.setdefault('ALT_BOOTDIR', mx.java().jdk) - if not mx._opts.verbose: - runCmd.append('MAKE_VERBOSE=') - env['JAVA_HOME'] = jdk - if vm.endswith('nograal'): - env['INCLUDE_GRAAL'] = 'false' - env.setdefault('ALT_OUTPUTDIR', join(_graal_home, 'build-nograal', mx.get_os())) - else: - env['INCLUDE_GRAAL'] = 'true' - env.setdefault('INSTALL', 'y') - if mx.get_os() == 'solaris' : - # If using sparcWorks, setup flags to avoid make complaining about CC version - cCompilerVersion = subprocess.Popen('CC -V', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).stderr.readlines()[0] - if cCompilerVersion.startswith('CC: Sun C++') : - compilerRev = cCompilerVersion.split(' ')[3] - env.setdefault('ENFORCE_COMPILER_REV', compilerRev) - env.setdefault('ENFORCE_CC_COMPILER_REV', compilerRev) - if build == 'jvmg': - # I want ALL the symbols when I'm debugging on Solaris - # Some Makefile variable are overloaded by environment variable so we need to explicitely - # pass them down in the command line. This one is an example of that. - runCmd.append('STRIP_POLICY=no_strip') - # This removes the need to unzip the *.diz files before debugging in gdb - env.setdefault('ZIP_DEBUGINFO_FILES', '0') - - # Clear these 2 variables as having them set can cause very confusing build problems - env.pop('LD_LIBRARY_PATH', None) - env.pop('CLASSPATH', None) - - mx.run(runCmd, cwd=join(_graal_home, 'make'), err=filterXusage, env=env) - - jvmCfg = _vmCfgInJdk(jdk) - if not exists(jvmCfg): - mx.abort(jvmCfg + ' does not exist') - - prefix = '-' + vm + ' ' - vmKnown = prefix + 'KNOWN\n' - lines = [] - found = False - with open(jvmCfg) as f: - for line in f: - if line.strip() == vmKnown.strip(): - found = True - lines.append(line) - - if not found: - mx.log('Appending "' + prefix + 'KNOWN" to ' + jvmCfg) - if mx.get_os() != 'windows': - os.chmod(jvmCfg, 0755) - with open(jvmCfg, 'w') as f: - for line in lines: - if line.startswith(prefix): - line = vmKnown - found = True - f.write(line) - if not found: - f.write(vmKnown) - - if exists(timestampFile): - os.utime(timestampFile, None) - else: - file(timestampFile, 'a') - -def vmg(args): - """run the debug build of VM selected by the '--vm' option""" - return vm(args, vmbuild='debug') - -def vmfg(args): - """run the fastdebug build of VM selected by the '--vm' option""" - return vm(args, vmbuild='fastdebug') - -def vm(args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, vmbuild=None): - """run the VM selected by the '--vm' option""" - - if vm is None: - vm = _get_vm() - - if cwd is None: - cwd = _vm_cwd - elif _vm_cwd is not None and _vm_cwd != cwd: - mx.abort("conflicting working directories: do not set --vmcwd for this command") - - build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product' - jdk = _jdk(build, vmToCheck=vm, installGraalJar=False) - _updateInstalledGraalOptionsFile(jdk) - mx.expand_project_in_args(args) - if _make_eclipse_launch: - mx.make_eclipse_launch(args, 'graal-' + build, name=None, deps=mx.project('com.oracle.graal.hotspot').all_deps([], True)) - if len([a for a in args if 'PrintAssembly' in a]) != 0: - hsdis([], copyToDir=_vmLibDirInJdk(jdk)) - if mx.java().debug_port is not None: - args = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(mx.java().debug_port)] + args - if _jacoco == 'on' or _jacoco == 'append': - jacocoagent = mx.library("JACOCOAGENT", True) - # Exclude all compiler tests and snippets - excludes = ['com.oracle.graal.compiler.tests.*', 'com.oracle.graal.jtt.*'] - for p in mx.projects(): - excludes += _find_classes_with_annotations(p, None, ['@Snippet', '@ClassSubstitution', '@Test'], includeInnerClasses=True).keys() - excludes += p.find_classes_with_matching_source_line(None, lambda line: 'JaCoCo Exclude' in line, includeInnerClasses=True).keys() - - includes = ['com.oracle.graal.*'] - agentOptions = { - 'append' : 'true' if _jacoco == 'append' else 'false', - 'bootclasspath' : 'true', - 'includes' : ':'.join(includes), - 'excludes' : ':'.join(excludes), - 'destfile' : 'jacoco.exec' - } - args = ['-javaagent:' + jacocoagent.get_path(True) + '=' + ','.join([k + '=' + v for k, v in agentOptions.items()])] + args - if '-d64' not in args: - args = ['-d64'] + args - - exe = join(jdk, 'bin', mx.exe_suffix('java')) - pfx = _vm_prefix.split() if _vm_prefix is not None else [] - - if '-version' in args: - ignoredArgs = args[args.index('-version') + 1:] - if len(ignoredArgs) > 0: - mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs)) - - return mx.run(pfx + [exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout) - -def _find_classes_with_annotations(p, pkgRoot, annotations, includeInnerClasses=False): - """ - Scan the sources of project 'p' for Java source files containing a line starting with 'annotation' - (ignoring preceding whitespace) and return the fully qualified class name for each Java - source file matched in a list. - """ - - matches = lambda line : len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0 - return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses) - -def _extract_VM_args(args, allowClasspath=False, useDoubleDash=False): - """ - Partitions a command line into a leading sequence of HotSpot VM options and the rest. - """ - for i in range(0, len(args)): - if useDoubleDash: - if args[i] == '--': - vmArgs = args[:i] - remainder = args[i + 1:] - return vmArgs, remainder - else: - if not args[i].startswith('-'): - if i != 0 and (args[i - 1] == '-cp' or args[i - 1] == '-classpath'): - if not allowClasspath: - mx.abort('Cannot supply explicit class path option') - else: - continue - vmArgs = args[:i] - remainder = args[i:] - return vmArgs, remainder - - return args, [] - -def _run_tests(args, harness, annotations, testfile): - - - vmArgs, tests = _extract_VM_args(args) - for t in tests: - if t.startswith('-'): - mx.abort('VM option ' + t + ' must precede ' + tests[0]) - - candidates = [] - for p in mx.projects_opt_limit_to_suites(): - if mx.java().javaCompliance < p.javaCompliance: - continue - candidates += _find_classes_with_annotations(p, None, annotations).keys() - - classes = [] - if len(tests) == 0: - classes = candidates - else: - for t in tests: - found = False - for c in candidates: - if t in c: - found = True - classes.append(c) - if not found: - mx.log('warning: no tests matched by substring "' + t) - - projectscp = mx.classpath([pcp.name for pcp in mx.projects_opt_limit_to_suites() if pcp.javaCompliance <= mx.java().javaCompliance]) - - if len(classes) != 0: - f_testfile = open(testfile, 'w') - for c in classes: - f_testfile.write(c + '\n') - f_testfile.close() - harness(projectscp, vmArgs) - -def _unittest(args, annotations): - mxdir = dirname(__file__) - name = 'JUnitWrapper' - javaSource = join(mxdir, name + '.java') - javaClass = join(mxdir, name + '.class') - testfile = os.environ.get('MX_TESTFILE', None) - if testfile is None: - (_, testfile) = tempfile.mkstemp(".testclasses", "graal") - os.close(_) - - def harness(projectscp, vmArgs): - if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource): - subprocess.check_call([mx.java().javac, '-cp', projectscp, '-d', mxdir, javaSource]) - if _get_vm() != 'graal': - prefixArgs = ['-esa', '-ea'] - else: - prefixArgs = ['-XX:-BootstrapGraal', '-esa', '-ea'] - with open(testfile) as fp: - testclasses = [l.rstrip() for l in fp.readlines()] - if len(testclasses) == 1: - # Execute Junit directly when one test is being run. This simplifies - # replaying the VM execution in a native debugger (e.g., gdb). - vm(prefixArgs + vmArgs + ['-cp', projectscp, 'org.junit.runner.JUnitCore'] + testclasses) - else: - vm(prefixArgs + vmArgs + ['-cp', projectscp + os.pathsep + mxdir, name] + [testfile]) - - try: - _run_tests(args, harness, annotations, testfile) - finally: - if os.environ.get('MX_TESTFILE') is None: - os.remove(testfile) - -_unittestHelpSuffix = """ - - If filters are supplied, only tests whose fully qualified name - includes a filter as a substring are run. - - For example, this command line: - - mx unittest -G:Dump= -G:MethodFilter=BC_aload.* -G:+PrintCFG BC_aload - - will run all JUnit test classes that contain 'BC_aload' in their - fully qualified name and will pass these options to the VM: - - -G:Dump= -G:MethodFilter=BC_aload.* -G:+PrintCFG - - To get around command line length limitations on some OSes, the - JUnit class names to be executed are written to a file that a - custom JUnit wrapper reads and passes onto JUnit proper. The - MX_TESTFILE environment variable can be set to specify a - file which will not be deleted once the unittests are done - (unlike the temporary file otherwise used). - - As with all other commands, using the global '-v' before 'unittest' - command will cause mx to show the complete command line - it uses to run the VM. -""" - -def unittest(args): - """run the JUnit tests (all testcases){0}""" - - _unittest(args, ['@Test', '@LongTest', '@Parameters']) - -def shortunittest(args): - """run the JUnit tests (short testcases only){0}""" - - _unittest(args, ['@Test']) - -def longunittest(args): - """run the JUnit tests (long testcases only){0}""" - - _unittest(args, ['@LongTest', '@Parameters']) - -def buildvms(args): - """build one or more VMs in various configurations""" - - vmsDefault = ','.join(_vmChoices.keys()) - vmbuildsDefault = ','.join(_vmbuildChoices) - - parser = ArgumentParser(prog='mx buildvms') - parser.add_argument('--vms', help='a comma separated list of VMs to build (default: ' + vmsDefault + ')', metavar='', default=vmsDefault) - parser.add_argument('--builds', help='a comma separated list of build types (default: ' + vmbuildsDefault + ')', metavar='', default=vmbuildsDefault) - parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build') - parser.add_argument('-c', '--console', action='store_true', help='send build output to console instead of log file') - - args = parser.parse_args(args) - vms = args.vms.split(',') - builds = args.builds.split(',') - - allStart = time.time() - for v in vms: - for vmbuild in builds: - if v == 'original' and vmbuild != 'product': - continue - if not args.console: - logFile = join(v + '-' + vmbuild + '.log') - log = open(join(_graal_home, logFile), 'wb') - start = time.time() - mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')') - # Run as subprocess so that output can be directed to a file - subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, '--vmbuild', - vmbuild, 'build'], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT) - duration = datetime.timedelta(seconds=time.time() - start) - mx.log('END: ' + v + '-' + vmbuild + '\t[' + str(duration) + ']') - else: - with VM(v, vmbuild): - build([]) - if not args.no_check: - vmargs = ['-version'] - if v == 'graal': - vmargs.insert(0, '-XX:-BootstrapGraal') - vm(vmargs, vm=v, vmbuild=vmbuild) - allDuration = datetime.timedelta(seconds=time.time() - allStart) - mx.log('TOTAL TIME: ' + '[' + str(allDuration) + ']') - -class Task: - def __init__(self, title): - self.start = time.time() - self.title = title - self.end = None - self.duration = None - mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: BEGIN: ') + title) - def stop(self): - self.end = time.time() - self.duration = datetime.timedelta(seconds=self.end - self.start) - mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: END: ') + self.title + ' [' + str(self.duration) + ']') - return self - def abort(self, codeOrMessage): - self.end = time.time() - self.duration = datetime.timedelta(seconds=self.end - self.start) - mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(self.duration) + ']') - mx.abort(codeOrMessage) - return self - -def _basic_gate_body(args, tasks): - t = Task('BuildHotSpotGraal: fastdebug,product') - buildvms(['--vms', 'graal,server', '--builds', 'fastdebug,product']) - tasks.append(t.stop()) - - with VM('graal', 'fastdebug'): - t = Task('BootstrapWithSystemAssertions:fastdebug') - vm(['-esa', '-version']) - tasks.append(t.stop()) - - with VM('graal', 'product'): - t = Task('BootstrapWithGCVerification:product') - out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write - vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) - tasks.append(t.stop()) - - with VM('graal', 'product'): - t = Task('BootstrapWithG1GCVerification:product') - out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write - vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) - tasks.append(t.stop()) - - with VM('graal', 'product'): - t = Task('BootstrapWithRegisterPressure:product') - vm(['-G:RegisterPressure=rbx,r11,r10,r14,xmm3,xmm11,xmm14', '-esa', '-version']) - tasks.append(t.stop()) - - with VM('graal', 'product'): - t = Task('BootstrapWithAOTConfiguration:product') - vm(['-G:+AOTCompilation', '-G:+VerifyPhases', '-esa', '-version']) - tasks.append(t.stop()) - - with VM('server', 'product'): # hosted mode - t = Task('UnitTests:hosted-product') - unittest([]) - tasks.append(t.stop()) - - for vmbuild in ['fastdebug', 'product']: - for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild): - t = Task(str(test) + ':' + vmbuild) - if not test.test('graal'): - t.abort(test.name + ' Failed') - tasks.append(t.stop()) - - if args.jacocout is not None: - jacocoreport([args.jacocout]) - - global _jacoco - _jacoco = 'off' - - t = Task('CleanAndBuildIdealGraphVisualizer') - mx.run(['ant', '-f', join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'), '-q', 'clean', 'build']) - tasks.append(t.stop()) - - # Prevent Graal modifications from breaking the standard builds - if args.buildNonGraal: - t = Task('BuildHotSpotVarieties') - buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product']) - buildvms(['--vms', 'server-nograal', '--builds', 'product']) - buildvms(['--vms', 'server-nograal', '--builds', 'optimized']) - tasks.append(t.stop()) - - for vmbuild in ['product', 'fastdebug']: - for theVm in ['client', 'server']: - with VM(theVm, vmbuild): - t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild) - dacapo(['pmd']) - tasks.append(t.stop()) - - t = Task('UnitTests:' + theVm + ':' + vmbuild) - unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api']) - tasks.append(t.stop()) - - -def gate(args, gate_body=_basic_gate_body): - """run the tests used to validate a push - - If this command exits with a 0 exit code, then the source code is in - a state that would be accepted for integration into the main repository.""" - - parser = ArgumentParser(prog='mx gate') - parser.add_argument('-j', '--omit-java-clean', action='store_false', dest='cleanJava', help='omit cleaning Java native code') - parser.add_argument('-n', '--omit-native-clean', action='store_false', dest='cleanNative', help='omit cleaning and building native code') - parser.add_argument('-g', '--only-build-graalvm', action='store_false', dest='buildNonGraal', help='only build the Graal VM') - parser.add_argument('--jacocout', help='specify the output directory for jacoco report') - - args = parser.parse_args(args) - - global _jacoco - - tasks = [] - total = Task('Gate') - try: - - t = Task('Pylint') - mx.pylint([]) - tasks.append(t.stop()) - - t = Task('Clean') - cleanArgs = [] - if not args.cleanNative: - cleanArgs.append('--no-native') - if not args.cleanJava: - cleanArgs.append('--no-java') - clean(cleanArgs) - tasks.append(t.stop()) - - t = Task('IDEConfigCheck') - mx.ideclean([]) - mx.ideinit([]) - tasks.append(t.stop()) - - eclipse_exe = os.environ.get('ECLIPSE_EXE') - if eclipse_exe is not None: - t = Task('CodeFormatCheck') - if mx.eclipseformat(['-e', eclipse_exe]) != 0: - t.abort('Formatter modified files - run "mx eclipseformat", check in changes and repush') - tasks.append(t.stop()) - - t = Task('Canonicalization Check') - mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...')) - if mx.canonicalizeprojects([]) != 0: - t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.') - tasks.append(t.stop()) - - t = Task('BuildJava') - build(['--no-native', '--jdt-warning-as-error']) - tasks.append(t.stop()) - - t = Task('Checkstyle') - if mx.checkstyle([]) != 0: - t.abort('Checkstyle warnings were found') - tasks.append(t.stop()) - - if exists('jacoco.exec'): - os.unlink('jacoco.exec') - - if args.jacocout is not None: - _jacoco = 'append' - else: - _jacoco = 'off' - - gate_body(args, tasks) - - except KeyboardInterrupt: - total.abort(1) - - except BaseException as e: - import traceback - traceback.print_exc() - total.abort(str(e)) - - total.stop() - - mx.log('Gate task times:') - for t in tasks: - mx.log(' ' + str(t.duration) + '\t' + t.title) - mx.log(' =======') - mx.log(' ' + str(total.duration)) - -def deoptalot(args): - """bootstrap a fastdebug Graal VM with DeoptimizeALot and VerifyOops on - - If the first argument is a number, the process will be repeated - this number of times. All other arguments are passed to the VM.""" - count = 1 - if len(args) > 0 and args[0].isdigit(): - count = int(args[0]) - del args[0] - - for _ in range(count): - if not vm(['-XX:+DeoptimizeALot', '-XX:+VerifyOops'] + args + ['-version'], vmbuild='fastdebug') == 0: - mx.abort("Failed") - -def longtests(args): - - deoptalot(['15', '-Xmx48m']) - - dacapo(['100', 'eclipse', '-esa']) - -def gv(args): - """run the Graal Visualizer""" - with open(join(_graal_home, '.graal_visualizer.log'), 'w') as fp: - mx.logv('[Graal Visualizer log is in ' + fp.name + ']') - if not exists(join(_graal_home, 'visualizer', 'build.xml')): - mx.logv('[This initial execution may take a while as the NetBeans platform needs to be downloaded]') - mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-l', fp.name, 'run']) - -def igv(args): - """run the Ideal Graph Visualizer""" - with open(join(_graal_home, '.ideal_graph_visualizer.log'), 'w') as fp: - mx.logv('[Ideal Graph Visualizer log is in ' + fp.name + ']') - if not exists(join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'nbplatform')): - mx.logv('[This initial execution may take a while as the NetBeans platform needs to be downloaded]') - mx.run(['ant', '-f', join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'), '-l', fp.name, 'run']) - -def bench(args): - """run benchmarks and parse their output for results - - Results are JSON formated : {group : {benchmark : score}}.""" - resultFile = None - if '-resultfile' in args: - index = args.index('-resultfile') - if index + 1 < len(args): - resultFile = args[index + 1] - del args[index] - del args[index] - else: - mx.abort('-resultfile must be followed by a file name') - vm = _get_vm() - if len(args) is 0: - args = ['all'] - - vmArgs = [arg for arg in args if arg.startswith('-')] - - def benchmarks_in_group(group): - prefix = group + ':' - return [a[len(prefix):] for a in args if a.startswith(prefix)] - - results = {} - benchmarks = [] - # DaCapo - if ('dacapo' in args or 'all' in args): - benchmarks += sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Benchmark) - else: - dacapos = benchmarks_in_group('dacapo') - for dacapo in dacapos: - if dacapo not in sanitycheck.dacapoSanityWarmup.keys(): - mx.abort('Unknown DaCapo : ' + dacapo) - iterations = sanitycheck.dacapoSanityWarmup[dacapo][sanitycheck.SanityCheckLevel.Benchmark] - if (iterations > 0): - benchmarks += [sanitycheck.getDacapo(dacapo, iterations)] - - if ('scaladacapo' in args or 'all' in args): - benchmarks += sanitycheck.getScalaDacapos(level=sanitycheck.SanityCheckLevel.Benchmark) - else: - scaladacapos = benchmarks_in_group('scaladacapo') - for scaladacapo in scaladacapos: - if scaladacapo not in sanitycheck.dacapoScalaSanityWarmup.keys(): - mx.abort('Unknown Scala DaCapo : ' + scaladacapo) - iterations = sanitycheck.dacapoScalaSanityWarmup[scaladacapo][sanitycheck.SanityCheckLevel.Benchmark] - if (iterations > 0): - benchmarks += [sanitycheck.getScalaDacapo(scaladacapo, ['-n', str(iterations)])] - - # Bootstrap - if ('bootstrap' in args or 'all' in args): - benchmarks += sanitycheck.getBootstraps() - # SPECjvm2008 - if ('specjvm2008' in args or 'all' in args): - benchmarks += [sanitycheck.getSPECjvm2008(['-ikv', '-wt', '120', '-it', '120'])] - else: - specjvms = benchmarks_in_group('specjvm2008') - for specjvm in specjvms: - benchmarks += [sanitycheck.getSPECjvm2008(['-ikv', '-wt', '120', '-it', '120', specjvm])] - - if ('specjbb2005' in args or 'all' in args): - benchmarks += [sanitycheck.getSPECjbb2005()] - - if ('specjbb2013' in args): # or 'all' in args //currently not in default set - benchmarks += [sanitycheck.getSPECjbb2013()] - - if ('ctw-full' in args): - benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.Full)) - if ('ctw-noinline' in args): - benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.NoInline)) - if ('ctw-nocomplex' in args): - benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.NoComplex)) - - for test in benchmarks: - for (groupName, res) in test.bench(vm, extraVmOpts=vmArgs).items(): - group = results.setdefault(groupName, {}) - group.update(res) - mx.log(json.dumps(results)) - if resultFile: - with open(resultFile, 'w') as f: - f.write(json.dumps(results)) - -def specjvm2008(args): - """run one or more SPECjvm2008 benchmarks""" - - def launcher(bm, harnessArgs, extraVmOpts): - return sanitycheck.getSPECjvm2008(harnessArgs + [bm]).bench(_get_vm(), extraVmOpts=extraVmOpts) - - availableBenchmarks = set(sanitycheck.specjvm2008Names) - for name in sanitycheck.specjvm2008Names: - parts = name.rsplit('.', 1) - if len(parts) > 1: - assert len(parts) == 2 - group = parts[0] - availableBenchmarks.add(group) - - _run_benchmark(args, sorted(availableBenchmarks), launcher) - -def specjbb2013(args): - """runs the composite SPECjbb2013 benchmark""" - - def launcher(bm, harnessArgs, extraVmOpts): - assert bm is None - return sanitycheck.getSPECjbb2013(harnessArgs).bench(_get_vm(), extraVmOpts=extraVmOpts) - - _run_benchmark(args, None, launcher) - -def specjbb2005(args): - """runs the composite SPECjbb2005 benchmark""" - - def launcher(bm, harnessArgs, extraVmOpts): - assert bm is None - return sanitycheck.getSPECjbb2005(harnessArgs).bench(_get_vm(), extraVmOpts=extraVmOpts) - - _run_benchmark(args, None, launcher) - -def hsdis(args, copyToDir=None): - """download the hsdis library - - This is needed to support HotSpot's assembly dumping features. - By default it downloads the Intel syntax version, use the 'att' argument to install AT&T syntax.""" - flavor = 'intel' - if 'att' in args: - flavor = 'att' - lib = mx.add_lib_suffix('hsdis-' + _arch()) - path = join(_graal_home, 'lib', lib) - if not exists(path): - mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hsdis/' + flavor + "/" + lib]) - if copyToDir is not None and exists(copyToDir): - shutil.copy(path, copyToDir) - -def hcfdis(args): - """disassemble HexCodeFiles embedded in text files - - Run a tool over the input files to convert all embedded HexCodeFiles - to a disassembled format.""" - - parser = ArgumentParser(prog='mx hcfdis') - parser.add_argument('-m', '--map', help='address to symbol map applied to disassembler output') - parser.add_argument('files', nargs=REMAINDER, metavar='files...') - - args = parser.parse_args(args) - - path = join(_graal_home, 'lib', 'hcfdis-1.jar') - if not exists(path): - mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hcfdis-1.jar']) - mx.run_java(['-jar', path] + args.files) - - if args.map is not None: - addressRE = re.compile(r'0[xX]([A-Fa-f0-9]+)') - with open(args.map) as fp: - lines = fp.read().splitlines() - symbols = dict() - for l in lines: - addressAndSymbol = l.split(' ', 1) - if len(addressAndSymbol) == 2: - address, symbol = addressAndSymbol - if address.startswith('0x'): - address = long(address, 16) - symbols[address] = symbol - for f in args.files: - with open(f) as fp: - lines = fp.read().splitlines() - updated = False - for i in range(0, len(lines)): - l = lines[i] - for m in addressRE.finditer(l): - sval = m.group(0) - val = long(sval, 16) - sym = symbols.get(val) - if sym: - l = l.replace(sval, sym) - updated = True - lines[i] = l - if updated: - mx.log('updating ' + f) - with open('new_' + f, "w") as fp: - for l in lines: - print >> fp, l - -def jacocoreport(args): - """create a JaCoCo coverage report - - Creates the report from the 'jacoco.exec' file in the current directory. - Default output directory is 'coverage', but an alternative can be provided as an argument.""" - jacocoreport = mx.library("JACOCOREPORT", True) - out = 'coverage' - if len(args) == 1: - out = args[0] - elif len(args) > 1: - mx.abort('jacocoreport takes only one argument : an output directory') - mx.run_java(['-jar', jacocoreport.get_path(True), '-in', 'jacoco.exec', '-g', join(_graal_home, 'graal'), out]) - -def sl(args): - """run an SL program""" - vmArgs, slArgs = _extract_VM_args(args) - vm(vmArgs + ['-cp', mx.classpath("com.oracle.truffle.sl"), "com.oracle.truffle.sl.SimpleLanguage"] + slArgs) - -def isGraalEnabled(vm): - return vm != 'original' and not vm.endswith('nograal') - -def site(args): - """create a website containing javadoc and the project dependency graph""" - - return mx.site(['--name', 'Graal', - '--jd', '@-tag', '--jd', '@test:X', - '--jd', '@-tag', '--jd', '@run:X', - '--jd', '@-tag', '--jd', '@bug:X', - '--jd', '@-tag', '--jd', '@summary:X', - '--jd', '@-tag', '--jd', '@vmoption:X', - '--overview', join(_graal_home, 'graal', 'overview.html'), - '--title', 'Graal OpenJDK Project Documentation', - '--dot-output-base', 'projects'] + args) - -def mx_init(suite): - commands = { - 'build': [build, ''], - 'buildvars': [buildvars, ''], - 'buildvms': [buildvms, '[-options]'], - 'clean': [clean, ''], - 'hsdis': [hsdis, '[att]'], - 'hcfdis': [hcfdis, ''], - 'igv' : [igv, ''], - 'jdkhome': [print_jdkhome, ''], - 'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'], - 'scaladacapo': [scaladacapo, '[VM options] benchmarks...|"all" [Scala DaCapo options]'], - 'specjvm2008': [specjvm2008, '[VM options] benchmarks...|"all" [SPECjvm2008 options]'], - 'specjbb2013': [specjbb2013, '[VM options] [-- [SPECjbb2013 options]]'], - 'specjbb2005': [specjbb2005, '[VM options] [-- [SPECjbb2005 options]]'], - 'gate' : [gate, '[-options]'], - 'gv' : [gv, ''], - 'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'], - 'unittest' : [unittest, '[VM options] [filters...]', _unittestHelpSuffix], - 'longunittest' : [longunittest, '[VM options] [filters...]', _unittestHelpSuffix], - 'shortunittest' : [shortunittest, '[VM options] [filters...]', _unittestHelpSuffix], - 'jacocoreport' : [jacocoreport, '[output directory]'], - 'site' : [site, '[-options]'], - 'vm': [vm, '[-options] class [args...]'], - 'vmg': [vmg, '[-options] class [args...]'], - 'vmfg': [vmfg, '[-options] class [args...]'], - 'deoptalot' : [deoptalot, '[n]'], - 'longtests' : [longtests, ''], - 'sl' : [sl, '[SL args|@VM options]'] - } - - mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append']) - mx.add_argument('--vmcwd', dest='vm_cwd', help='current directory will be changed to before the VM is executed', default=None, metavar='') - mx.add_argument('--installed-jdks', help='the base directory in which the JDKs cloned from $JAVA_HOME exist. ' + - 'The VM selected by --vm and --vmbuild options is under this directory (i.e., ' + - join('', '', '', 'jre', 'lib', '', mx.add_lib_prefix(mx.add_lib_suffix('jvm'))) + ')', default=None, metavar='') - - if (_vmSourcesAvailable): - mx.add_argument('--vm', action='store', dest='vm', choices=_vmChoices.keys(), help='the VM type to build/run') - mx.add_argument('--vmbuild', action='store', dest='vmbuild', choices=_vmbuildChoices, help='the VM build to build/run (default: ' + _vmbuildChoices[0] + ')') - mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse') - mx.add_argument('--vmprefix', action='store', dest='vm_prefix', help='prefix for running the VM (e.g. "/usr/bin/gdb --args")', metavar='') - mx.add_argument('--gdb', action='store_const', const='/usr/bin/gdb --args', dest='vm_prefix', help='alias for --vmprefix "/usr/bin/gdb --args"') - - commands.update({ - 'export': [export, '[-options] [zipfile]'], - }) - - mx.update_commands(suite, commands) - -def mx_post_parse_cmd_line(opts): # - # TODO _minVersion check could probably be part of a Suite in mx? - if (mx.java().version < _minVersion) : - mx.abort('Requires Java version ' + str(_minVersion) + ' or greater, got version ' + str(mx.java().version)) - - if (_vmSourcesAvailable): - if hasattr(opts, 'vm') and opts.vm is not None: - global _vm - _vm = opts.vm - if hasattr(opts, 'vmbuild') and opts.vmbuild is not None: - global _vmbuild - _vmbuild = opts.vmbuild - global _make_eclipse_launch - _make_eclipse_launch = getattr(opts, 'make_eclipse_launch', False) - global _jacoco - _jacoco = opts.jacoco - global _vm_cwd - _vm_cwd = opts.vm_cwd - global _installed_jdks - _installed_jdks = opts.installed_jdks - global _vm_prefix - _vm_prefix = opts.vm_prefix - - mx.distribution('GRAAL').add_update_listener(_installGraalJarInJdks) diff -r bff24aae4640 -r 6cdf3b17316d mx/mx_graal.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mx/mx_graal.py Tue Nov 12 19:39:25 2013 -0800 @@ -0,0 +1,1427 @@ +# +# commands.py - the GraalVM specific commands +# +# ---------------------------------------------------------------------------------------------------- +# +# Copyright (c) 2007, 2012, 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. +# +# ---------------------------------------------------------------------------------------------------- + +import os, sys, shutil, zipfile, tempfile, re, time, datetime, platform, subprocess, multiprocessing +from os.path import join, exists, dirname, basename, getmtime +from argparse import ArgumentParser, REMAINDER +import mx +import sanitycheck +import itertools +import json, textwrap + +# This works because when mx loads this file, it makes sure __file__ gets an absolute path +_graal_home = dirname(dirname(__file__)) + +""" Used to distinguish an exported GraalVM (see 'mx export'). """ +_vmSourcesAvailable = exists(join(_graal_home, 'make')) and exists(join(_graal_home, 'src')) + +""" The VMs that can be built and run along with an optional description. Only VMs with a + description are listed in the dialogue for setting the default VM (see _get_vm()). """ +_vmChoices = { + 'graal' : 'All compilation is performed with Graal. This includes bootstrapping Graal itself unless -XX:-BootstrapGraal is used.', + 'server' : 'Normal compilation is performed with the tiered system (i.e., client + server), Truffle compilation is performed with Graal. Use this for optimal Truffle performance.', + 'client' : None, # normal compilation with client compiler, explicit compilation (e.g., by Truffle) with Graal + 'server-nograal' : None, # all compilation with tiered system (i.e., client + server), Graal omitted + 'client-nograal' : None, # all compilation with client compiler, Graal omitted + 'original' : None, # default VM copied from bootstrap JDK +} + +""" The VM that will be run by the 'vm' command and built by default by the 'build' command. + This can be set via the global '--vm' option or the DEFAULT_VM environment variable. + It can also be temporarily set by using of a VM context manager object in a 'with' statement. """ +_vm = None + +""" The VM builds that will be run by the 'vm' command - default is first in list """ +_vmbuildChoices = ['product', 'fastdebug', 'debug', 'optimized'] + +""" The VM build that will be run by the 'vm' command. + This can be set via the global '--vmbuild' option. + It can also be temporarily set by using of a VM context manager object in a 'with' statement. """ +_vmbuild = _vmbuildChoices[0] + +_jacoco = 'off' + +""" The current working directory to switch to before running the VM. """ +_vm_cwd = None + +""" The base directory in which the JDKs cloned from $JAVA_HOME exist. """ +_installed_jdks = None + +""" Prefix for running the VM. """ +_vm_prefix = None + +_make_eclipse_launch = False + +_minVersion = mx.JavaVersion('1.7.0_04') + +def _get_vm(): + """ + Gets the configured VM, presenting a dialogue if there is no currently configured VM. + """ + global _vm + if _vm: + return _vm + vm = mx.get_env('DEFAULT_VM') + if vm is None: + if not sys.stdout.isatty(): + mx.abort('Need to specify VM with --vm option or DEFAULT_VM environment variable') + envPath = join(_graal_home, 'mx', 'env') + mx.log('Please select the VM to be executed from the following: ') + items = [k for k in _vmChoices.keys() if _vmChoices[k] is not None] + descriptions = [_vmChoices[k] for k in _vmChoices.keys() if _vmChoices[k] is not None] + vm = mx.select_items(items, descriptions, allowMultiple=False) + if mx.ask_yes_no('Persist this choice by adding "DEFAULT_VM=' + vm + '" to ' + envPath, 'y'): + with open(envPath, 'a') as fp: + print >> fp, 'DEFAULT_VM=' + vm + _vm = vm + return vm + +""" +A context manager that can be used with the 'with' statement to set the VM +used by all VM executions within the scope of the 'with' statement. For example: + + with VM('server'): + dacapo(['pmd']) +""" +class VM: + def __init__(self, vm=None, build=None): + assert vm is None or vm in _vmChoices.keys() + assert build is None or build in _vmbuildChoices + self.vm = vm if vm else _vm + self.build = build if build else _vmbuild + self.previousVm = _vm + self.previousBuild = _vmbuild + + def __enter__(self): + global _vm, _vmbuild + _vm = self.vm + _vmbuild = self.build + + def __exit__(self, exc_type, exc_value, traceback): + global _vm, _vmbuild + _vm = self.previousVm + _vmbuild = self.previousBuild + +def _chmodDir(chmodFlags, dirname, fnames): + os.chmod(dirname, chmodFlags) + for name in fnames: + os.chmod(os.path.join(dirname, name), chmodFlags) + +def chmodRecursive(dirname, chmodFlags): + os.path.walk(dirname, _chmodDir, chmodFlags) + +def clean(args): + """clean the GraalVM source tree""" + opts = mx.clean(args, parser=ArgumentParser(prog='mx clean')) + if opts.native: + def rmIfExists(name): + if os.path.isdir(name): + shutil.rmtree(name) + elif os.path.isfile(name): + os.unlink(name) + + rmIfExists(join(_graal_home, 'build')) + rmIfExists(join(_graal_home, 'build-nograal')) + rmIfExists(_jdksDir()) + rmIfExists(mx.distribution('GRAAL').path) + +def export(args): + """create a GraalVM zip file for distribution""" + + parser = ArgumentParser(prog='mx export') + parser.add_argument('--omit-vm-build', action='store_false', dest='vmbuild', help='omit VM build step') + parser.add_argument('--omit-dist-init', action='store_false', dest='distInit', help='omit class files and IDE configurations from distribution') + parser.add_argument('zipfile', nargs=REMAINDER, metavar='zipfile') + + args = parser.parse_args(args) + + tmp = tempfile.mkdtemp(prefix='tmp', dir=_graal_home) + if args.vmbuild: + # Make sure the product VM binary is up to date + with VM(vmbuild='product'): + build([]) + + mx.log('Copying Java sources and mx files...') + mx.run(('hg archive -I graal -I mx -I mxtool -I mx.sh ' + tmp).split()) + + # Copy the GraalVM JDK + mx.log('Copying GraalVM JDK...') + src = _jdk() + dst = join(tmp, basename(src)) + shutil.copytree(src, dst) + zfName = join(_graal_home, 'graalvm-' + mx.get_os() + '.zip') + zf = zipfile.ZipFile(zfName, 'w') + for root, _, files in os.walk(tmp): + for f in files: + name = join(root, f) + arcname = name[len(tmp) + 1:] + zf.write(join(tmp, name), arcname) + + # create class files and IDE configurations + if args.distInit: + mx.log('Creating class files...') + mx.run('mx build'.split(), cwd=tmp) + mx.log('Creating IDE configurations...') + mx.run('mx ideinit'.split(), cwd=tmp) + + # clean up temp directory + mx.log('Cleaning up...') + shutil.rmtree(tmp) + + mx.log('Created distribution in ' + zfName) + +def _run_benchmark(args, availableBenchmarks, runBenchmark): + + vmOpts, benchmarksAndOptions = _extract_VM_args(args, useDoubleDash=availableBenchmarks is None) + + if availableBenchmarks is None: + harnessArgs = benchmarksAndOptions + return runBenchmark(None, harnessArgs, vmOpts) + + if len(benchmarksAndOptions) == 0: + mx.abort('at least one benchmark name or "all" must be specified') + benchmarks = list(itertools.takewhile(lambda x: not x.startswith('-'), benchmarksAndOptions)) + harnessArgs = benchmarksAndOptions[len(benchmarks):] + + if 'all' in benchmarks: + benchmarks = availableBenchmarks + else: + for bm in benchmarks: + if bm not in availableBenchmarks: + mx.abort('unknown benchmark: ' + bm + '\nselect one of: ' + str(availableBenchmarks)) + + failed = [] + for bm in benchmarks: + if not runBenchmark(bm, harnessArgs, vmOpts): + failed.append(bm) + + if len(failed) != 0: + mx.abort('Benchmark failures: ' + str(failed)) + +def dacapo(args): + """run one or more DaCapo benchmarks""" + + def launcher(bm, harnessArgs, extraVmOpts): + return sanitycheck.getDacapo(bm, harnessArgs).test(_get_vm(), extraVmOpts=extraVmOpts) + + _run_benchmark(args, sanitycheck.dacapoSanityWarmup.keys(), launcher) + +def scaladacapo(args): + """run one or more Scala DaCapo benchmarks""" + + def launcher(bm, harnessArgs, extraVmOpts): + return sanitycheck.getScalaDacapo(bm, harnessArgs).test(_get_vm(), extraVmOpts=extraVmOpts) + + _run_benchmark(args, sanitycheck.dacapoScalaSanityWarmup.keys(), launcher) + +def _arch(): + machine = platform.uname()[4] + if machine in ['amd64', 'AMD64', 'x86_64', 'i86pc']: + return 'amd64' + if machine in ['sun4v', 'sun4u']: + return 'sparcv9' + if machine == 'i386' and mx.get_os() == 'darwin': + try: + # Support for Snow Leopard and earlier version of MacOSX + if subprocess.check_output(['sysctl', '-n', 'hw.cpu64bit_capable']).strip() == '1': + return 'amd64' + except OSError: + # sysctl is not available + pass + mx.abort('unknown or unsupported architecture: os=' + mx.get_os() + ', machine=' + machine) + +def _vmLibDirInJdk(jdk): + """ + Get the directory within a JDK where the server and client + subdirectories are located. + """ + if platform.system() == 'Darwin': + return join(jdk, 'jre', 'lib') + if platform.system() == 'Windows': + return join(jdk, 'jre', 'bin') + return join(jdk, 'jre', 'lib', _arch()) + +def _vmCfgInJdk(jdk): + """ + Get the jvm.cfg file. + """ + if platform.system() == 'Windows': + return join(jdk, 'jre', 'lib', _arch(), 'jvm.cfg') + return join(_vmLibDirInJdk(jdk), 'jvm.cfg') + +def _jdksDir(): + return os.path.abspath(join(_installed_jdks if _installed_jdks else _graal_home, 'jdk' + str(mx.java().version))) + +def _handle_missing_VM(bld, vm): + mx.log('The ' + bld + ' ' + vm + ' VM has not been created') + if sys.stdout.isatty(): + if mx.ask_yes_no('Build it now', 'y'): + with VM(vm, bld): + build([]) + return + mx.abort('You need to run "mx --vm ' + vm + ' --vmbuild ' + bld + ' build" to build the selected VM') + +def _jdk(build='product', vmToCheck=None, create=False, installGraalJar=True): + """ + Get the JDK into which Graal is installed, creating it first if necessary. + """ + jdk = join(_jdksDir(), build) + if create: + srcJdk = mx.java().jdk + jdkContents = ['bin', 'include', 'jre', 'lib'] + if exists(join(srcJdk, 'db')): + jdkContents.append('db') + if mx.get_os() != 'windows' and exists(join(srcJdk, 'man')): + jdkContents.append('man') + if not exists(jdk): + mx.log('Creating ' + jdk + ' from ' + srcJdk) + os.makedirs(jdk) + for d in jdkContents: + src = join(srcJdk, d) + dst = join(jdk, d) + if not exists(src): + mx.abort('Host JDK directory is missing: ' + src) + shutil.copytree(src, dst) + + # Make a copy of the default VM so that this JDK can be + # reliably used as the bootstrap for a HotSpot build. + jvmCfg = _vmCfgInJdk(jdk) + if not exists(jvmCfg): + mx.abort(jvmCfg + ' does not exist') + + defaultVM = None + jvmCfgLines = [] + with open(jvmCfg) as f: + for line in f: + if line.startswith('-') and defaultVM is None: + parts = line.split() + if len(parts) == 2: + assert parts[1] == 'KNOWN', parts[1] + defaultVM = parts[0][1:] + jvmCfgLines += ['# default VM is a copy of the unmodified ' + defaultVM + ' VM\n'] + jvmCfgLines += ['-original KNOWN\n'] + else: + # skip lines which we cannot parse (e.g. '-hotspot ALIASED_TO -client') + mx.log("WARNING: skipping not parsable line \"" + line + "\"") + else: + jvmCfgLines += [line] + + assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg + if mx.get_os() != 'windows': + chmodRecursive(jdk, 0755) + shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'original')) + + + with open(jvmCfg, 'w') as fp: + for line in jvmCfgLines: + fp.write(line) + + # Install a copy of the disassembler library + try: + hsdis([], copyToDir=_vmLibDirInJdk(jdk)) + except SystemExit: + pass + else: + if not exists(jdk): + if _installed_jdks: + mx.log("The selected JDK directory does not (yet) exist: " + jdk) + _handle_missing_VM(build, vmToCheck if vmToCheck else 'graal') + + if installGraalJar: + _installGraalJarInJdks(mx.distribution('GRAAL')) + + if vmToCheck is not None: + jvmCfg = _vmCfgInJdk(jdk) + found = False + with open(jvmCfg) as f: + for line in f: + if line.strip() == '-' + vmToCheck + ' KNOWN': + found = True + break + if not found: + _handle_missing_VM(build, vmToCheck) + + return jdk + +def _updateInstalledGraalOptionsFile(jdk): + graalOptions = join(_graal_home, 'graal.options') + jreLibDir = join(jdk, 'jre', 'lib') + if exists(graalOptions): + shutil.copy(graalOptions, join(jreLibDir, 'graal.options')) + else: + toDelete = join(jreLibDir, 'graal.options') + if exists(toDelete): + os.unlink(toDelete) + +def _installGraalJarInJdks(graalDist): + graalJar = graalDist.path + jdks = _jdksDir() + if exists(jdks): + for e in os.listdir(jdks): + jreLibDir = join(jdks, e, 'jre', 'lib') + if exists(jreLibDir): + # do a copy and then a move to get atomic updating (on Unix) of graal.jar in the JRE + fd, tmp = tempfile.mkstemp(suffix='', prefix='graal.jar', dir=jreLibDir) + shutil.copyfile(graalJar, tmp) + os.close(fd) + shutil.move(tmp, join(jreLibDir, 'graal.jar')) + +# run a command in the windows SDK Debug Shell +def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None): + if respondTo is None: + respondTo = {} + newLine = os.linesep + startToken = 'RUNINDEBUGSHELL_STARTSEQUENCE' + endToken = 'RUNINDEBUGSHELL_ENDSEQUENCE' + + winSDK = mx.get_env('WIN_SDK', 'C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\') + + if not exists(winSDK): + mx.abort("Could not find Windows SDK : '" + winSDK + "' does not exist") + + if not exists(join(winSDK, 'Bin', 'SetEnv.cmd')): + mx.abort("Invalid Windows SDK path (" + winSDK + ") : could not find Bin/SetEnv.cmd (you can use the WIN_SDK environment variable to specify an other path)") + + p = subprocess.Popen('cmd.exe /E:ON /V:ON /K ""' + winSDK + '/Bin/SetEnv.cmd" & echo ' + startToken + '"', \ + shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP) + stdout = p.stdout + stdin = p.stdin + if logFile: + log = open(logFile, 'w') + ret = False + while True: + + # encoding may be None on windows plattforms + if sys.stdout.encoding is None: + encoding = 'utf-8' + else: + encoding = sys.stdout.encoding + + line = stdout.readline().decode(encoding) + if logFile: + log.write(line.encode('utf-8')) + line = line.strip() + mx.log(line) + if line == startToken: + stdin.write('cd /D ' + workingDir + ' & ' + cmd + ' & echo ' + endToken + newLine) + for regex in respondTo.keys(): + match = regex.search(line) + if match: + stdin.write(respondTo[regex] + newLine) + if findInOutput: + match = findInOutput.search(line) + if match: + ret = True + if line == endToken: + if not findInOutput: + stdin.write('echo ERRXXX%errorlevel%' + newLine) + else: + break + if line.startswith('ERRXXX'): + if line == 'ERRXXX0': + ret = True + break + stdin.write('exit' + newLine) + if logFile: + log.close() + return ret + +def jdkhome(vm=None): + """return the JDK directory selected for the 'vm' command""" + build = _vmbuild if _vmSourcesAvailable else 'product' + return _jdk(build, installGraalJar=False) + +def print_jdkhome(args, vm=None): + """print the JDK directory selected for the 'vm' command""" + print jdkhome(vm) + +def buildvars(args): + """describe the variables that can be set by the -D option to the 'mx build' commmand""" + + buildVars = { + 'ALT_BOOTDIR' : 'The location of the bootstrap JDK installation (default: ' + mx.java().jdk + ')', + 'ALT_OUTPUTDIR' : 'Build directory', + 'HOTSPOT_BUILD_JOBS' : 'Number of CPUs used by make (default: ' + str(multiprocessing.cpu_count()) + ')', + 'INSTALL' : 'Install the built VM into the JDK? (default: y)', + 'ZIP_DEBUGINFO_FILES' : 'Install zipped debug symbols file? (default: 0)', + } + + mx.log('HotSpot build variables that can be set by the -D option to "mx build":') + mx.log('') + for n in sorted(buildVars.iterkeys()): + mx.log(n) + mx.log(textwrap.fill(buildVars[n], initial_indent=' ', subsequent_indent=' ', width=200)) + + mx.log('') + mx.log('Note that these variables can be given persistent values in the file ' + join(_graal_home, 'mx', 'env') + ' (see \'mx about\').') + +def build(args, vm=None): + """build the VM binary + + The global '--vm' and '--vmbuild' options select which VM type and build target to build.""" + + # Override to fail quickly if extra arguments are given + # at the end of the command line. This allows for a more + # helpful error message. + class AP(ArgumentParser): + def __init__(self): + ArgumentParser.__init__(self, prog='mx build') + def parse_args(self, args): + result = ArgumentParser.parse_args(self, args) + if len(result.remainder) != 0: + firstBuildTarget = result.remainder[0] + mx.abort('To specify the ' + firstBuildTarget + ' VM build target, you need to use the global "--vmbuild" option. For example:\n' + + ' mx --vmbuild ' + firstBuildTarget + ' build') + return result + + # Call mx.build to compile the Java sources + parser = AP() + parser.add_argument('--export-dir', help='directory to which graal.jar and graal.options will be copied', metavar='') + parser.add_argument('-D', action='append', help='set a HotSpot build variable (run \'mx buildvars\' to list variables)', metavar='name=value') + opts2 = mx.build(['--source', '1.7'] + args, parser=parser) + assert len(opts2.remainder) == 0 + + if opts2.export_dir is not None: + if not exists(opts2.export_dir): + os.makedirs(opts2.export_dir) + else: + assert os.path.isdir(opts2.export_dir), '{} is not a directory'.format(opts2.export_dir) + + shutil.copy(mx.distribution('GRAAL').path, opts2.export_dir) + graalOptions = join(_graal_home, 'graal.options') + if exists(graalOptions): + shutil.copy(graalOptions, opts2.export_dir) + + if not _vmSourcesAvailable or not opts2.native: + return + + builds = [_vmbuild] + + if vm is None: + vm = _get_vm() + + if vm == 'original': + pass + elif vm.startswith('server'): + buildSuffix = '' + elif vm.startswith('client'): + buildSuffix = '1' + else: + assert vm == 'graal', vm + buildSuffix = 'graal' + + if _installed_jdks and _installed_jdks != _graal_home: + if not mx.ask_yes_no("Warning: building while --installed-jdks is set (" + _installed_jdks + ") is not recommanded - are you sure you want to continue", 'n'): + mx.abort(1) + + for build in builds: + if build == 'ide-build-target': + build = os.environ.get('IDE_BUILD_TARGET', None) + if build is None or len(build) == 0: + continue + + jdk = _jdk(build, create=True) + + if vm == 'original': + if build != 'product': + mx.log('only product build of original VM exists') + continue + + vmDir = join(_vmLibDirInJdk(jdk), vm) + if not exists(vmDir): + if mx.get_os() != 'windows': + chmodRecursive(jdk, 0755) + mx.log('Creating VM directory in JDK7: ' + vmDir) + os.makedirs(vmDir) + + def filterXusage(line): + if not 'Xusage.txt' in line: + sys.stderr.write(line + os.linesep) + + # Check if a build really needs to be done + timestampFile = join(vmDir, '.build-timestamp') + if opts2.force or not exists(timestampFile): + mustBuild = True + else: + mustBuild = False + timestamp = os.path.getmtime(timestampFile) + sources = [] + for d in ['src', 'make']: + for root, dirnames, files in os.walk(join(_graal_home, d)): + # ignore /src/share/tools + if root == join(_graal_home, 'src', 'share'): + dirnames.remove('tools') + sources += [join(root, name) for name in files] + for f in sources: + if len(f) != 0 and os.path.getmtime(f) > timestamp: + mustBuild = True + break + + if not mustBuild: + mx.logv('[all files in src and make directories are older than ' + timestampFile[len(_graal_home) + 1:] + ' - skipping native build]') + continue + + if platform.system() == 'Windows': + compilelogfile = _graal_home + '/graalCompile.log' + mksHome = mx.get_env('MKS_HOME', 'C:\\cygwin\\bin') + + variant = {'client': 'compiler1', 'server': 'compiler2'}.get(vm, vm) + project_config = variant + '_' + build + _runInDebugShell('msbuild ' + _graal_home + r'\build\vs-amd64\jvm.vcproj /p:Configuration=' + project_config + ' /target:clean', _graal_home) + winCompileCmd = r'set HotSpotMksHome=' + mksHome + r'& set OUT_DIR=' + jdk + r'& set JAVA_HOME=' + jdk + r'& set path=%JAVA_HOME%\bin;%path%;%HotSpotMksHome%& cd /D "' + _graal_home + r'\make\windows"& call create.bat ' + _graal_home + print(winCompileCmd) + winCompileSuccess = re.compile(r"^Writing \.vcxproj file:") + if not _runInDebugShell(winCompileCmd, _graal_home, compilelogfile, winCompileSuccess): + mx.log('Error executing create command') + return + winBuildCmd = 'msbuild ' + _graal_home + r'\build\vs-amd64\jvm.vcxproj /p:Configuration=' + project_config + ' /p:Platform=x64' + if not _runInDebugShell(winBuildCmd, _graal_home, compilelogfile): + mx.log('Error building project') + return + else: + cpus = multiprocessing.cpu_count() + runCmd = [mx.gmake_cmd()] + runCmd.append(build + buildSuffix) + env = os.environ.copy() + + if opts2.D: + for nv in opts2.D: + name, value = nv.split('=', 1) + env[name.strip()] = value + + env.setdefault('ARCH_DATA_MODEL', '64') + env.setdefault('LANG', 'C') + env.setdefault('HOTSPOT_BUILD_JOBS', str(cpus)) + env.setdefault('ALT_BOOTDIR', mx.java().jdk) + if not mx._opts.verbose: + runCmd.append('MAKE_VERBOSE=') + env['JAVA_HOME'] = jdk + if vm.endswith('nograal'): + env['INCLUDE_GRAAL'] = 'false' + env.setdefault('ALT_OUTPUTDIR', join(_graal_home, 'build-nograal', mx.get_os())) + else: + env['INCLUDE_GRAAL'] = 'true' + env.setdefault('INSTALL', 'y') + if mx.get_os() == 'solaris' : + # If using sparcWorks, setup flags to avoid make complaining about CC version + cCompilerVersion = subprocess.Popen('CC -V', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).stderr.readlines()[0] + if cCompilerVersion.startswith('CC: Sun C++') : + compilerRev = cCompilerVersion.split(' ')[3] + env.setdefault('ENFORCE_COMPILER_REV', compilerRev) + env.setdefault('ENFORCE_CC_COMPILER_REV', compilerRev) + if build == 'jvmg': + # I want ALL the symbols when I'm debugging on Solaris + # Some Makefile variable are overloaded by environment variable so we need to explicitely + # pass them down in the command line. This one is an example of that. + runCmd.append('STRIP_POLICY=no_strip') + # This removes the need to unzip the *.diz files before debugging in gdb + env.setdefault('ZIP_DEBUGINFO_FILES', '0') + + # Clear these 2 variables as having them set can cause very confusing build problems + env.pop('LD_LIBRARY_PATH', None) + env.pop('CLASSPATH', None) + + mx.run(runCmd, cwd=join(_graal_home, 'make'), err=filterXusage, env=env) + + jvmCfg = _vmCfgInJdk(jdk) + if not exists(jvmCfg): + mx.abort(jvmCfg + ' does not exist') + + prefix = '-' + vm + ' ' + vmKnown = prefix + 'KNOWN\n' + lines = [] + found = False + with open(jvmCfg) as f: + for line in f: + if line.strip() == vmKnown.strip(): + found = True + lines.append(line) + + if not found: + mx.log('Appending "' + prefix + 'KNOWN" to ' + jvmCfg) + if mx.get_os() != 'windows': + os.chmod(jvmCfg, 0755) + with open(jvmCfg, 'w') as f: + for line in lines: + if line.startswith(prefix): + line = vmKnown + found = True + f.write(line) + if not found: + f.write(vmKnown) + + if exists(timestampFile): + os.utime(timestampFile, None) + else: + file(timestampFile, 'a') + +def vmg(args): + """run the debug build of VM selected by the '--vm' option""" + return vm(args, vmbuild='debug') + +def vmfg(args): + """run the fastdebug build of VM selected by the '--vm' option""" + return vm(args, vmbuild='fastdebug') + +def vm(args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, vmbuild=None): + """run the VM selected by the '--vm' option""" + + if vm is None: + vm = _get_vm() + + if cwd is None: + cwd = _vm_cwd + elif _vm_cwd is not None and _vm_cwd != cwd: + mx.abort("conflicting working directories: do not set --vmcwd for this command") + + build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product' + jdk = _jdk(build, vmToCheck=vm, installGraalJar=False) + _updateInstalledGraalOptionsFile(jdk) + mx.expand_project_in_args(args) + if _make_eclipse_launch: + mx.make_eclipse_launch(args, 'graal-' + build, name=None, deps=mx.project('com.oracle.graal.hotspot').all_deps([], True)) + if len([a for a in args if 'PrintAssembly' in a]) != 0: + hsdis([], copyToDir=_vmLibDirInJdk(jdk)) + if mx.java().debug_port is not None: + args = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(mx.java().debug_port)] + args + if _jacoco == 'on' or _jacoco == 'append': + jacocoagent = mx.library("JACOCOAGENT", True) + # Exclude all compiler tests and snippets + excludes = ['com.oracle.graal.compiler.tests.*', 'com.oracle.graal.jtt.*'] + for p in mx.projects(): + excludes += _find_classes_with_annotations(p, None, ['@Snippet', '@ClassSubstitution', '@Test'], includeInnerClasses=True).keys() + excludes += p.find_classes_with_matching_source_line(None, lambda line: 'JaCoCo Exclude' in line, includeInnerClasses=True).keys() + + includes = ['com.oracle.graal.*'] + agentOptions = { + 'append' : 'true' if _jacoco == 'append' else 'false', + 'bootclasspath' : 'true', + 'includes' : ':'.join(includes), + 'excludes' : ':'.join(excludes), + 'destfile' : 'jacoco.exec' + } + args = ['-javaagent:' + jacocoagent.get_path(True) + '=' + ','.join([k + '=' + v for k, v in agentOptions.items()])] + args + if '-d64' not in args: + args = ['-d64'] + args + + exe = join(jdk, 'bin', mx.exe_suffix('java')) + pfx = _vm_prefix.split() if _vm_prefix is not None else [] + + if '-version' in args: + ignoredArgs = args[args.index('-version') + 1:] + if len(ignoredArgs) > 0: + mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs)) + + return mx.run(pfx + [exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout) + +def _find_classes_with_annotations(p, pkgRoot, annotations, includeInnerClasses=False): + """ + Scan the sources of project 'p' for Java source files containing a line starting with 'annotation' + (ignoring preceding whitespace) and return the fully qualified class name for each Java + source file matched in a list. + """ + + matches = lambda line : len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0 + return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses) + +def _extract_VM_args(args, allowClasspath=False, useDoubleDash=False): + """ + Partitions a command line into a leading sequence of HotSpot VM options and the rest. + """ + for i in range(0, len(args)): + if useDoubleDash: + if args[i] == '--': + vmArgs = args[:i] + remainder = args[i + 1:] + return vmArgs, remainder + else: + if not args[i].startswith('-'): + if i != 0 and (args[i - 1] == '-cp' or args[i - 1] == '-classpath'): + if not allowClasspath: + mx.abort('Cannot supply explicit class path option') + else: + continue + vmArgs = args[:i] + remainder = args[i:] + return vmArgs, remainder + + return args, [] + +def _run_tests(args, harness, annotations, testfile): + + + vmArgs, tests = _extract_VM_args(args) + for t in tests: + if t.startswith('-'): + mx.abort('VM option ' + t + ' must precede ' + tests[0]) + + candidates = [] + for p in mx.projects_opt_limit_to_suites(): + if mx.java().javaCompliance < p.javaCompliance: + continue + candidates += _find_classes_with_annotations(p, None, annotations).keys() + + classes = [] + if len(tests) == 0: + classes = candidates + else: + for t in tests: + found = False + for c in candidates: + if t in c: + found = True + classes.append(c) + if not found: + mx.log('warning: no tests matched by substring "' + t) + + projectscp = mx.classpath([pcp.name for pcp in mx.projects_opt_limit_to_suites() if pcp.javaCompliance <= mx.java().javaCompliance]) + + if len(classes) != 0: + f_testfile = open(testfile, 'w') + for c in classes: + f_testfile.write(c + '\n') + f_testfile.close() + harness(projectscp, vmArgs) + +def _unittest(args, annotations): + mxdir = dirname(__file__) + name = 'JUnitWrapper' + javaSource = join(mxdir, name + '.java') + javaClass = join(mxdir, name + '.class') + testfile = os.environ.get('MX_TESTFILE', None) + if testfile is None: + (_, testfile) = tempfile.mkstemp(".testclasses", "graal") + os.close(_) + + def harness(projectscp, vmArgs): + if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource): + subprocess.check_call([mx.java().javac, '-cp', projectscp, '-d', mxdir, javaSource]) + if _get_vm() != 'graal': + prefixArgs = ['-esa', '-ea'] + else: + prefixArgs = ['-XX:-BootstrapGraal', '-esa', '-ea'] + with open(testfile) as fp: + testclasses = [l.rstrip() for l in fp.readlines()] + if len(testclasses) == 1: + # Execute Junit directly when one test is being run. This simplifies + # replaying the VM execution in a native debugger (e.g., gdb). + vm(prefixArgs + vmArgs + ['-cp', projectscp, 'org.junit.runner.JUnitCore'] + testclasses) + else: + vm(prefixArgs + vmArgs + ['-cp', projectscp + os.pathsep + mxdir, name] + [testfile]) + + try: + _run_tests(args, harness, annotations, testfile) + finally: + if os.environ.get('MX_TESTFILE') is None: + os.remove(testfile) + +_unittestHelpSuffix = """ + + If filters are supplied, only tests whose fully qualified name + includes a filter as a substring are run. + + For example, this command line: + + mx unittest -G:Dump= -G:MethodFilter=BC_aload.* -G:+PrintCFG BC_aload + + will run all JUnit test classes that contain 'BC_aload' in their + fully qualified name and will pass these options to the VM: + + -G:Dump= -G:MethodFilter=BC_aload.* -G:+PrintCFG + + To get around command line length limitations on some OSes, the + JUnit class names to be executed are written to a file that a + custom JUnit wrapper reads and passes onto JUnit proper. The + MX_TESTFILE environment variable can be set to specify a + file which will not be deleted once the unittests are done + (unlike the temporary file otherwise used). + + As with all other commands, using the global '-v' before 'unittest' + command will cause mx to show the complete command line + it uses to run the VM. +""" + +def unittest(args): + """run the JUnit tests (all testcases){0}""" + + _unittest(args, ['@Test', '@LongTest', '@Parameters']) + +def shortunittest(args): + """run the JUnit tests (short testcases only){0}""" + + _unittest(args, ['@Test']) + +def longunittest(args): + """run the JUnit tests (long testcases only){0}""" + + _unittest(args, ['@LongTest', '@Parameters']) + +def buildvms(args): + """build one or more VMs in various configurations""" + + vmsDefault = ','.join(_vmChoices.keys()) + vmbuildsDefault = ','.join(_vmbuildChoices) + + parser = ArgumentParser(prog='mx buildvms') + parser.add_argument('--vms', help='a comma separated list of VMs to build (default: ' + vmsDefault + ')', metavar='', default=vmsDefault) + parser.add_argument('--builds', help='a comma separated list of build types (default: ' + vmbuildsDefault + ')', metavar='', default=vmbuildsDefault) + parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build') + parser.add_argument('-c', '--console', action='store_true', help='send build output to console instead of log file') + + args = parser.parse_args(args) + vms = args.vms.split(',') + builds = args.builds.split(',') + + allStart = time.time() + for v in vms: + for vmbuild in builds: + if v == 'original' and vmbuild != 'product': + continue + if not args.console: + logFile = join(v + '-' + vmbuild + '.log') + log = open(join(_graal_home, logFile), 'wb') + start = time.time() + mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')') + # Run as subprocess so that output can be directed to a file + subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, '--vmbuild', + vmbuild, 'build'], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT) + duration = datetime.timedelta(seconds=time.time() - start) + mx.log('END: ' + v + '-' + vmbuild + '\t[' + str(duration) + ']') + else: + with VM(v, vmbuild): + build([]) + if not args.no_check: + vmargs = ['-version'] + if v == 'graal': + vmargs.insert(0, '-XX:-BootstrapGraal') + vm(vmargs, vm=v, vmbuild=vmbuild) + allDuration = datetime.timedelta(seconds=time.time() - allStart) + mx.log('TOTAL TIME: ' + '[' + str(allDuration) + ']') + +class Task: + def __init__(self, title): + self.start = time.time() + self.title = title + self.end = None + self.duration = None + mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: BEGIN: ') + title) + def stop(self): + self.end = time.time() + self.duration = datetime.timedelta(seconds=self.end - self.start) + mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: END: ') + self.title + ' [' + str(self.duration) + ']') + return self + def abort(self, codeOrMessage): + self.end = time.time() + self.duration = datetime.timedelta(seconds=self.end - self.start) + mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(self.duration) + ']') + mx.abort(codeOrMessage) + return self + +def _basic_gate_body(args, tasks): + t = Task('BuildHotSpotGraal: fastdebug,product') + buildvms(['--vms', 'graal,server', '--builds', 'fastdebug,product']) + tasks.append(t.stop()) + + with VM('graal', 'fastdebug'): + t = Task('BootstrapWithSystemAssertions:fastdebug') + vm(['-esa', '-version']) + tasks.append(t.stop()) + + with VM('graal', 'product'): + t = Task('BootstrapWithGCVerification:product') + out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write + vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) + tasks.append(t.stop()) + + with VM('graal', 'product'): + t = Task('BootstrapWithG1GCVerification:product') + out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write + vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) + tasks.append(t.stop()) + + with VM('graal', 'product'): + t = Task('BootstrapWithRegisterPressure:product') + vm(['-G:RegisterPressure=rbx,r11,r10,r14,xmm3,xmm11,xmm14', '-esa', '-version']) + tasks.append(t.stop()) + + with VM('graal', 'product'): + t = Task('BootstrapWithAOTConfiguration:product') + vm(['-G:+AOTCompilation', '-G:+VerifyPhases', '-esa', '-version']) + tasks.append(t.stop()) + + with VM('server', 'product'): # hosted mode + t = Task('UnitTests:hosted-product') + unittest([]) + tasks.append(t.stop()) + + for vmbuild in ['fastdebug', 'product']: + for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild): + t = Task(str(test) + ':' + vmbuild) + if not test.test('graal'): + t.abort(test.name + ' Failed') + tasks.append(t.stop()) + + if args.jacocout is not None: + jacocoreport([args.jacocout]) + + global _jacoco + _jacoco = 'off' + + t = Task('CleanAndBuildIdealGraphVisualizer') + mx.run(['ant', '-f', join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'), '-q', 'clean', 'build']) + tasks.append(t.stop()) + + # Prevent Graal modifications from breaking the standard builds + if args.buildNonGraal: + t = Task('BuildHotSpotVarieties') + buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product']) + buildvms(['--vms', 'server-nograal', '--builds', 'product']) + buildvms(['--vms', 'server-nograal', '--builds', 'optimized']) + tasks.append(t.stop()) + + for vmbuild in ['product', 'fastdebug']: + for theVm in ['client', 'server']: + with VM(theVm, vmbuild): + t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild) + dacapo(['pmd']) + tasks.append(t.stop()) + + t = Task('UnitTests:' + theVm + ':' + vmbuild) + unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api']) + tasks.append(t.stop()) + + +def gate(args, gate_body=_basic_gate_body): + """run the tests used to validate a push + + If this command exits with a 0 exit code, then the source code is in + a state that would be accepted for integration into the main repository.""" + + parser = ArgumentParser(prog='mx gate') + parser.add_argument('-j', '--omit-java-clean', action='store_false', dest='cleanJava', help='omit cleaning Java native code') + parser.add_argument('-n', '--omit-native-clean', action='store_false', dest='cleanNative', help='omit cleaning and building native code') + parser.add_argument('-g', '--only-build-graalvm', action='store_false', dest='buildNonGraal', help='only build the Graal VM') + parser.add_argument('--jacocout', help='specify the output directory for jacoco report') + + args = parser.parse_args(args) + + global _jacoco + + tasks = [] + total = Task('Gate') + try: + + t = Task('Pylint') + mx.pylint([]) + tasks.append(t.stop()) + + t = Task('Clean') + cleanArgs = [] + if not args.cleanNative: + cleanArgs.append('--no-native') + if not args.cleanJava: + cleanArgs.append('--no-java') + clean(cleanArgs) + tasks.append(t.stop()) + + t = Task('IDEConfigCheck') + mx.ideclean([]) + mx.ideinit([]) + tasks.append(t.stop()) + + eclipse_exe = os.environ.get('ECLIPSE_EXE') + if eclipse_exe is not None: + t = Task('CodeFormatCheck') + if mx.eclipseformat(['-e', eclipse_exe]) != 0: + t.abort('Formatter modified files - run "mx eclipseformat", check in changes and repush') + tasks.append(t.stop()) + + t = Task('Canonicalization Check') + mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...')) + if mx.canonicalizeprojects([]) != 0: + t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.') + tasks.append(t.stop()) + + t = Task('BuildJava') + build(['--no-native', '--jdt-warning-as-error']) + tasks.append(t.stop()) + + t = Task('Checkstyle') + if mx.checkstyle([]) != 0: + t.abort('Checkstyle warnings were found') + tasks.append(t.stop()) + + if exists('jacoco.exec'): + os.unlink('jacoco.exec') + + if args.jacocout is not None: + _jacoco = 'append' + else: + _jacoco = 'off' + + gate_body(args, tasks) + + except KeyboardInterrupt: + total.abort(1) + + except BaseException as e: + import traceback + traceback.print_exc() + total.abort(str(e)) + + total.stop() + + mx.log('Gate task times:') + for t in tasks: + mx.log(' ' + str(t.duration) + '\t' + t.title) + mx.log(' =======') + mx.log(' ' + str(total.duration)) + +def deoptalot(args): + """bootstrap a fastdebug Graal VM with DeoptimizeALot and VerifyOops on + + If the first argument is a number, the process will be repeated + this number of times. All other arguments are passed to the VM.""" + count = 1 + if len(args) > 0 and args[0].isdigit(): + count = int(args[0]) + del args[0] + + for _ in range(count): + if not vm(['-XX:+DeoptimizeALot', '-XX:+VerifyOops'] + args + ['-version'], vmbuild='fastdebug') == 0: + mx.abort("Failed") + +def longtests(args): + + deoptalot(['15', '-Xmx48m']) + + dacapo(['100', 'eclipse', '-esa']) + +def gv(args): + """run the Graal Visualizer""" + with open(join(_graal_home, '.graal_visualizer.log'), 'w') as fp: + mx.logv('[Graal Visualizer log is in ' + fp.name + ']') + if not exists(join(_graal_home, 'visualizer', 'build.xml')): + mx.logv('[This initial execution may take a while as the NetBeans platform needs to be downloaded]') + mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-l', fp.name, 'run']) + +def igv(args): + """run the Ideal Graph Visualizer""" + with open(join(_graal_home, '.ideal_graph_visualizer.log'), 'w') as fp: + mx.logv('[Ideal Graph Visualizer log is in ' + fp.name + ']') + if not exists(join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'nbplatform')): + mx.logv('[This initial execution may take a while as the NetBeans platform needs to be downloaded]') + mx.run(['ant', '-f', join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'), '-l', fp.name, 'run']) + +def bench(args): + """run benchmarks and parse their output for results + + Results are JSON formated : {group : {benchmark : score}}.""" + resultFile = None + if '-resultfile' in args: + index = args.index('-resultfile') + if index + 1 < len(args): + resultFile = args[index + 1] + del args[index] + del args[index] + else: + mx.abort('-resultfile must be followed by a file name') + vm = _get_vm() + if len(args) is 0: + args = ['all'] + + vmArgs = [arg for arg in args if arg.startswith('-')] + + def benchmarks_in_group(group): + prefix = group + ':' + return [a[len(prefix):] for a in args if a.startswith(prefix)] + + results = {} + benchmarks = [] + # DaCapo + if ('dacapo' in args or 'all' in args): + benchmarks += sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Benchmark) + else: + dacapos = benchmarks_in_group('dacapo') + for dacapo in dacapos: + if dacapo not in sanitycheck.dacapoSanityWarmup.keys(): + mx.abort('Unknown DaCapo : ' + dacapo) + iterations = sanitycheck.dacapoSanityWarmup[dacapo][sanitycheck.SanityCheckLevel.Benchmark] + if (iterations > 0): + benchmarks += [sanitycheck.getDacapo(dacapo, iterations)] + + if ('scaladacapo' in args or 'all' in args): + benchmarks += sanitycheck.getScalaDacapos(level=sanitycheck.SanityCheckLevel.Benchmark) + else: + scaladacapos = benchmarks_in_group('scaladacapo') + for scaladacapo in scaladacapos: + if scaladacapo not in sanitycheck.dacapoScalaSanityWarmup.keys(): + mx.abort('Unknown Scala DaCapo : ' + scaladacapo) + iterations = sanitycheck.dacapoScalaSanityWarmup[scaladacapo][sanitycheck.SanityCheckLevel.Benchmark] + if (iterations > 0): + benchmarks += [sanitycheck.getScalaDacapo(scaladacapo, ['-n', str(iterations)])] + + # Bootstrap + if ('bootstrap' in args or 'all' in args): + benchmarks += sanitycheck.getBootstraps() + # SPECjvm2008 + if ('specjvm2008' in args or 'all' in args): + benchmarks += [sanitycheck.getSPECjvm2008(['-ikv', '-wt', '120', '-it', '120'])] + else: + specjvms = benchmarks_in_group('specjvm2008') + for specjvm in specjvms: + benchmarks += [sanitycheck.getSPECjvm2008(['-ikv', '-wt', '120', '-it', '120', specjvm])] + + if ('specjbb2005' in args or 'all' in args): + benchmarks += [sanitycheck.getSPECjbb2005()] + + if ('specjbb2013' in args): # or 'all' in args //currently not in default set + benchmarks += [sanitycheck.getSPECjbb2013()] + + if ('ctw-full' in args): + benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.Full)) + if ('ctw-noinline' in args): + benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.NoInline)) + if ('ctw-nocomplex' in args): + benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.NoComplex)) + + for test in benchmarks: + for (groupName, res) in test.bench(vm, extraVmOpts=vmArgs).items(): + group = results.setdefault(groupName, {}) + group.update(res) + mx.log(json.dumps(results)) + if resultFile: + with open(resultFile, 'w') as f: + f.write(json.dumps(results)) + +def specjvm2008(args): + """run one or more SPECjvm2008 benchmarks""" + + def launcher(bm, harnessArgs, extraVmOpts): + return sanitycheck.getSPECjvm2008(harnessArgs + [bm]).bench(_get_vm(), extraVmOpts=extraVmOpts) + + availableBenchmarks = set(sanitycheck.specjvm2008Names) + for name in sanitycheck.specjvm2008Names: + parts = name.rsplit('.', 1) + if len(parts) > 1: + assert len(parts) == 2 + group = parts[0] + availableBenchmarks.add(group) + + _run_benchmark(args, sorted(availableBenchmarks), launcher) + +def specjbb2013(args): + """runs the composite SPECjbb2013 benchmark""" + + def launcher(bm, harnessArgs, extraVmOpts): + assert bm is None + return sanitycheck.getSPECjbb2013(harnessArgs).bench(_get_vm(), extraVmOpts=extraVmOpts) + + _run_benchmark(args, None, launcher) + +def specjbb2005(args): + """runs the composite SPECjbb2005 benchmark""" + + def launcher(bm, harnessArgs, extraVmOpts): + assert bm is None + return sanitycheck.getSPECjbb2005(harnessArgs).bench(_get_vm(), extraVmOpts=extraVmOpts) + + _run_benchmark(args, None, launcher) + +def hsdis(args, copyToDir=None): + """download the hsdis library + + This is needed to support HotSpot's assembly dumping features. + By default it downloads the Intel syntax version, use the 'att' argument to install AT&T syntax.""" + flavor = 'intel' + if 'att' in args: + flavor = 'att' + lib = mx.add_lib_suffix('hsdis-' + _arch()) + path = join(_graal_home, 'lib', lib) + if not exists(path): + mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hsdis/' + flavor + "/" + lib]) + if copyToDir is not None and exists(copyToDir): + shutil.copy(path, copyToDir) + +def hcfdis(args): + """disassemble HexCodeFiles embedded in text files + + Run a tool over the input files to convert all embedded HexCodeFiles + to a disassembled format.""" + + parser = ArgumentParser(prog='mx hcfdis') + parser.add_argument('-m', '--map', help='address to symbol map applied to disassembler output') + parser.add_argument('files', nargs=REMAINDER, metavar='files...') + + args = parser.parse_args(args) + + path = join(_graal_home, 'lib', 'hcfdis-1.jar') + if not exists(path): + mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hcfdis-1.jar']) + mx.run_java(['-jar', path] + args.files) + + if args.map is not None: + addressRE = re.compile(r'0[xX]([A-Fa-f0-9]+)') + with open(args.map) as fp: + lines = fp.read().splitlines() + symbols = dict() + for l in lines: + addressAndSymbol = l.split(' ', 1) + if len(addressAndSymbol) == 2: + address, symbol = addressAndSymbol + if address.startswith('0x'): + address = long(address, 16) + symbols[address] = symbol + for f in args.files: + with open(f) as fp: + lines = fp.read().splitlines() + updated = False + for i in range(0, len(lines)): + l = lines[i] + for m in addressRE.finditer(l): + sval = m.group(0) + val = long(sval, 16) + sym = symbols.get(val) + if sym: + l = l.replace(sval, sym) + updated = True + lines[i] = l + if updated: + mx.log('updating ' + f) + with open('new_' + f, "w") as fp: + for l in lines: + print >> fp, l + +def jacocoreport(args): + """create a JaCoCo coverage report + + Creates the report from the 'jacoco.exec' file in the current directory. + Default output directory is 'coverage', but an alternative can be provided as an argument.""" + jacocoreport = mx.library("JACOCOREPORT", True) + out = 'coverage' + if len(args) == 1: + out = args[0] + elif len(args) > 1: + mx.abort('jacocoreport takes only one argument : an output directory') + mx.run_java(['-jar', jacocoreport.get_path(True), '-in', 'jacoco.exec', '-g', join(_graal_home, 'graal'), out]) + +def sl(args): + """run an SL program""" + vmArgs, slArgs = _extract_VM_args(args) + vm(vmArgs + ['-cp', mx.classpath("com.oracle.truffle.sl"), "com.oracle.truffle.sl.SimpleLanguage"] + slArgs) + +def isGraalEnabled(vm): + return vm != 'original' and not vm.endswith('nograal') + +def site(args): + """create a website containing javadoc and the project dependency graph""" + + return mx.site(['--name', 'Graal', + '--jd', '@-tag', '--jd', '@test:X', + '--jd', '@-tag', '--jd', '@run:X', + '--jd', '@-tag', '--jd', '@bug:X', + '--jd', '@-tag', '--jd', '@summary:X', + '--jd', '@-tag', '--jd', '@vmoption:X', + '--overview', join(_graal_home, 'graal', 'overview.html'), + '--title', 'Graal OpenJDK Project Documentation', + '--dot-output-base', 'projects'] + args) + +def mx_init(suite): + commands = { + 'build': [build, ''], + 'buildvars': [buildvars, ''], + 'buildvms': [buildvms, '[-options]'], + 'clean': [clean, ''], + 'hsdis': [hsdis, '[att]'], + 'hcfdis': [hcfdis, ''], + 'igv' : [igv, ''], + 'jdkhome': [print_jdkhome, ''], + 'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'], + 'scaladacapo': [scaladacapo, '[VM options] benchmarks...|"all" [Scala DaCapo options]'], + 'specjvm2008': [specjvm2008, '[VM options] benchmarks...|"all" [SPECjvm2008 options]'], + 'specjbb2013': [specjbb2013, '[VM options] [-- [SPECjbb2013 options]]'], + 'specjbb2005': [specjbb2005, '[VM options] [-- [SPECjbb2005 options]]'], + 'gate' : [gate, '[-options]'], + 'gv' : [gv, ''], + 'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'], + 'unittest' : [unittest, '[VM options] [filters...]', _unittestHelpSuffix], + 'longunittest' : [longunittest, '[VM options] [filters...]', _unittestHelpSuffix], + 'shortunittest' : [shortunittest, '[VM options] [filters...]', _unittestHelpSuffix], + 'jacocoreport' : [jacocoreport, '[output directory]'], + 'site' : [site, '[-options]'], + 'vm': [vm, '[-options] class [args...]'], + 'vmg': [vmg, '[-options] class [args...]'], + 'vmfg': [vmfg, '[-options] class [args...]'], + 'deoptalot' : [deoptalot, '[n]'], + 'longtests' : [longtests, ''], + 'sl' : [sl, '[SL args|@VM options]'] + } + + mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append']) + mx.add_argument('--vmcwd', dest='vm_cwd', help='current directory will be changed to before the VM is executed', default=None, metavar='') + mx.add_argument('--installed-jdks', help='the base directory in which the JDKs cloned from $JAVA_HOME exist. ' + + 'The VM selected by --vm and --vmbuild options is under this directory (i.e., ' + + join('', '', '', 'jre', 'lib', '', mx.add_lib_prefix(mx.add_lib_suffix('jvm'))) + ')', default=None, metavar='') + + if (_vmSourcesAvailable): + mx.add_argument('--vm', action='store', dest='vm', choices=_vmChoices.keys(), help='the VM type to build/run') + mx.add_argument('--vmbuild', action='store', dest='vmbuild', choices=_vmbuildChoices, help='the VM build to build/run (default: ' + _vmbuildChoices[0] + ')') + mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse') + mx.add_argument('--vmprefix', action='store', dest='vm_prefix', help='prefix for running the VM (e.g. "/usr/bin/gdb --args")', metavar='') + mx.add_argument('--gdb', action='store_const', const='/usr/bin/gdb --args', dest='vm_prefix', help='alias for --vmprefix "/usr/bin/gdb --args"') + + commands.update({ + 'export': [export, '[-options] [zipfile]'], + }) + + mx.update_commands(suite, commands) + +def mx_post_parse_cmd_line(opts): # + # TODO _minVersion check could probably be part of a Suite in mx? + if (mx.java().version < _minVersion) : + mx.abort('Requires Java version ' + str(_minVersion) + ' or greater, got version ' + str(mx.java().version)) + + if (_vmSourcesAvailable): + if hasattr(opts, 'vm') and opts.vm is not None: + global _vm + _vm = opts.vm + if hasattr(opts, 'vmbuild') and opts.vmbuild is not None: + global _vmbuild + _vmbuild = opts.vmbuild + global _make_eclipse_launch + _make_eclipse_launch = getattr(opts, 'make_eclipse_launch', False) + global _jacoco + _jacoco = opts.jacoco + global _vm_cwd + _vm_cwd = opts.vm_cwd + global _installed_jdks + _installed_jdks = opts.installed_jdks + global _vm_prefix + _vm_prefix = opts.vm_prefix + + mx.distribution('GRAAL').add_update_listener(_installGraalJarInJdks)