Mercurial > hg > graal-jvmci-8
comparison mx.jvmci/mx_jvmci.py @ 22139:ed35cb998428
Initial split off from monolithic basic-graal repo
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Mon, 06 Jul 2015 14:10:14 +0200 |
parents | mx.graal/mx_graal.py@51ceda0cf404 |
children | 60d9e50d5481 |
comparison
equal
deleted
inserted
replaced
22138:103f53747955 | 22139:ed35cb998428 |
---|---|
1 # | |
2 # ---------------------------------------------------------------------------------------------------- | |
3 # | |
4 # Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. | |
5 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
6 # | |
7 # This code is free software; you can redistribute it and/or modify it | |
8 # under the terms of the GNU General Public License version 2 only, as | |
9 # published by the Free Software Foundation. | |
10 # | |
11 # This code is distributed in the hope that it will be useful, but WITHOUT | |
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 # version 2 for more details (a copy is included in the LICENSE file that | |
15 # accompanied this code). | |
16 # | |
17 # You should have received a copy of the GNU General Public License version | |
18 # 2 along with this work; if not, write to the Free Software Foundation, | |
19 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
20 # | |
21 # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
22 # or visit www.oracle.com if you need additional information or have any | |
23 # questions. | |
24 # | |
25 # ---------------------------------------------------------------------------------------------------- | |
26 | |
27 import os, stat, errno, sys, shutil, zipfile, tarfile, tempfile, re, time, datetime, platform, subprocess, socket | |
28 from os.path import join, exists, dirname, basename | |
29 from argparse import ArgumentParser, REMAINDER | |
30 import xml.dom.minidom | |
31 import json, textwrap | |
32 | |
33 import mx | |
34 import mx_unittest | |
35 import mx_findbugs | |
36 import mx_jvmci_makefile | |
37 | |
38 _suite = mx.suite('jvmci') | |
39 | |
40 """ The VMs that can be built and run along with an optional description. Only VMs with a | |
41 description are listed in the dialogue for setting the default VM (see get_vm()). """ | |
42 _vmChoices = { | |
43 'jvmci' : 'VM triggered compilation is performed with a tiered system (C1 + Graal) and Graal is available for hosted compilation.', | |
44 'server' : 'Normal compilation is performed with a tiered system (C1 + C2) and Graal is available for hosted compilation.', | |
45 'client' : None, # VM compilation with client compiler, hosted compilation with Graal | |
46 'server-nojvmci' : None, # all compilation with tiered system (i.e., client + server), JVMCI omitted | |
47 'client-nojvmci' : None, # all compilation with client compiler, JVMCI omitted | |
48 'original' : None, # default VM copied from bootstrap JDK | |
49 'graal' : None, # alias for jvmci | |
50 'server-nograal' : None, # alias for server-nojvmci | |
51 'client-nograal' : None, # alias for client-nojvmci | |
52 } | |
53 | |
54 """ The VM that will be run by the 'vm' command and built by default by the 'build' command. | |
55 This can be set via the global '--vm' option or the DEFAULT_VM environment variable. | |
56 It can also be temporarily set by using of a VM context manager object in a 'with' statement. """ | |
57 _vm = None | |
58 | |
59 """ The VM builds that will be run by the 'vm' command - default is first in list """ | |
60 _vmbuildChoices = ['product', 'fastdebug', 'debug', 'optimized'] | |
61 | |
62 """ The VM build that will be run by the 'vm' command. | |
63 This can be set via the global '--vmbuild' option. | |
64 It can also be temporarily set by using of a VM context manager object in a 'with' statement. """ | |
65 _vmbuild = _vmbuildChoices[0] | |
66 | |
67 _jacoco = 'off' | |
68 | |
69 """ The current working directory to switch to before running the VM. """ | |
70 _vm_cwd = None | |
71 | |
72 """ The base directory in which the JDKs cloned from $JAVA_HOME exist. """ | |
73 _installed_jdks = None | |
74 | |
75 """ Prefix for running the VM. """ | |
76 _vm_prefix = None | |
77 | |
78 _make_eclipse_launch = False | |
79 | |
80 _minVersion = mx.VersionSpec('1.8') | |
81 | |
82 # max version (first _unsupported_ version) | |
83 _untilVersion = None | |
84 | |
85 class JDKDeployedDist: | |
86 def __init__(self, name, isExtension=False, usesJVMCIClassLoader=False, partOfHotSpot=False): | |
87 self.name = name | |
88 self.isExtension = isExtension | |
89 self.usesJVMCIClassLoader = usesJVMCIClassLoader | |
90 self.partOfHotSpot = partOfHotSpot # true when this distribution is delivered with HotSpot | |
91 | |
92 # A hook called after the jar(s) for this dist have been deployed into a JDK. If not None, | |
93 # this hook is called with these arguments: | |
94 # jdkDir: the root directory of the JDK | |
95 # targetDir: the directory into which the jar(s) were installed | |
96 self.postJdkInstall = None | |
97 | |
98 """ | |
99 List of distributions that are deployed into a JDK by mx. | |
100 """ | |
101 jdkDeployedDists = [ | |
102 JDKDeployedDist('JVMCI_SERVICE', partOfHotSpot=True), | |
103 JDKDeployedDist('JVMCI_API', usesJVMCIClassLoader=True, partOfHotSpot=True), | |
104 JDKDeployedDist('JVMCI_HOTSPOT', usesJVMCIClassLoader=True, partOfHotSpot=True), | |
105 ] | |
106 | |
107 JDK_UNIX_PERMISSIONS_DIR = 0755 | |
108 JDK_UNIX_PERMISSIONS_FILE = 0644 | |
109 JDK_UNIX_PERMISSIONS_EXEC = 0755 | |
110 | |
111 def isVMSupported(vm): | |
112 if 'client' == vm and len(platform.mac_ver()[0]) != 0: | |
113 # Client VM not supported: java launcher on Mac OS X translates '-client' to '-server' | |
114 return False | |
115 return True | |
116 | |
117 def get_vm(): | |
118 """ | |
119 Gets the configured VM, presenting a dialogue if there is no currently configured VM. | |
120 """ | |
121 global _vm | |
122 if _vm: | |
123 return _vm | |
124 vm = mx.get_env('DEFAULT_VM') | |
125 envPath = join(_suite.mxDir, 'env') | |
126 if vm and 'graal' in vm: | |
127 if exists(envPath): | |
128 with open(envPath) as fp: | |
129 if 'DEFAULT_VM=' + vm in fp.read(): | |
130 mx.log('Please update the DEFAULT_VM value in ' + envPath + ' to replace "graal" with "jvmci"') | |
131 vm = vm.replace('graal', 'jvmci') | |
132 if vm is None: | |
133 if not mx.is_interactive(): | |
134 mx.abort('Need to specify VM with --vm option or DEFAULT_VM environment variable') | |
135 mx.log('Please select the VM to be executed from the following: ') | |
136 items = [k for k in _vmChoices.keys() if _vmChoices[k] is not None] | |
137 descriptions = [_vmChoices[k] for k in _vmChoices.keys() if _vmChoices[k] is not None] | |
138 vm = mx.select_items(items, descriptions, allowMultiple=False) | |
139 mx.ask_persist_env('DEFAULT_VM', vm) | |
140 _vm = vm | |
141 return vm | |
142 | |
143 """ | |
144 A context manager that can be used with the 'with' statement to set the VM | |
145 used by all VM executions within the scope of the 'with' statement. For example: | |
146 | |
147 with VM('server'): | |
148 dacapo(['pmd']) | |
149 """ | |
150 class VM: | |
151 def __init__(self, vm=None, build=None): | |
152 assert vm is None or vm in _vmChoices.keys() | |
153 assert build is None or build in _vmbuildChoices | |
154 self.vm = vm if vm else _vm | |
155 self.build = build if build else _vmbuild | |
156 self.previousVm = _vm | |
157 self.previousBuild = _vmbuild | |
158 | |
159 def __enter__(self): | |
160 global _vm, _vmbuild | |
161 _vm = self.vm | |
162 _vmbuild = self.build | |
163 | |
164 def __exit__(self, exc_type, exc_value, traceback): | |
165 global _vm, _vmbuild | |
166 _vm = self.previousVm | |
167 _vmbuild = self.previousBuild | |
168 | |
169 def chmodRecursive(dirname, chmodFlagsDir): | |
170 if mx.get_os() == 'windows': | |
171 return | |
172 | |
173 def _chmodDir(chmodFlags, dirname, fnames): | |
174 os.chmod(dirname, chmodFlagsDir) | |
175 | |
176 os.path.walk(dirname, _chmodDir, chmodFlagsDir) | |
177 | |
178 def clean(args): | |
179 """clean the source tree""" | |
180 opts = mx.clean(args, parser=ArgumentParser(prog='mx clean')) | |
181 | |
182 if opts.native: | |
183 def handleRemoveReadonly(func, path, exc): | |
184 excvalue = exc[1] | |
185 if mx.get_os() == 'windows' and func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES: | |
186 os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777 | |
187 func(path) | |
188 else: | |
189 raise | |
190 | |
191 def rmIfExists(name): | |
192 if os.path.isdir(name): | |
193 shutil.rmtree(name, ignore_errors=False, onerror=handleRemoveReadonly) | |
194 elif os.path.isfile(name): | |
195 os.unlink(name) | |
196 | |
197 rmIfExists(join(_suite.dir, 'build')) | |
198 rmIfExists(join(_suite.dir, 'build-nojvmci')) | |
199 rmIfExists(_jdksDir()) | |
200 | |
201 def export(args): | |
202 """create archives of builds split by vmbuild and vm""" | |
203 | |
204 parser = ArgumentParser(prog='mx export') | |
205 args = parser.parse_args(args) | |
206 | |
207 # collect data about export | |
208 infos = dict() | |
209 infos['timestamp'] = time.time() | |
210 | |
211 hgcfg = mx.HgConfig() | |
212 hgcfg.check() | |
213 infos['revision'] = hgcfg.tip('.') + ('+' if hgcfg.isDirty('.') else '') | |
214 # TODO: infos['repository'] | |
215 | |
216 infos['jdkversion'] = str(mx.java().version) | |
217 | |
218 infos['architecture'] = mx.get_arch() | |
219 infos['platform'] = mx.get_os() | |
220 | |
221 if mx.get_os != 'windows': | |
222 pass | |
223 # infos['ccompiler'] | |
224 # infos['linker'] | |
225 | |
226 infos['hostname'] = socket.gethostname() | |
227 | |
228 def _writeJson(suffix, properties): | |
229 d = infos.copy() | |
230 for k, v in properties.iteritems(): | |
231 assert not d.has_key(k) | |
232 d[k] = v | |
233 | |
234 jsonFileName = 'export-' + suffix + '.json' | |
235 with open(jsonFileName, 'w') as f: | |
236 print >> f, json.dumps(d) | |
237 return jsonFileName | |
238 | |
239 | |
240 def _genFileName(archivtype, middle): | |
241 idPrefix = infos['revision'] + '_' | |
242 idSuffix = '.tar.gz' | |
243 return join(_suite.dir, "graalvm_" + archivtype + "_" + idPrefix + middle + idSuffix) | |
244 | |
245 def _genFileArchPlatformName(archivtype, middle): | |
246 return _genFileName(archivtype, infos['platform'] + '_' + infos['architecture'] + '_' + middle) | |
247 | |
248 | |
249 # archive different build types of hotspot | |
250 for vmBuild in _vmbuildChoices: | |
251 jdkpath = join(_jdksDir(), vmBuild) | |
252 if not exists(jdkpath): | |
253 mx.logv("skipping " + vmBuild) | |
254 continue | |
255 | |
256 tarName = _genFileArchPlatformName('basejdk', vmBuild) | |
257 mx.logv("creating basejdk " + tarName) | |
258 vmSet = set() | |
259 with tarfile.open(tarName, 'w:gz') as tar: | |
260 for root, _, files in os.walk(jdkpath): | |
261 if basename(root) in _vmChoices.keys(): | |
262 # TODO: add some assert to check path assumption | |
263 vmSet.add(root) | |
264 continue | |
265 | |
266 for f in files: | |
267 name = join(root, f) | |
268 # print name | |
269 tar.add(name, name) | |
270 | |
271 n = _writeJson("basejdk-" + vmBuild, {'vmbuild' : vmBuild}) | |
272 tar.add(n, n) | |
273 | |
274 # create a separate archive for each VM | |
275 for vm in vmSet: | |
276 bVm = basename(vm) | |
277 vmTarName = _genFileArchPlatformName('vm', vmBuild + '_' + bVm) | |
278 mx.logv("creating vm " + vmTarName) | |
279 | |
280 debugFiles = set() | |
281 with tarfile.open(vmTarName, 'w:gz') as tar: | |
282 for root, _, files in os.walk(vm): | |
283 for f in files: | |
284 # TODO: mac, windows, solaris? | |
285 if any(map(f.endswith, [".debuginfo"])): | |
286 debugFiles.add(f) | |
287 else: | |
288 name = join(root, f) | |
289 # print name | |
290 tar.add(name, name) | |
291 | |
292 n = _writeJson("vm-" + vmBuild + "-" + bVm, {'vmbuild' : vmBuild, 'vm' : bVm}) | |
293 tar.add(n, n) | |
294 | |
295 if len(debugFiles) > 0: | |
296 debugTarName = _genFileArchPlatformName('debugfilesvm', vmBuild + '_' + bVm) | |
297 mx.logv("creating debugfilesvm " + debugTarName) | |
298 with tarfile.open(debugTarName, 'w:gz') as tar: | |
299 for f in debugFiles: | |
300 name = join(root, f) | |
301 # print name | |
302 tar.add(name, name) | |
303 | |
304 n = _writeJson("debugfilesvm-" + vmBuild + "-" + bVm, {'vmbuild' : vmBuild, 'vm' : bVm}) | |
305 tar.add(n, n) | |
306 | |
307 # jvmci directory | |
308 jvmciDirTarName = _genFileName('classfiles', 'javac') | |
309 mx.logv("creating jvmci " + jvmciDirTarName) | |
310 with tarfile.open(jvmciDirTarName, 'w:gz') as tar: | |
311 for root, _, files in os.walk("jvmci"): | |
312 for f in [f for f in files if not f.endswith('.java')]: | |
313 name = join(root, f) | |
314 # print name | |
315 tar.add(name, name) | |
316 | |
317 n = _writeJson("jvmci", {'javacompiler' : 'javac'}) | |
318 tar.add(n, n) | |
319 | |
320 def _vmLibDirInJdk(jdk): | |
321 """ | |
322 Gets the directory within a JDK where the server and client | |
323 sub-directories are located. | |
324 """ | |
325 mxos = mx.get_os() | |
326 if mxos == 'darwin': | |
327 return join(jdk, 'jre', 'lib') | |
328 if mxos == 'windows' or mxos == 'cygwin': | |
329 return join(jdk, 'jre', 'bin') | |
330 return join(jdk, 'jre', 'lib', mx.get_arch()) | |
331 | |
332 def _vmJliLibDirs(jdk): | |
333 """ | |
334 Get the directories within a JDK where the jli library designates to. | |
335 """ | |
336 mxos = mx.get_os() | |
337 if mxos == 'darwin': | |
338 return [join(jdk, 'jre', 'lib', 'jli')] | |
339 if mxos == 'windows' or mxos == 'cygwin': | |
340 return [join(jdk, 'jre', 'bin'), join(jdk, 'bin')] | |
341 return [join(jdk, 'jre', 'lib', mx.get_arch(), 'jli'), join(jdk, 'lib', mx.get_arch(), 'jli')] | |
342 | |
343 def _vmCfgInJdk(jdk, jvmCfgFile='jvm.cfg'): | |
344 """ | |
345 Get the jvm.cfg file. | |
346 """ | |
347 mxos = mx.get_os() | |
348 if mxos == "windows" or mxos == "cygwin": | |
349 return join(jdk, 'jre', 'lib', mx.get_arch(), jvmCfgFile) | |
350 return join(_vmLibDirInJdk(jdk), jvmCfgFile) | |
351 | |
352 def _jdksDir(): | |
353 return os.path.abspath(join(_installed_jdks if _installed_jdks else _suite.dir, 'jdk' + str(mx.java().version))) | |
354 | |
355 def _handle_missing_VM(bld, vm=None): | |
356 if not vm: | |
357 vm = get_vm() | |
358 mx.log('The ' + bld + ' ' + vm + ' VM has not been created') | |
359 if mx.is_interactive(): | |
360 if mx.ask_yes_no('Build it now', 'y'): | |
361 with VM(vm, bld): | |
362 build([]) | |
363 return | |
364 mx.abort('You need to run "mx --vm ' + vm + ' --vmbuild ' + bld + ' build" to build the selected VM') | |
365 | |
366 def _jdk(build=None, vmToCheck=None, create=False, installJars=True): | |
367 """ | |
368 Get the JDK into which JVMCI is installed, creating it first if necessary. | |
369 """ | |
370 if not build: | |
371 build = _vmbuild | |
372 jdk = join(_jdksDir(), build) | |
373 if create: | |
374 srcJdk = mx.java().jdk | |
375 if not exists(jdk): | |
376 mx.log('Creating ' + jdk + ' from ' + srcJdk) | |
377 shutil.copytree(srcJdk, jdk) | |
378 | |
379 # Make a copy of the default VM so that this JDK can be | |
380 # reliably used as the bootstrap for a HotSpot build. | |
381 jvmCfg = _vmCfgInJdk(jdk) | |
382 if not exists(jvmCfg): | |
383 mx.abort(jvmCfg + ' does not exist') | |
384 | |
385 defaultVM = None | |
386 jvmCfgLines = [] | |
387 with open(jvmCfg) as f: | |
388 for line in f: | |
389 if line.startswith('-') and defaultVM is None: | |
390 parts = line.split() | |
391 if len(parts) == 2: | |
392 assert parts[1] == 'KNOWN', parts[1] | |
393 defaultVM = parts[0][1:] | |
394 jvmCfgLines += ['# default VM is a copy of the unmodified ' + defaultVM + ' VM\n'] | |
395 jvmCfgLines += ['-original KNOWN\n'] | |
396 else: | |
397 # skip lines which we cannot parse (e.g. '-hotspot ALIASED_TO -client') | |
398 mx.log("WARNING: skipping not parsable line \"" + line + "\"") | |
399 else: | |
400 jvmCfgLines += [line] | |
401 | |
402 assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg | |
403 chmodRecursive(jdk, JDK_UNIX_PERMISSIONS_DIR) | |
404 shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'original')) | |
405 | |
406 if mx.get_os() != 'windows': | |
407 os.chmod(jvmCfg, JDK_UNIX_PERMISSIONS_FILE) | |
408 with open(jvmCfg, 'w') as fp: | |
409 for line in jvmCfgLines: | |
410 fp.write(line) | |
411 | |
412 # patch 'release' file (append jvmci revision) | |
413 releaseFile = join(jdk, 'release') | |
414 if exists(releaseFile): | |
415 releaseFileLines = [] | |
416 with open(releaseFile) as f: | |
417 for line in f: | |
418 releaseFileLines.append(line) | |
419 | |
420 if mx.get_os() != 'windows': | |
421 os.chmod(releaseFile, JDK_UNIX_PERMISSIONS_FILE) | |
422 with open(releaseFile, 'w') as fp: | |
423 for line in releaseFileLines: | |
424 if line.startswith("SOURCE="): | |
425 try: | |
426 sourceLine = line[0:-2] # remove last char | |
427 hgcfg = mx.HgConfig() | |
428 hgcfg.check() | |
429 revision = hgcfg.tip('.')[:12] # take first 12 chars | |
430 fp.write(sourceLine + ' jvmci:' + revision + '\"\n') | |
431 except: | |
432 fp.write(line) | |
433 else: | |
434 fp.write(line) | |
435 | |
436 # Install a copy of the disassembler library | |
437 try: | |
438 hsdis([], copyToDir=_vmLibDirInJdk(jdk)) | |
439 except SystemExit: | |
440 pass | |
441 else: | |
442 if not exists(jdk): | |
443 if _installed_jdks: | |
444 mx.log("The selected JDK directory does not (yet) exist: " + jdk) | |
445 _handle_missing_VM(build, vmToCheck) | |
446 | |
447 if installJars: | |
448 for jdkDist in jdkDeployedDists: | |
449 dist = mx.distribution(jdkDist.name) | |
450 if exists(dist.path) and jdkDist.partOfHotSpot: | |
451 _installDistInJdks(jdkDist) | |
452 | |
453 if vmToCheck is not None: | |
454 jvmCfg = _vmCfgInJdk(jdk) | |
455 found = False | |
456 with open(jvmCfg) as f: | |
457 for line in f: | |
458 if line.strip() == '-' + vmToCheck + ' KNOWN': | |
459 found = True | |
460 break | |
461 if not found: | |
462 _handle_missing_VM(build, vmToCheck) | |
463 | |
464 return jdk | |
465 | |
466 def _updateInstalledJVMCIOptionsFile(jdk): | |
467 jvmciOptions = join(_suite.dir, 'jvmci.options') | |
468 jreLibDir = join(jdk, 'jre', 'lib') | |
469 if exists(jvmciOptions): | |
470 shutil.copy(jvmciOptions, join(jreLibDir, 'jvmci.options')) | |
471 else: | |
472 toDelete = join(jreLibDir, 'jvmci.options') | |
473 if exists(toDelete): | |
474 os.unlink(toDelete) | |
475 | |
476 def _makeHotspotGeneratedSourcesDir(): | |
477 """ | |
478 Gets the directory containing all the HotSpot sources generated from | |
479 JVMCI Java sources. This directory will be created if it doesn't yet exist. | |
480 """ | |
481 hsSrcGenDir = join(mx.project('jdk.internal.jvmci.hotspot').source_gen_dir(), 'hotspot') | |
482 if not exists(hsSrcGenDir): | |
483 os.makedirs(hsSrcGenDir) | |
484 return hsSrcGenDir | |
485 | |
486 def _copyToJdk(src, dst, permissions=JDK_UNIX_PERMISSIONS_FILE): | |
487 name = os.path.basename(src) | |
488 dstLib = join(dst, name) | |
489 if mx.get_env('SYMLINK_GRAAL_JAR', None) == 'true': | |
490 # Using symlinks is much faster than copying but may | |
491 # cause issues if the lib is being updated while | |
492 # the VM is running. | |
493 if not os.path.islink(dstLib) or not os.path.realpath(dstLib) == src: | |
494 if exists(dstLib): | |
495 os.remove(dstLib) | |
496 os.symlink(src, dstLib) | |
497 else: | |
498 # do a copy and then a move to get atomic updating (on Unix) | |
499 fd, tmp = tempfile.mkstemp(suffix='', prefix=name, dir=dst) | |
500 shutil.copyfile(src, tmp) | |
501 os.close(fd) | |
502 shutil.move(tmp, dstLib) | |
503 os.chmod(dstLib, permissions) | |
504 | |
505 def _extractJVMCIFiles(jdkJars, jvmciJars, servicesDir, optionsDir): | |
506 | |
507 oldServices = os.listdir(servicesDir) if exists(servicesDir) else os.makedirs(servicesDir) | |
508 oldOptions = os.listdir(optionsDir) if exists(optionsDir) else os.makedirs(optionsDir) | |
509 | |
510 jvmciServices = {} | |
511 optionsFiles = [] | |
512 for jar in jvmciJars: | |
513 if os.path.isfile(jar): | |
514 with zipfile.ZipFile(jar) as zf: | |
515 for member in zf.namelist(): | |
516 if member.startswith('META-INF/jvmci.services/') and member != 'META-INF/jvmci.services/': | |
517 service = basename(member) | |
518 assert service != "", member | |
519 with zf.open(member) as serviceFile: | |
520 providers = jvmciServices.setdefault(service, []) | |
521 for line in serviceFile.readlines(): | |
522 line = line.strip() | |
523 if line: | |
524 providers.append(line) | |
525 elif member.startswith('META-INF/jvmci.options/') and member != 'META-INF/jvmci.options/': | |
526 filename = basename(member) | |
527 assert filename != "", member | |
528 targetpath = join(optionsDir, filename) | |
529 optionsFiles.append(filename) | |
530 with zf.open(member) as optionsFile, \ | |
531 file(targetpath, "wb") as target: | |
532 shutil.copyfileobj(optionsFile, target) | |
533 if oldOptions and filename in oldOptions: | |
534 oldOptions.remove(filename) | |
535 for service, providers in jvmciServices.iteritems(): | |
536 fd, tmp = tempfile.mkstemp(prefix=service) | |
537 f = os.fdopen(fd, 'w+') | |
538 for provider in providers: | |
539 f.write(provider + os.linesep) | |
540 target = join(servicesDir, service) | |
541 f.close() | |
542 shutil.move(tmp, target) | |
543 if oldServices and service in oldServices: | |
544 oldServices.remove(service) | |
545 if mx.get_os() != 'windows': | |
546 os.chmod(target, JDK_UNIX_PERMISSIONS_FILE) | |
547 | |
548 if mx.is_interactive(): | |
549 for d, files in [(servicesDir, oldServices), (optionsDir, oldOptions)]: | |
550 if files and mx.ask_yes_no('These files in ' + d + ' look obsolete:\n ' + '\n '.join(files) + '\nDelete them', 'n'): | |
551 for f in files: | |
552 path = join(d, f) | |
553 os.remove(path) | |
554 mx.log('Deleted ' + path) | |
555 | |
556 def _updateJVMCIFiles(jdkDir): | |
557 jreJVMCIDir = join(jdkDir, 'jre', 'lib', 'jvmci') | |
558 jvmciJars = [join(jreJVMCIDir, e) for e in os.listdir(jreJVMCIDir) if e.endswith('.jar')] | |
559 jreJVMCIServicesDir = join(jreJVMCIDir, 'services') | |
560 jreJVMCIOptionsDir = join(jreJVMCIDir, 'options') | |
561 _extractJVMCIFiles(_getJdkDeployedJars(jdkDir), jvmciJars, jreJVMCIServicesDir, jreJVMCIOptionsDir) | |
562 | |
563 def _installDistInJdks(deployableDist): | |
564 """ | |
565 Installs the jar(s) for a given Distribution into all existing JVMCI JDKs | |
566 """ | |
567 dist = mx.distribution(deployableDist.name) | |
568 jdks = _jdksDir() | |
569 if exists(jdks): | |
570 for e in os.listdir(jdks): | |
571 jdkDir = join(jdks, e) | |
572 jreLibDir = join(jdkDir, 'jre', 'lib') | |
573 if exists(jreLibDir): | |
574 if deployableDist.isExtension: | |
575 targetDir = join(jreLibDir, 'ext') | |
576 elif deployableDist.usesJVMCIClassLoader: | |
577 targetDir = join(jreLibDir, 'jvmci') | |
578 else: | |
579 targetDir = jreLibDir | |
580 if not exists(targetDir): | |
581 os.makedirs(targetDir) | |
582 _copyToJdk(dist.path, targetDir) | |
583 if dist.sourcesPath: | |
584 _copyToJdk(dist.sourcesPath, jdkDir) | |
585 if deployableDist.usesJVMCIClassLoader: | |
586 # deploy service files | |
587 _updateJVMCIFiles(jdkDir) | |
588 if deployableDist.postJdkInstall: | |
589 deployableDist.postJdkInstall(jdkDir, targetDir) | |
590 | |
591 def _getJdkDeployedJars(jdkDir): | |
592 """ | |
593 Gets jar paths for all deployed distributions in the context of | |
594 a given JDK directory. | |
595 """ | |
596 jreLibDir = join(jdkDir, 'jre', 'lib') | |
597 jars = [] | |
598 for dist in jdkDeployedDists: | |
599 jar = basename(mx.distribution(dist.name).path) | |
600 if dist.isExtension: | |
601 jars.append(join(jreLibDir, 'ext', jar)) | |
602 elif dist.usesJVMCIClassLoader: | |
603 jars.append(join(jreLibDir, 'jvmci', jar)) | |
604 else: | |
605 jars.append(join(jreLibDir, jar)) | |
606 return jars | |
607 | |
608 | |
609 # run a command in the windows SDK Debug Shell | |
610 def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None): | |
611 if respondTo is None: | |
612 respondTo = {} | |
613 newLine = os.linesep | |
614 startToken = 'RUNINDEBUGSHELL_STARTSEQUENCE' | |
615 endToken = 'RUNINDEBUGSHELL_ENDSEQUENCE' | |
616 | |
617 winSDK = mx.get_env('WIN_SDK', 'C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\') | |
618 | |
619 if not exists(mx._cygpathW2U(winSDK)): | |
620 mx.abort("Could not find Windows SDK : '" + winSDK + "' does not exist") | |
621 | |
622 winSDKSetEnv = mx._cygpathW2U(join(winSDK, 'Bin', 'SetEnv.cmd')) | |
623 if not exists(winSDKSetEnv): | |
624 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)") | |
625 | |
626 wincmd = 'cmd.exe /E:ON /V:ON /K "' + mx._cygpathU2W(winSDKSetEnv) + '"' | |
627 p = subprocess.Popen(wincmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | |
628 stdout = p.stdout | |
629 stdin = p.stdin | |
630 if logFile: | |
631 log = open(logFile, 'w') | |
632 ret = False | |
633 | |
634 def _writeProcess(s): | |
635 stdin.write(s + newLine) | |
636 | |
637 _writeProcess("echo " + startToken) | |
638 while True: | |
639 # encoding may be None on windows plattforms | |
640 if sys.stdout.encoding is None: | |
641 encoding = 'utf-8' | |
642 else: | |
643 encoding = sys.stdout.encoding | |
644 | |
645 line = stdout.readline().decode(encoding) | |
646 if logFile: | |
647 log.write(line.encode('utf-8')) | |
648 line = line.strip() | |
649 mx.log(line) | |
650 if line == startToken: | |
651 _writeProcess('cd /D ' + workingDir + ' & ' + cmd + ' & echo ' + endToken) | |
652 for regex in respondTo.keys(): | |
653 match = regex.search(line) | |
654 if match: | |
655 _writeProcess(respondTo[regex]) | |
656 if findInOutput: | |
657 match = findInOutput.search(line) | |
658 if match: | |
659 ret = True | |
660 if line == endToken: | |
661 if not findInOutput: | |
662 _writeProcess('echo ERRXXX%errorlevel%') | |
663 else: | |
664 break | |
665 if line.startswith('ERRXXX'): | |
666 if line == 'ERRXXX0': | |
667 ret = True | |
668 break | |
669 _writeProcess("exit") | |
670 if logFile: | |
671 log.close() | |
672 return ret | |
673 | |
674 def jdkhome(vm=None): | |
675 """return the JDK directory selected for the 'vm' command""" | |
676 return _jdk(installJars=False) | |
677 | |
678 def print_jdkhome(args, vm=None): | |
679 """print the JDK directory selected for the 'vm' command""" | |
680 print jdkhome(vm) | |
681 | |
682 def buildvars(args): | |
683 """describe the variables that can be set by the -D option to the 'mx build' commmand""" | |
684 | |
685 buildVars = { | |
686 'ALT_BOOTDIR' : 'The location of the bootstrap JDK installation (default: ' + mx.java().jdk + ')', | |
687 'ALT_OUTPUTDIR' : 'Build directory', | |
688 'HOTSPOT_BUILD_JOBS' : 'Number of CPUs used by make (default: ' + str(mx.cpu_count()) + ')', | |
689 'INSTALL' : 'Install the built VM into the JDK? (default: y)', | |
690 'ZIP_DEBUGINFO_FILES' : 'Install zipped debug symbols file? (default: 0)', | |
691 } | |
692 | |
693 mx.log('HotSpot build variables that can be set by the -D option to "mx build":') | |
694 mx.log('') | |
695 for n in sorted(buildVars.iterkeys()): | |
696 mx.log(n) | |
697 mx.log(textwrap.fill(buildVars[n], initial_indent=' ', subsequent_indent=' ', width=200)) | |
698 | |
699 mx.log('') | |
700 mx.log('Note that these variables can be given persistent values in the file ' + join(_suite.mxDir, 'env') + ' (see \'mx about\').') | |
701 | |
702 cached_graal_version = None | |
703 | |
704 def build(args, vm=None): | |
705 """build the VM binary | |
706 | |
707 The global '--vm' and '--vmbuild' options select which VM type and build target to build.""" | |
708 | |
709 # Override to fail quickly if extra arguments are given | |
710 # at the end of the command line. This allows for a more | |
711 # helpful error message. | |
712 class AP(ArgumentParser): | |
713 def __init__(self): | |
714 ArgumentParser.__init__(self, prog='mx build') | |
715 def parse_args(self, args): | |
716 result = ArgumentParser.parse_args(self, args) | |
717 if len(result.remainder) != 0: | |
718 firstBuildTarget = result.remainder[0] | |
719 mx.abort('To specify the ' + firstBuildTarget + ' VM build target, you need to use the global "--vmbuild" option. For example:\n' + | |
720 ' mx --vmbuild ' + firstBuildTarget + ' build') | |
721 return result | |
722 | |
723 # Call mx.build to compile the Java sources | |
724 parser = AP() | |
725 parser.add_argument('-D', action='append', help='set a HotSpot build variable (run \'mx buildvars\' to list variables)', metavar='name=value') | |
726 | |
727 opts2 = mx.build(['--source', '1.7'] + args, parser=parser) | |
728 assert len(opts2.remainder) == 0 | |
729 | |
730 if not opts2.native: | |
731 return | |
732 | |
733 builds = [_vmbuild] | |
734 | |
735 if os.environ.get('BUILDING_FROM_IDE', None) == 'true': | |
736 build = os.environ.get('IDE_BUILD_TARGET', None) | |
737 if build is None or len(build) == 0: | |
738 return | |
739 if build not in _vmbuildChoices: | |
740 mx.abort('VM build "' + build + '" specified by IDE_BUILD_TARGET environment variable is unknown (must be one of ' + | |
741 str(_vmbuildChoices) + ')') | |
742 builds = [build] | |
743 | |
744 if vm is None: | |
745 vm = get_vm() | |
746 | |
747 if vm == 'original': | |
748 pass | |
749 elif vm.startswith('server'): | |
750 buildSuffix = '' | |
751 elif vm.startswith('client'): | |
752 buildSuffix = '1' | |
753 else: | |
754 assert vm == 'jvmci', vm | |
755 buildSuffix = 'jvmci' | |
756 | |
757 if _installed_jdks and _installed_jdks != _suite.dir: | |
758 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'): | |
759 mx.abort(1) | |
760 | |
761 isWindows = platform.system() == 'Windows' or "CYGWIN" in platform.system() | |
762 for build in builds: | |
763 installJars = vm != 'original' and (isWindows or not opts2.java) | |
764 jdk = _jdk(build, create=True, installJars=installJars) | |
765 | |
766 if vm == 'original': | |
767 if build != 'product': | |
768 mx.log('only product build of original VM exists') | |
769 continue | |
770 | |
771 if not isVMSupported(vm): | |
772 mx.log('The ' + vm + ' VM is not supported on this platform - skipping') | |
773 continue | |
774 | |
775 vmDir = join(_vmLibDirInJdk(jdk), vm) | |
776 if not exists(vmDir): | |
777 chmodRecursive(jdk, JDK_UNIX_PERMISSIONS_DIR) | |
778 mx.log('Creating VM directory in JDK: ' + vmDir) | |
779 os.makedirs(vmDir) | |
780 | |
781 def filterXusage(line): | |
782 if not 'Xusage.txt' in line: | |
783 sys.stderr.write(line + os.linesep) | |
784 | |
785 # Check if a build really needs to be done | |
786 timestampFile = join(vmDir, '.build-timestamp') | |
787 if opts2.force or not exists(timestampFile): | |
788 mustBuild = True | |
789 else: | |
790 mustBuild = False | |
791 timestamp = os.path.getmtime(timestampFile) | |
792 sources = [] | |
793 for d in ['src', 'make', join('jvmci', 'jdk.internal.jvmci.hotspot', 'src_gen', 'hotspot')]: | |
794 for root, dirnames, files in os.walk(join(_suite.dir, d)): | |
795 # ignore <graal>/src/share/tools | |
796 if root == join(_suite.dir, 'src', 'share'): | |
797 dirnames.remove('tools') | |
798 sources += [join(root, name) for name in files] | |
799 for f in sources: | |
800 if len(f) != 0 and os.path.getmtime(f) > timestamp: | |
801 mustBuild = True | |
802 break | |
803 | |
804 if not mustBuild: | |
805 mx.logv('[all files in src and make directories are older than ' + timestampFile[len(_suite.dir) + 1:] + ' - skipping native build]') | |
806 continue | |
807 | |
808 if isWindows: | |
809 t_compilelogfile = mx._cygpathU2W(os.path.join(_suite.dir, "graalCompile.log")) | |
810 mksHome = mx.get_env('MKS_HOME', 'C:\\cygwin\\bin') | |
811 | |
812 variant = {'client': 'compiler1', 'server': 'compiler2'}.get(vm, vm) | |
813 project_config = variant + '_' + build | |
814 jvmciHome = mx._cygpathU2W(_suite.dir) | |
815 _runInDebugShell('msbuild ' + jvmciHome + r'\build\vs-amd64\jvm.vcproj /p:Configuration=' + project_config + ' /target:clean', jvmciHome) | |
816 winCompileCmd = r'set HotSpotMksHome=' + mksHome + r'& set OUT_DIR=' + mx._cygpathU2W(jdk) + r'& set JAVA_HOME=' + mx._cygpathU2W(jdk) + r'& set path=%JAVA_HOME%\bin;%path%;%HotSpotMksHome%& cd /D "' + jvmciHome + r'\make\windows"& call create.bat ' + jvmciHome | |
817 print winCompileCmd | |
818 winCompileSuccess = re.compile(r"^Writing \.vcxproj file:") | |
819 if not _runInDebugShell(winCompileCmd, jvmciHome, t_compilelogfile, winCompileSuccess): | |
820 mx.log('Error executing create command') | |
821 return | |
822 winBuildCmd = 'msbuild ' + jvmciHome + r'\build\vs-amd64\jvm.vcxproj /p:Configuration=' + project_config + ' /p:Platform=x64' | |
823 if not _runInDebugShell(winBuildCmd, jvmciHome, t_compilelogfile): | |
824 mx.log('Error building project') | |
825 return | |
826 else: | |
827 cpus = mx.cpu_count() | |
828 makeDir = join(_suite.dir, 'make') | |
829 runCmd = [mx.gmake_cmd(), '-C', makeDir] | |
830 | |
831 env = os.environ.copy() | |
832 | |
833 # These must be passed as environment variables | |
834 env.setdefault('LANG', 'C') | |
835 env['JAVA_HOME'] = jdk | |
836 | |
837 def setMakeVar(name, default, env=None): | |
838 """Sets a make variable on the command line to the value | |
839 of the variable in 'env' with the same name if defined | |
840 and 'env' is not None otherwise to 'default' | |
841 """ | |
842 runCmd.append(name + '=' + (env.get(name, default) if env else default)) | |
843 | |
844 if opts2.D: | |
845 for nv in opts2.D: | |
846 name, value = nv.split('=', 1) | |
847 setMakeVar(name.strip(), value) | |
848 | |
849 setMakeVar('ARCH_DATA_MODEL', '64', env=env) | |
850 setMakeVar('HOTSPOT_BUILD_JOBS', str(cpus), env=env) | |
851 setMakeVar('ALT_BOOTDIR', mx.java().jdk, env=env) | |
852 setMakeVar("EXPORT_PATH", jdk) | |
853 | |
854 setMakeVar('MAKE_VERBOSE', 'y' if mx._opts.verbose else '') | |
855 if vm.endswith('nojvmci'): | |
856 setMakeVar('INCLUDE_JVMCI', 'false') | |
857 setMakeVar('ALT_OUTPUTDIR', join(_suite.dir, 'build-nojvmci', mx.get_os()), env=env) | |
858 else: | |
859 version = _suite.release_version() | |
860 setMakeVar('USER_RELEASE_SUFFIX', 'jvmci-' + version) | |
861 setMakeVar('INCLUDE_JVMCI', 'true') | |
862 setMakeVar('INSTALL', 'y', env=env) | |
863 if mx.get_os() == 'darwin' and platform.mac_ver()[0] != '': | |
864 # Force use of clang on MacOS | |
865 setMakeVar('USE_CLANG', 'true') | |
866 if mx.get_os() == 'solaris': | |
867 # If using sparcWorks, setup flags to avoid make complaining about CC version | |
868 cCompilerVersion = subprocess.Popen('CC -V', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).stderr.readlines()[0] | |
869 if cCompilerVersion.startswith('CC: Sun C++'): | |
870 compilerRev = cCompilerVersion.split(' ')[3] | |
871 setMakeVar('ENFORCE_COMPILER_REV', compilerRev, env=env) | |
872 setMakeVar('ENFORCE_CC_COMPILER_REV', compilerRev, env=env) | |
873 if build == 'jvmg': | |
874 # We want ALL the symbols when debugging on Solaris | |
875 setMakeVar('STRIP_POLICY', 'no_strip') | |
876 # This removes the need to unzip the *.diz files before debugging in gdb | |
877 setMakeVar('ZIP_DEBUGINFO_FILES', '0', env=env) | |
878 | |
879 if buildSuffix == "1": | |
880 setMakeVar("BUILD_CLIENT_ONLY", "true") | |
881 | |
882 # Clear this variable as having it set can cause very confusing build problems | |
883 env.pop('CLASSPATH', None) | |
884 | |
885 # Issue an env prefix that can be used to run the make on the command line | |
886 if not mx._opts.verbose: | |
887 mx.log('--------------- make command line ----------------------') | |
888 | |
889 envPrefix = ' '.join([key + '=' + env[key] for key in env.iterkeys() if not os.environ.has_key(key) or env[key] != os.environ[key]]) | |
890 if len(envPrefix): | |
891 mx.log('env ' + envPrefix + ' \\') | |
892 | |
893 runCmd.append(build + buildSuffix) | |
894 runCmd.append("docs") | |
895 runCmd.append("export_" + build) | |
896 | |
897 if not mx._opts.verbose: | |
898 mx.log(' '.join(runCmd)) | |
899 mx.log('--------------------------------------------------------') | |
900 mx.run(runCmd, err=filterXusage, env=env) | |
901 | |
902 jvmCfg = _vmCfgInJdk(jdk) | |
903 if not exists(jvmCfg): | |
904 mx.abort(jvmCfg + ' does not exist') | |
905 | |
906 prefix = '-' + vm + ' ' | |
907 vmKnown = prefix + 'KNOWN\n' | |
908 lines = [] | |
909 found = False | |
910 with open(jvmCfg) as f: | |
911 for line in f: | |
912 if line.strip() == vmKnown.strip(): | |
913 found = True | |
914 lines.append(line) | |
915 | |
916 if not found: | |
917 mx.log('Prepending "' + prefix + 'KNOWN" to ' + jvmCfg) | |
918 if mx.get_os() != 'windows': | |
919 os.chmod(jvmCfg, JDK_UNIX_PERMISSIONS_FILE) | |
920 with open(jvmCfg, 'w') as f: | |
921 written = False | |
922 for line in lines: | |
923 if line.startswith('#'): | |
924 f.write(line) | |
925 continue | |
926 if not written: | |
927 f.write(vmKnown) | |
928 if vm == 'jvmci': | |
929 # Legacy support | |
930 f.write('-graal ALIASED_TO -jvmci\n') | |
931 written = True | |
932 if line.startswith(prefix): | |
933 line = vmKnown | |
934 if written: | |
935 continue | |
936 f.write(line) | |
937 | |
938 for jdkDist in jdkDeployedDists: # Install non HotSpot distribution | |
939 if not jdkDist.partOfHotSpot: | |
940 _installDistInJdks(jdkDist) | |
941 if exists(timestampFile): | |
942 os.utime(timestampFile, None) | |
943 else: | |
944 file(timestampFile, 'a') | |
945 | |
946 """ | |
947 The base list of JaCoCo includes. | |
948 """ | |
949 jacocoIncludes = ['@Test'] | |
950 | |
951 """ | |
952 The list of annotations which if present denote a class that should | |
953 be excluded from JaCoCo analysis. | |
954 """ | |
955 jacocoExcludedAnnotations = ['@Test'] | |
956 | |
957 def parseVmArgs(args, vm=None, cwd=None, vmbuild=None): | |
958 """run the VM selected by the '--vm' option""" | |
959 | |
960 if vm is None: | |
961 vm = get_vm() | |
962 | |
963 if not isVMSupported(vm): | |
964 mx.abort('The ' + vm + ' is not supported on this platform') | |
965 | |
966 if cwd is None: | |
967 cwd = _vm_cwd | |
968 elif _vm_cwd is not None and _vm_cwd != cwd: | |
969 mx.abort("conflicting working directories: do not set --vmcwd for this command") | |
970 | |
971 build = vmbuild if vmbuild else _vmbuild | |
972 jdk = _jdk(build, vmToCheck=vm, installJars=False) | |
973 _updateInstalledJVMCIOptionsFile(jdk) | |
974 mx.expand_project_in_args(args) | |
975 if _make_eclipse_launch: | |
976 mx.make_eclipse_launch(_suite, args, _suite.name + '-' + build, name=None, deps=mx.sorted_deps(includeLibs=True)) | |
977 if _jacoco == 'on' or _jacoco == 'append': | |
978 jacocoagent = mx.library("JACOCOAGENT", True) | |
979 # Exclude all compiler tests and snippets | |
980 | |
981 includes = list(jacocoIncludes) | |
982 baseExcludes = [] | |
983 for p in mx.projects(): | |
984 projsetting = getattr(p, 'jacoco', '') | |
985 if projsetting == 'exclude': | |
986 baseExcludes.append(p.name) | |
987 if projsetting == 'include': | |
988 includes.append(p.name + '.*') | |
989 | |
990 def _filter(l): | |
991 # filter out specific classes which are already covered by a baseExclude package | |
992 return [clazz for clazz in l if not any([clazz.startswith(package) for package in baseExcludes])] | |
993 excludes = [] | |
994 for p in mx.projects(): | |
995 excludes += _filter(p.find_classes_with_annotations(None, jacocoExcludedAnnotations, includeInnerClasses=True).keys()) | |
996 excludes += _filter(p.find_classes_with_matching_source_line(None, lambda line: 'JaCoCo Exclude' in line, includeInnerClasses=True).keys()) | |
997 | |
998 excludes += [package + '.*' for package in baseExcludes] | |
999 agentOptions = { | |
1000 'append' : 'true' if _jacoco == 'append' else 'false', | |
1001 'bootclasspath' : 'true', | |
1002 'includes' : ':'.join(includes), | |
1003 'excludes' : ':'.join(excludes), | |
1004 'destfile' : 'jacoco.exec' | |
1005 } | |
1006 args = ['-javaagent:' + jacocoagent.get_path(True) + '=' + ','.join([k + '=' + v for k, v in agentOptions.items()])] + args | |
1007 exe = join(jdk, 'bin', mx.exe_suffix('java')) | |
1008 pfx = _vm_prefix.split() if _vm_prefix is not None else [] | |
1009 | |
1010 if '-version' in args: | |
1011 ignoredArgs = args[args.index('-version') + 1:] | |
1012 if len(ignoredArgs) > 0: | |
1013 mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs)) | |
1014 | |
1015 args = mx.java().processArgs(args) | |
1016 return (pfx, exe, vm, args, cwd) | |
1017 | |
1018 def vm(args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, vmbuild=None): | |
1019 (pfx_, exe_, vm_, args_, cwd) = parseVmArgs(args, vm, cwd, vmbuild) | |
1020 return mx.run(pfx_ + [exe_, '-' + vm_] + args_, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout) | |
1021 | |
1022 def unittest(args): | |
1023 def vmLauncher(vmArgs, mainClass, mainClassArgs): | |
1024 if isJVMCIEnabled(get_vm()): | |
1025 # Remove entries from class path that are in JVMCI loaded jars | |
1026 cpIndex, cp = mx.find_classpath_arg(vmArgs) | |
1027 if cp: | |
1028 excluded = set() | |
1029 for jdkDist in jdkDeployedDists: | |
1030 dist = mx.distribution(jdkDist.name) | |
1031 excluded.update([d.output_dir() for d in dist.sorted_deps()]) | |
1032 cp = os.pathsep.join([e for e in cp.split(os.pathsep) if e not in excluded]) | |
1033 vmArgs[cpIndex] = cp | |
1034 | |
1035 # Run the VM in a mode where application/test classes can | |
1036 # access JVMCI loaded classes. | |
1037 vmArgs = ['-XX:-UseJVMCIClassLoader'] + vmArgs | |
1038 | |
1039 vm(vmArgs + [mainClass] + mainClassArgs) | |
1040 mx_unittest.unittest(args, vmLauncher=vmLauncher) | |
1041 | |
1042 def shortunittest(args): | |
1043 """alias for 'unittest --whitelist test/whitelist_shortunittest.txt'""" | |
1044 | |
1045 args = ['--whitelist', 'test/whitelist_shortunittest.txt'] + args | |
1046 unittest(args) | |
1047 | |
1048 def buildvms(args): | |
1049 """build one or more VMs in various configurations""" | |
1050 | |
1051 vmsDefault = ','.join(_vmChoices.keys()) | |
1052 vmbuildsDefault = ','.join(_vmbuildChoices) | |
1053 | |
1054 parser = ArgumentParser(prog='mx buildvms') | |
1055 parser.add_argument('--vms', help='a comma separated list of VMs to build (default: ' + vmsDefault + ')', metavar='<args>', default=vmsDefault) | |
1056 parser.add_argument('--builds', help='a comma separated list of build types (default: ' + vmbuildsDefault + ')', metavar='<args>', default=vmbuildsDefault) | |
1057 parser.add_argument('--check-distributions', action='store_true', dest='check_distributions', help='check built distributions for overlap') | |
1058 parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build') | |
1059 parser.add_argument('-c', '--console', action='store_true', help='send build output to console instead of log file') | |
1060 | |
1061 args = parser.parse_args(args) | |
1062 vms = args.vms.split(',') | |
1063 builds = args.builds.split(',') | |
1064 | |
1065 allStart = time.time() | |
1066 check_dists_args = ['--check-distributions'] if args.check_distributions else [] | |
1067 for v in vms: | |
1068 if not isVMSupported(v): | |
1069 mx.log('The ' + v + ' VM is not supported on this platform - skipping') | |
1070 continue | |
1071 | |
1072 for vmbuild in builds: | |
1073 if v == 'original' and vmbuild != 'product': | |
1074 continue | |
1075 if not args.console: | |
1076 logFile = join(v + '-' + vmbuild + '.log') | |
1077 log = open(join(_suite.dir, logFile), 'wb') | |
1078 start = time.time() | |
1079 mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')') | |
1080 verbose = ['-v'] if mx._opts.verbose else [] | |
1081 # Run as subprocess so that output can be directed to a file | |
1082 cmd = [sys.executable, '-u', join('mxtool', 'mx.py')] + verbose + ['--vm', v, '--vmbuild', vmbuild, 'build'] + check_dists_args | |
1083 mx.logv("executing command: " + str(cmd)) | |
1084 subprocess.check_call(cmd, cwd=_suite.dir, stdout=log, stderr=subprocess.STDOUT) | |
1085 duration = datetime.timedelta(seconds=time.time() - start) | |
1086 mx.log('END: ' + v + '-' + vmbuild + '\t[' + str(duration) + ']') | |
1087 else: | |
1088 with VM(v, vmbuild): | |
1089 build(check_dists_args) | |
1090 if not args.no_check: | |
1091 vmargs = ['-version'] | |
1092 if v == 'jvmci': | |
1093 vmargs.insert(0, '-XX:-BootstrapJVMCI') | |
1094 vm(vmargs, vm=v, vmbuild=vmbuild) | |
1095 allDuration = datetime.timedelta(seconds=time.time() - allStart) | |
1096 mx.log('TOTAL TIME: ' + '[' + str(allDuration) + ']') | |
1097 | |
1098 | |
1099 """ | |
1100 Context manager for a single gate task that can prevent the | |
1101 task from executing or time and log its execution. | |
1102 """ | |
1103 class Task: | |
1104 # None or a list of strings. If not None, only tasks whose title | |
1105 # matches at least one of the substrings in this list will return | |
1106 # a non-None value from __enter__. The body of a 'with Task(...) as t' | |
1107 # statement should check 't' and exit immediately if it is None. | |
1108 filters = None | |
1109 filtersExclude = False | |
1110 | |
1111 def __init__(self, title, tasks=None, disableJacoco=False): | |
1112 self.tasks = tasks | |
1113 self.title = title | |
1114 if tasks is not None and Task.filters is not None: | |
1115 if Task.filtersExclude: | |
1116 self.skipped = any([f in title for f in Task.filters]) | |
1117 else: | |
1118 self.skipped = not any([f in title for f in Task.filters]) | |
1119 else: | |
1120 self.skipped = False | |
1121 if not self.skipped: | |
1122 self.start = time.time() | |
1123 self.end = None | |
1124 self.duration = None | |
1125 self.disableJacoco = disableJacoco | |
1126 mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: BEGIN: ') + title) | |
1127 def __enter__(self): | |
1128 assert self.tasks is not None, "using Task with 'with' statement requires to pass the tasks list in the constructor" | |
1129 if self.skipped: | |
1130 return None | |
1131 if self.disableJacoco: | |
1132 self.jacacoSave = _jacoco | |
1133 return self | |
1134 def __exit__(self, exc_type, exc_value, traceback): | |
1135 if not self.skipped: | |
1136 self.tasks.append(self.stop()) | |
1137 if self.disableJacoco: | |
1138 global _jacoco | |
1139 _jacoco = self.jacacoSave | |
1140 | |
1141 def stop(self): | |
1142 self.end = time.time() | |
1143 self.duration = datetime.timedelta(seconds=self.end - self.start) | |
1144 mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: END: ') + self.title + ' [' + str(self.duration) + ']') | |
1145 return self | |
1146 def abort(self, codeOrMessage): | |
1147 self.end = time.time() | |
1148 self.duration = datetime.timedelta(seconds=self.end - self.start) | |
1149 mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(self.duration) + ']') | |
1150 mx.abort(codeOrMessage) | |
1151 return self | |
1152 | |
1153 def ctw(args): | |
1154 """run CompileTheWorld""" | |
1155 | |
1156 defaultCtwopts = '-Inline' | |
1157 | |
1158 parser = ArgumentParser(prog='mx ctw') | |
1159 parser.add_argument('--ctwopts', action='store', help='space separated JVMCI options used for CTW compilations (default: --ctwopts="' + defaultCtwopts + '")', default=defaultCtwopts, metavar='<options>') | |
1160 parser.add_argument('--jar', action='store', help='jar of classes to compiled instead of rt.jar', metavar='<path>') | |
1161 | |
1162 args, vmargs = parser.parse_known_args(args) | |
1163 | |
1164 if args.ctwopts: | |
1165 vmargs.append('-G:CompileTheWorldConfig=' + args.ctwopts) | |
1166 | |
1167 if args.jar: | |
1168 jar = os.path.abspath(args.jar) | |
1169 else: | |
1170 jar = join(_jdk(installJars=False), 'jre', 'lib', 'rt.jar') | |
1171 vmargs.append('-G:CompileTheWorldExcludeMethodFilter=sun.awt.X11.*.*') | |
1172 | |
1173 vmargs += ['-XX:+CompileTheWorld'] | |
1174 vm_ = get_vm() | |
1175 if isJVMCIEnabled(vm_): | |
1176 if vm_ == 'jvmci': | |
1177 vmargs += ['-XX:+BootstrapJVMCI'] | |
1178 vmargs += ['-G:CompileTheWorldClasspath=' + jar] | |
1179 else: | |
1180 vmargs += ['-Xbootclasspath/p:' + jar] | |
1181 | |
1182 # suppress menubar and dock when running on Mac; exclude x11 classes as they may cause vm crashes (on Solaris) | |
1183 vmargs = ['-Djava.awt.headless=true'] + vmargs | |
1184 | |
1185 vm(vmargs) | |
1186 | |
1187 def _jvmci_gate_runner(args, tasks): | |
1188 # Build server-hosted-jvmci now so we can run the unit tests | |
1189 with Task('BuildHotSpotJVMCIHosted: product', tasks) as t: | |
1190 if t: buildvms(['--vms', 'server', '--builds', 'product', '--check-distributions']) | |
1191 | |
1192 # Run unit tests on server-hosted-jvmci | |
1193 with VM('server', 'product'): | |
1194 with Task('UnitTests:hosted-product', tasks) as t: | |
1195 if t: unittest(['--enable-timing', '--verbose', '--fail-fast']) | |
1196 | |
1197 # Run unit tests on server-hosted-jvmci with -G:+SSA_LIR | |
1198 with VM('server', 'product'): | |
1199 with Task('UnitTestsSSA:hosted-product', tasks) as t: | |
1200 if t: unittest(['--enable-timing', '--verbose', '--fail-fast', '-G:+SSA_LIR']) | |
1201 # Run ctw against rt.jar on server-hosted-jvmci | |
1202 with VM('server', 'product'): | |
1203 with Task('CTW:hosted-product', tasks) as t: | |
1204 if t: ctw(['--ctwopts', '-Inline +ExitVMOnException', '-esa', '-G:+CompileTheWorldMultiThreaded', '-G:-InlineDuringParsing', '-G:-CompileTheWorldVerbose']) | |
1205 | |
1206 # Build the other VM flavors | |
1207 with Task('BuildHotSpotGraalOthers: fastdebug,product', tasks) as t: | |
1208 if t: buildvms(['--vms', 'jvmci,server', '--builds', 'fastdebug,product', '--check-distributions']) | |
1209 | |
1210 with VM('jvmci', 'fastdebug'): | |
1211 with Task('BootstrapWithSystemAssertions:fastdebug', tasks) as t: | |
1212 if t: vm(['-esa', '-XX:-TieredCompilation', '-version']) | |
1213 | |
1214 with VM('jvmci', 'fastdebug'): | |
1215 with Task('BootstrapEconomyWithSystemAssertions:fastdebug', tasks) as t: | |
1216 if t: vm(['-esa', '-XX:-TieredCompilation', '-G:CompilerConfiguration=economy', '-version']) | |
1217 | |
1218 with VM('jvmci', 'fastdebug'): | |
1219 with Task('BootstrapWithSystemAssertionsNoCoop:fastdebug', tasks) as t: | |
1220 if t: vm(['-esa', '-XX:-TieredCompilation', '-XX:-UseCompressedOops', '-version']) | |
1221 | |
1222 with VM('jvmci', 'fastdebug'): | |
1223 with Task('BootstrapWithExceptionEdges:fastdebug', tasks) as t: | |
1224 if t: vm(['-esa', '-XX:-TieredCompilation', '-G:+StressInvokeWithExceptionNode', '-version']) | |
1225 | |
1226 with VM('jvmci', 'product'): | |
1227 with Task('BootstrapWithGCVerification:product', tasks) as t: | |
1228 if t: | |
1229 out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write | |
1230 vm(['-XX:-TieredCompilation', '-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) | |
1231 | |
1232 with VM('jvmci', 'product'): | |
1233 with Task('BootstrapWithG1GCVerification:product', tasks) as t: | |
1234 if t: | |
1235 out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write | |
1236 vm(['-XX:-TieredCompilation', '-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) | |
1237 | |
1238 with VM('jvmci', 'product'): | |
1239 with Task('BootstrapWithRegisterPressure:product', tasks) as t: | |
1240 if t: | |
1241 registers = 'o0,o1,o2,o3,f8,f9,d32,d34' if platform.processor() == 'sparc' else 'rbx,r11,r10,r14,xmm3,xmm11,xmm14' | |
1242 vm(['-XX:-TieredCompilation', '-G:RegisterPressure=' + registers, '-esa', '-version']) | |
1243 | |
1244 with VM('jvmci', 'product'): | |
1245 with Task('BootstrapSSAWithRegisterPressure:product', tasks) as t: | |
1246 if t: | |
1247 registers = 'o0,o1,o2,o3,f8,f9,d32,d34' if platform.processor() == 'sparc' else 'rbx,r11,r10,r14,xmm3,xmm11,xmm14' | |
1248 vm(['-XX:-TieredCompilation', '-G:+SSA_LIR', '-G:RegisterPressure=' + registers, '-esa', '-version']) | |
1249 | |
1250 with VM('jvmci', 'product'): | |
1251 with Task('BootstrapWithImmutableCode:product', tasks) as t: | |
1252 if t: vm(['-XX:-TieredCompilation', '-G:+ImmutableCode', '-G:+VerifyPhases', '-esa', '-version']) | |
1253 | |
1254 with Task('CleanAndBuildIdealGraphVisualizer', tasks, disableJacoco=True) as t: | |
1255 if t and platform.processor() != 'sparc': | |
1256 buildxml = mx._cygpathU2W(join(_suite.dir, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml')) | |
1257 mx.run(['ant', '-f', buildxml, '-q', 'clean', 'build'], env=_igvBuildEnv()) | |
1258 | |
1259 # Prevent JVMCI modifications from breaking the standard builds | |
1260 if args.buildNonJVMCI: | |
1261 with Task('BuildHotSpotVarieties', tasks, disableJacoco=True) as t: | |
1262 if t: | |
1263 buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product']) | |
1264 if mx.get_os() not in ['windows', 'cygwin']: | |
1265 buildvms(['--vms', 'server-nojvmci', '--builds', 'product,optimized']) | |
1266 | |
1267 """ | |
1268 List of function called by the gate once common gate tasks have been executed. | |
1269 Each function is called with these arguments: | |
1270 args: the argparse.Namespace object containing result of parsing gate command line | |
1271 tasks: list of Task to which extra Tasks should be added | |
1272 """ | |
1273 gateRunners = [_jvmci_gate_runner] | |
1274 | |
1275 def gate(args): | |
1276 """run the tests used to validate a push | |
1277 | |
1278 If this command exits with a 0 exit code, then the source code is in | |
1279 a state that would be accepted for integration into the main repository.""" | |
1280 | |
1281 parser = ArgumentParser(prog='mx gate') | |
1282 parser.add_argument('-j', '--omit-java-clean', action='store_false', dest='cleanJava', help='omit cleaning Java native code') | |
1283 parser.add_argument('-n', '--omit-native-clean', action='store_false', dest='cleanNative', help='omit cleaning and building native code') | |
1284 parser.add_argument('-i', '--omit-ide-clean', action='store_false', dest='cleanIde', help='omit cleaning the ide project files') | |
1285 parser.add_argument('-g', '--only-build-jvmci', action='store_false', dest='buildNonJVMCI', help='only build the JVMCI VM') | |
1286 parser.add_argument('-t', '--task-filter', help='comma separated list of substrings to select subset of tasks to be run') | |
1287 parser.add_argument('-x', action='store_true', help='makes --task-filter an exclusion instead of inclusion filter') | |
1288 parser.add_argument('--jacocout', help='specify the output directory for jacoco report') | |
1289 | |
1290 args = parser.parse_args(args) | |
1291 | |
1292 global _jacoco | |
1293 if args.task_filter: | |
1294 Task.filters = args.task_filter.split(',') | |
1295 Task.filtersExclude = args.x | |
1296 elif args.x: | |
1297 mx.abort('-x option cannot be used without --task-filter option') | |
1298 | |
1299 # Force | |
1300 if not mx._opts.strict_compliance: | |
1301 mx.log("[gate] forcing strict compliance") | |
1302 mx._opts.strict_compliance = True | |
1303 | |
1304 tasks = [] | |
1305 total = Task('Gate') | |
1306 try: | |
1307 with Task('Check jvmci.make in sync with suite.py', tasks) as t: | |
1308 if t: | |
1309 jvmciMake = join('make', 'jvmci.make') | |
1310 if mx_jvmci_makefile.build_makefile(['-o', jvmciMake]) != 0: | |
1311 t.abort('Rerun "mx makefile -o ' + jvmciMake + ' and check-in the modified ' + jvmciMake) | |
1312 | |
1313 with Task('Pylint', tasks) as t: | |
1314 if t: mx.pylint([]) | |
1315 | |
1316 def _clean(name='Clean'): | |
1317 with Task(name, tasks) as t: | |
1318 if t: | |
1319 cleanArgs = [] | |
1320 if not args.cleanNative: | |
1321 cleanArgs.append('--no-native') | |
1322 if not args.cleanJava: | |
1323 cleanArgs.append('--no-java') | |
1324 clean(cleanArgs) | |
1325 _clean() | |
1326 | |
1327 with Task('IDEConfigCheck', tasks) as t: | |
1328 if t: | |
1329 if args.cleanIde: | |
1330 mx.ideclean([]) | |
1331 mx.ideinit([]) | |
1332 | |
1333 eclipse_exe = mx.get_env('ECLIPSE_EXE') | |
1334 if eclipse_exe is not None: | |
1335 with Task('CodeFormatCheck', tasks) as t: | |
1336 if t and mx.eclipseformat(['-e', eclipse_exe]) != 0: | |
1337 t.abort('Formatter modified files - run "mx eclipseformat", check in changes and repush') | |
1338 | |
1339 with Task('Canonicalization Check', tasks) as t: | |
1340 if t: | |
1341 mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...')) | |
1342 if mx.canonicalizeprojects([]) != 0: | |
1343 t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/suite*.py files.') | |
1344 | |
1345 if mx.get_env('JDT'): | |
1346 with Task('BuildJavaWithEcj', tasks): | |
1347 if t: build(['-p', '--no-native', '--jdt-warning-as-error']) | |
1348 _clean('CleanAfterEcjBuild') | |
1349 | |
1350 with Task('BuildJavaWithJavac', tasks): | |
1351 if t: build(['-p', '--no-native', '--force-javac']) | |
1352 | |
1353 with Task('Checkstyle', tasks) as t: | |
1354 if t and mx.checkstyle([]) != 0: | |
1355 t.abort('Checkstyle warnings were found') | |
1356 | |
1357 with Task('Checkheaders', tasks) as t: | |
1358 if t and checkheaders([]) != 0: | |
1359 t.abort('Checkheaders warnings were found') | |
1360 | |
1361 with Task('FindBugs', tasks) as t: | |
1362 if t and mx_findbugs.findbugs([]) != 0: | |
1363 t.abort('FindBugs warnings were found') | |
1364 | |
1365 if exists('jacoco.exec'): | |
1366 os.unlink('jacoco.exec') | |
1367 | |
1368 if args.jacocout is not None: | |
1369 _jacoco = 'append' | |
1370 else: | |
1371 _jacoco = 'off' | |
1372 | |
1373 for runner in gateRunners: | |
1374 runner(args, tasks) | |
1375 | |
1376 if args.jacocout is not None: | |
1377 jacocoreport([args.jacocout]) | |
1378 _jacoco = 'off' | |
1379 | |
1380 except KeyboardInterrupt: | |
1381 total.abort(1) | |
1382 | |
1383 except BaseException as e: | |
1384 import traceback | |
1385 traceback.print_exc() | |
1386 total.abort(str(e)) | |
1387 | |
1388 total.stop() | |
1389 | |
1390 mx.log('Gate task times:') | |
1391 for t in tasks: | |
1392 mx.log(' ' + str(t.duration) + '\t' + t.title) | |
1393 mx.log(' =======') | |
1394 mx.log(' ' + str(total.duration)) | |
1395 | |
1396 if args.task_filter: | |
1397 Task.filters = None | |
1398 | |
1399 def deoptalot(args): | |
1400 """bootstrap a VM with DeoptimizeALot and VerifyOops on | |
1401 | |
1402 If the first argument is a number, the process will be repeated | |
1403 this number of times. All other arguments are passed to the VM.""" | |
1404 count = 1 | |
1405 if len(args) > 0 and args[0].isdigit(): | |
1406 count = int(args[0]) | |
1407 del args[0] | |
1408 | |
1409 for _ in range(count): | |
1410 if not vm(['-XX:-TieredCompilation', '-XX:+DeoptimizeALot', '-XX:+VerifyOops'] + args + ['-version']) == 0: | |
1411 mx.abort("Failed") | |
1412 | |
1413 def longtests(args): | |
1414 | |
1415 deoptalot(['15', '-Xmx48m']) | |
1416 | |
1417 def _igvJdk(): | |
1418 v8u20 = mx.VersionSpec("1.8.0_20") | |
1419 v8u40 = mx.VersionSpec("1.8.0_40") | |
1420 v8 = mx.VersionSpec("1.8") | |
1421 def _igvJdkVersionCheck(version): | |
1422 return version >= v8 and (version < v8u20 or version >= v8u40) | |
1423 return mx.java(_igvJdkVersionCheck, versionDescription='>= 1.8 and < 1.8.0u20 or >= 1.8.0u40', purpose="building & running IGV").jdk | |
1424 | |
1425 def _igvBuildEnv(): | |
1426 # When the http_proxy environment variable is set, convert it to the proxy settings that ant needs | |
1427 env = dict(os.environ) | |
1428 proxy = os.environ.get('http_proxy') | |
1429 if not (proxy is None) and len(proxy) > 0: | |
1430 if '://' in proxy: | |
1431 # Remove the http:// prefix (or any other protocol prefix) | |
1432 proxy = proxy.split('://', 1)[1] | |
1433 # Separate proxy server name and port number | |
1434 proxyName, proxyPort = proxy.split(':', 1) | |
1435 proxyEnv = '-DproxyHost="' + proxyName + '" -DproxyPort=' + proxyPort | |
1436 env['ANT_OPTS'] = proxyEnv | |
1437 | |
1438 env['JAVA_HOME'] = _igvJdk() | |
1439 return env | |
1440 | |
1441 def igv(args): | |
1442 """run the Ideal Graph Visualizer""" | |
1443 logFile = '.ideal_graph_visualizer.log' | |
1444 with open(join(_suite.dir, logFile), 'w') as fp: | |
1445 mx.logv('[Ideal Graph Visualizer log is in ' + fp.name + ']') | |
1446 nbplatform = join(_suite.dir, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'nbplatform') | |
1447 | |
1448 # Remove NetBeans platform if it is earlier than the current supported version | |
1449 if exists(nbplatform): | |
1450 updateTrackingFile = join(nbplatform, 'platform', 'update_tracking', 'org-netbeans-core.xml') | |
1451 if not exists(updateTrackingFile): | |
1452 mx.log('Could not find \'' + updateTrackingFile + '\', removing NetBeans platform') | |
1453 shutil.rmtree(nbplatform) | |
1454 else: | |
1455 dom = xml.dom.minidom.parse(updateTrackingFile) | |
1456 currentVersion = mx.VersionSpec(dom.getElementsByTagName('module_version')[0].getAttribute('specification_version')) | |
1457 supportedVersion = mx.VersionSpec('3.43.1') | |
1458 if currentVersion < supportedVersion: | |
1459 mx.log('Replacing NetBeans platform version ' + str(currentVersion) + ' with version ' + str(supportedVersion)) | |
1460 shutil.rmtree(nbplatform) | |
1461 elif supportedVersion < currentVersion: | |
1462 mx.log('Supported NetBeans version in igv command should be updated to ' + str(currentVersion)) | |
1463 | |
1464 if not exists(nbplatform): | |
1465 mx.logv('[This execution may take a while as the NetBeans platform needs to be downloaded]') | |
1466 | |
1467 env = _igvBuildEnv() | |
1468 # make the jar for Batik 1.7 available. | |
1469 env['IGV_BATIK_JAR'] = mx.library('BATIK').get_path(True) | |
1470 if mx.run(['ant', '-f', mx._cygpathU2W(join(_suite.dir, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml')), '-l', mx._cygpathU2W(fp.name), 'run'], env=env, nonZeroIsFatal=False): | |
1471 mx.abort("IGV ant build & launch failed. Check '" + logFile + "'. You can also try to delete 'src/share/tools/IdealGraphVisualizer/nbplatform'.") | |
1472 | |
1473 def c1visualizer(args): | |
1474 """run the Cl Compiler Visualizer""" | |
1475 libpath = join(_suite.dir, 'lib') | |
1476 if mx.get_os() == 'windows': | |
1477 executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer.exe') | |
1478 else: | |
1479 executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer') | |
1480 | |
1481 # Check whether the current C1Visualizer installation is the up-to-date | |
1482 if exists(executable) and not exists(mx.library('C1VISUALIZER_DIST').get_path(resolve=False)): | |
1483 mx.log('Updating C1Visualizer') | |
1484 shutil.rmtree(join(libpath, 'c1visualizer')) | |
1485 | |
1486 archive = mx.library('C1VISUALIZER_DIST').get_path(resolve=True) | |
1487 | |
1488 if not exists(executable): | |
1489 zf = zipfile.ZipFile(archive, 'r') | |
1490 zf.extractall(libpath) | |
1491 | |
1492 if not exists(executable): | |
1493 mx.abort('C1Visualizer binary does not exist: ' + executable) | |
1494 | |
1495 if mx.get_os() != 'windows': | |
1496 # Make sure that execution is allowed. The zip file does not always specfiy that correctly | |
1497 os.chmod(executable, 0777) | |
1498 | |
1499 mx.run([executable]) | |
1500 | |
1501 def _get_jmh_path(): | |
1502 path = mx.get_env('JMH_BENCHMARKS', None) | |
1503 if not path: | |
1504 probe = join(dirname(_suite.dir), 'java-benchmarks') | |
1505 if exists(probe): | |
1506 path = probe | |
1507 | |
1508 if not path: | |
1509 mx.abort("Please set the JMH_BENCHMARKS environment variable to point to the java-benchmarks workspace") | |
1510 if not exists(path): | |
1511 mx.abort("The directory denoted by the JMH_BENCHMARKS environment variable does not exist: " + path) | |
1512 return path | |
1513 | |
1514 def makejmhdeps(args): | |
1515 """creates and installs Maven dependencies required by the JMH benchmarks | |
1516 | |
1517 The dependencies are specified by files named pom.mxdeps in the | |
1518 JMH directory tree. Each such file contains a list of dependencies | |
1519 defined in JSON format. For example: | |
1520 | |
1521 '[{"artifactId" : "compiler.test", "groupId" : "com.oracle.graal", "deps" : ["com.oracle.graal.compiler.test"]}]' | |
1522 | |
1523 will result in a dependency being installed in the local Maven repository | |
1524 that can be referenced in a pom.xml file as follows: | |
1525 | |
1526 <dependency> | |
1527 <groupId>com.oracle.graal</groupId> | |
1528 <artifactId>compiler.test</artifactId> | |
1529 <version>1.0-SNAPSHOT</version> | |
1530 </dependency>""" | |
1531 | |
1532 parser = ArgumentParser(prog='mx makejmhdeps') | |
1533 parser.add_argument('-s', '--settings', help='alternative path for Maven user settings file', metavar='<path>') | |
1534 parser.add_argument('-p', '--permissive', action='store_true', help='issue note instead of error if a Maven dependency cannot be built due to missing projects/libraries') | |
1535 args = parser.parse_args(args) | |
1536 | |
1537 def makejmhdep(artifactId, groupId, deps): | |
1538 path = artifactId + '.jar' | |
1539 if args.permissive: | |
1540 allDeps = [] | |
1541 for name in deps: | |
1542 dist = mx.distribution(name, fatalIfMissing=False) | |
1543 if dist: | |
1544 allDeps = allDeps + [d.name for d in dist.sorted_deps(transitive=True)] | |
1545 else: | |
1546 if not mx.project(name, fatalIfMissing=False): | |
1547 if not mx.library(name, fatalIfMissing=False): | |
1548 mx.log('Skipping dependency ' + groupId + '.' + artifactId + ' as ' + name + ' cannot be resolved') | |
1549 return | |
1550 allDeps.append(name) | |
1551 d = mx.Distribution(_suite, name=artifactId, path=path, sourcesPath=path, deps=allDeps, mainClass=None, excludedDependencies=[], distDependencies=[], javaCompliance=None) | |
1552 d.make_archive() | |
1553 cmd = ['mvn', 'install:install-file', '-DgroupId=' + groupId, '-DartifactId=' + artifactId, | |
1554 '-Dversion=1.0-SNAPSHOT', '-Dpackaging=jar', '-Dfile=' + d.path] | |
1555 if not mx._opts.verbose: | |
1556 cmd.append('-q') | |
1557 if args.settings: | |
1558 cmd = cmd + ['-s', args.settings] | |
1559 mx.run(cmd) | |
1560 os.unlink(d.path) | |
1561 | |
1562 jmhPath = _get_jmh_path() | |
1563 for root, _, filenames in os.walk(jmhPath): | |
1564 for f in [join(root, n) for n in filenames if n == 'pom.mxdeps']: | |
1565 mx.logv('[processing ' + f + ']') | |
1566 try: | |
1567 with open(f) as fp: | |
1568 for d in json.load(fp): | |
1569 artifactId = d['artifactId'] | |
1570 groupId = d['groupId'] | |
1571 deps = d['deps'] | |
1572 makejmhdep(artifactId, groupId, deps) | |
1573 except ValueError as e: | |
1574 mx.abort('Error parsing {0}:\n{1}'.format(f, e)) | |
1575 | |
1576 def buildjmh(args): | |
1577 """build the JMH benchmarks""" | |
1578 | |
1579 parser = ArgumentParser(prog='mx buildjmh') | |
1580 parser.add_argument('-s', '--settings', help='alternative path for Maven user settings file', metavar='<path>') | |
1581 parser.add_argument('-c', action='store_true', dest='clean', help='clean before building') | |
1582 args = parser.parse_args(args) | |
1583 | |
1584 jmhPath = _get_jmh_path() | |
1585 mx.log('JMH benchmarks: ' + jmhPath) | |
1586 | |
1587 # Ensure the mx injected dependencies are up to date | |
1588 makejmhdeps(['-p'] + (['-s', args.settings] if args.settings else [])) | |
1589 | |
1590 timestamp = mx.TimeStampFile(join(_suite.mxDir, 'jmh', jmhPath.replace(os.sep, '_') + '.timestamp')) | |
1591 mustBuild = args.clean | |
1592 if not mustBuild: | |
1593 try: | |
1594 hgfiles = [join(jmhPath, f) for f in subprocess.check_output(['hg', '-R', jmhPath, 'locate']).split('\n')] | |
1595 mustBuild = timestamp.isOlderThan(hgfiles) | |
1596 except: | |
1597 # not a Mercurial repository or hg commands are not available. | |
1598 mustBuild = True | |
1599 | |
1600 if mustBuild: | |
1601 buildOutput = [] | |
1602 def _redirect(x): | |
1603 if mx._opts.verbose: | |
1604 mx.log(x[:-1]) | |
1605 else: | |
1606 buildOutput.append(x) | |
1607 env = os.environ.copy() | |
1608 env['JAVA_HOME'] = _jdk(vmToCheck='server') | |
1609 env['MAVEN_OPTS'] = '-server -XX:-UseJVMCIClassLoader' | |
1610 mx.log("Building benchmarks...") | |
1611 cmd = ['mvn'] | |
1612 if args.settings: | |
1613 cmd = cmd + ['-s', args.settings] | |
1614 if args.clean: | |
1615 cmd.append('clean') | |
1616 cmd.append('package') | |
1617 retcode = mx.run(cmd, cwd=jmhPath, out=_redirect, env=env, nonZeroIsFatal=False) | |
1618 if retcode != 0: | |
1619 mx.log(''.join(buildOutput)) | |
1620 mx.abort(retcode) | |
1621 timestamp.touch() | |
1622 else: | |
1623 mx.logv('[all Mercurial controlled files in ' + jmhPath + ' are older than ' + timestamp.path + ' - skipping build]') | |
1624 | |
1625 def jmh(args): | |
1626 """run the JMH benchmarks | |
1627 | |
1628 This command respects the standard --vm and --vmbuild options | |
1629 for choosing which VM to run the benchmarks with.""" | |
1630 if '-h' in args: | |
1631 mx.help_(['jmh']) | |
1632 mx.abort(1) | |
1633 | |
1634 vmArgs, benchmarksAndJsons = mx.extract_VM_args(args) | |
1635 if isJVMCIEnabled(get_vm()) and '-XX:-UseJVMCIClassLoader' not in vmArgs: | |
1636 vmArgs = ['-XX:-UseJVMCIClassLoader'] + vmArgs | |
1637 | |
1638 benchmarks = [b for b in benchmarksAndJsons if not b.startswith('{')] | |
1639 jmhArgJsons = [b for b in benchmarksAndJsons if b.startswith('{')] | |
1640 jmhOutDir = join(_suite.mxDir, 'jmh') | |
1641 if not exists(jmhOutDir): | |
1642 os.makedirs(jmhOutDir) | |
1643 jmhOut = join(jmhOutDir, 'jmh.out') | |
1644 jmhArgs = {'-rff' : jmhOut, '-v' : 'EXTRA' if mx._opts.verbose else 'NORMAL'} | |
1645 | |
1646 # e.g. '{"-wi" : 20}' | |
1647 for j in jmhArgJsons: | |
1648 try: | |
1649 for n, v in json.loads(j).iteritems(): | |
1650 if v is None: | |
1651 del jmhArgs[n] | |
1652 else: | |
1653 jmhArgs[n] = v | |
1654 except ValueError as e: | |
1655 mx.abort('error parsing JSON input: {0}\n{1}'.format(j, e)) | |
1656 | |
1657 jmhPath = _get_jmh_path() | |
1658 mx.log('Using benchmarks in ' + jmhPath) | |
1659 | |
1660 matchedSuites = set() | |
1661 numBench = [0] | |
1662 for micros in os.listdir(jmhPath): | |
1663 absoluteMicro = os.path.join(jmhPath, micros) | |
1664 if not os.path.isdir(absoluteMicro): | |
1665 continue | |
1666 if not micros.startswith("micros-"): | |
1667 mx.logv('JMH: ignored ' + absoluteMicro + " because it doesn't start with 'micros-'") | |
1668 continue | |
1669 | |
1670 microJar = os.path.join(absoluteMicro, "target", "microbenchmarks.jar") | |
1671 if not exists(microJar): | |
1672 mx.log('Missing ' + microJar + ' - please run "mx buildjmh"') | |
1673 continue | |
1674 if benchmarks: | |
1675 def _addBenchmark(x): | |
1676 if x.startswith("Benchmark:"): | |
1677 return | |
1678 match = False | |
1679 for b in benchmarks: | |
1680 match = match or (b in x) | |
1681 | |
1682 if match: | |
1683 numBench[0] += 1 | |
1684 matchedSuites.add(micros) | |
1685 | |
1686 mx.run_java(['-jar', microJar, "-l"], cwd=jmhPath, out=_addBenchmark, addDefaultArgs=False) | |
1687 else: | |
1688 matchedSuites.add(micros) | |
1689 | |
1690 mx.logv("matchedSuites: " + str(matchedSuites)) | |
1691 plural = 's' if not benchmarks or numBench[0] > 1 else '' | |
1692 number = str(numBench[0]) if benchmarks else "all" | |
1693 mx.log("Running " + number + " benchmark" + plural + '...') | |
1694 | |
1695 regex = [] | |
1696 if benchmarks: | |
1697 regex.append(r".*(" + "|".join(benchmarks) + ").*") | |
1698 | |
1699 for suite in matchedSuites: | |
1700 absoluteMicro = os.path.join(jmhPath, suite) | |
1701 (pfx, exe, vm, forkedVmArgs, _) = parseVmArgs(vmArgs) | |
1702 if pfx: | |
1703 mx.log("JMH ignores prefix: \"" + ' '.join(pfx) + "\"") | |
1704 javaArgs = ['-jar', os.path.join(absoluteMicro, "target", "microbenchmarks.jar"), | |
1705 '--jvm', exe, | |
1706 '--jvmArgs', ' '.join(["-" + vm] + forkedVmArgs)] | |
1707 for k, v in jmhArgs.iteritems(): | |
1708 javaArgs.append(k) | |
1709 if len(str(v)): | |
1710 javaArgs.append(str(v)) | |
1711 mx.run_java(javaArgs + regex, addDefaultArgs=False, cwd=jmhPath) | |
1712 | |
1713 def microbench(args): | |
1714 """run JMH microbenchmark projects""" | |
1715 vmArgs, jmhArgs = mx.extract_VM_args(args, useDoubleDash=True) | |
1716 | |
1717 # look for -f in JMH arguments | |
1718 containsF = False | |
1719 forking = True | |
1720 for i in range(len(jmhArgs)): | |
1721 arg = jmhArgs[i] | |
1722 if arg.startswith('-f'): | |
1723 containsF = True | |
1724 if arg == '-f' and (i+1) < len(jmhArgs): | |
1725 arg += jmhArgs[i+1] | |
1726 try: | |
1727 if int(arg[2:]) == 0: | |
1728 forking = False | |
1729 except ValueError: | |
1730 pass | |
1731 | |
1732 # default to -f1 if not specified otherwise | |
1733 if not containsF: | |
1734 jmhArgs += ['-f1'] | |
1735 | |
1736 # find all projects with a direct JMH dependency | |
1737 jmhProjects = [] | |
1738 for p in mx.projects(): | |
1739 if 'JMH' in p.deps: | |
1740 jmhProjects.append(p.name) | |
1741 cp = mx.classpath(jmhProjects) | |
1742 | |
1743 # execute JMH runner | |
1744 args = ['-cp', cp] | |
1745 if not forking: | |
1746 args += vmArgs | |
1747 args += ['org.openjdk.jmh.Main'] | |
1748 if forking: | |
1749 (_, _, jvm, _, _) = parseVmArgs(vmArgs) | |
1750 args += ['--jvmArgsPrepend', ' '.join(['-' + jvm] + vmArgs)] | |
1751 vm(args + jmhArgs) | |
1752 | |
1753 def hsdis(args, copyToDir=None): | |
1754 """download the hsdis library | |
1755 | |
1756 This is needed to support HotSpot's assembly dumping features. | |
1757 By default it downloads the Intel syntax version, use the 'att' argument to install AT&T syntax.""" | |
1758 flavor = 'intel' | |
1759 if 'att' in args: | |
1760 flavor = 'att' | |
1761 if mx.get_arch() == "sparcv9": | |
1762 flavor = "sparcv9" | |
1763 lib = mx.add_lib_suffix('hsdis-' + mx.get_arch()) | |
1764 path = join(_suite.dir, 'lib', lib) | |
1765 | |
1766 sha1s = { | |
1767 'att/hsdis-amd64.dll' : 'bcbd535a9568b5075ab41e96205e26a2bac64f72', | |
1768 'att/hsdis-amd64.so' : '58919ba085d4ef7a513f25bae75e7e54ee73c049', | |
1769 'intel/hsdis-amd64.dll' : '6a388372cdd5fe905c1a26ced614334e405d1f30', | |
1770 'intel/hsdis-amd64.so' : '844ed9ffed64fe9599638f29a8450c50140e3192', | |
1771 'intel/hsdis-amd64.dylib' : 'fdb13ef0d7d23d93dacaae9c98837bea0d4fc5a2', | |
1772 'sparcv9/hsdis-sparcv9.so': '970640a9af0bd63641f9063c11275b371a59ee60', | |
1773 } | |
1774 | |
1775 flavoredLib = flavor + "/" + lib | |
1776 if flavoredLib not in sha1s: | |
1777 mx.logv("hsdis not supported on this plattform or architecture") | |
1778 return | |
1779 | |
1780 if not exists(path): | |
1781 sha1 = sha1s[flavoredLib] | |
1782 sha1path = path + '.sha1' | |
1783 mx.download_file_with_sha1('hsdis', path, ['http://lafo.ssw.uni-linz.ac.at/hsdis/' + flavoredLib], sha1, sha1path, True, True, sources=False) | |
1784 if copyToDir is not None and exists(copyToDir): | |
1785 shutil.copy(path, copyToDir) | |
1786 | |
1787 def hcfdis(args): | |
1788 """disassemble HexCodeFiles embedded in text files | |
1789 | |
1790 Run a tool over the input files to convert all embedded HexCodeFiles | |
1791 to a disassembled format.""" | |
1792 | |
1793 parser = ArgumentParser(prog='mx hcfdis') | |
1794 parser.add_argument('-m', '--map', help='address to symbol map applied to disassembler output') | |
1795 parser.add_argument('files', nargs=REMAINDER, metavar='files...') | |
1796 | |
1797 args = parser.parse_args(args) | |
1798 | |
1799 path = mx.library('HCFDIS').get_path(resolve=True) | |
1800 mx.run_java(['-cp', path, 'com.oracle.max.hcfdis.HexCodeFileDis'] + args.files) | |
1801 | |
1802 if args.map is not None: | |
1803 addressRE = re.compile(r'0[xX]([A-Fa-f0-9]+)') | |
1804 with open(args.map) as fp: | |
1805 lines = fp.read().splitlines() | |
1806 symbols = dict() | |
1807 for l in lines: | |
1808 addressAndSymbol = l.split(' ', 1) | |
1809 if len(addressAndSymbol) == 2: | |
1810 address, symbol = addressAndSymbol | |
1811 if address.startswith('0x'): | |
1812 address = long(address, 16) | |
1813 symbols[address] = symbol | |
1814 for f in args.files: | |
1815 with open(f) as fp: | |
1816 lines = fp.read().splitlines() | |
1817 updated = False | |
1818 for i in range(0, len(lines)): | |
1819 l = lines[i] | |
1820 for m in addressRE.finditer(l): | |
1821 sval = m.group(0) | |
1822 val = long(sval, 16) | |
1823 sym = symbols.get(val) | |
1824 if sym: | |
1825 l = l.replace(sval, sym) | |
1826 updated = True | |
1827 lines[i] = l | |
1828 if updated: | |
1829 mx.log('updating ' + f) | |
1830 with open('new_' + f, "w") as fp: | |
1831 for l in lines: | |
1832 print >> fp, l | |
1833 | |
1834 def jacocoreport(args): | |
1835 """create a JaCoCo coverage report | |
1836 | |
1837 Creates the report from the 'jacoco.exec' file in the current directory. | |
1838 Default output directory is 'coverage', but an alternative can be provided as an argument.""" | |
1839 jacocoreport = mx.library("JACOCOREPORT", True) | |
1840 out = 'coverage' | |
1841 if len(args) == 1: | |
1842 out = args[0] | |
1843 elif len(args) > 1: | |
1844 mx.abort('jacocoreport takes only one argument : an output directory') | |
1845 | |
1846 includes = ['com.oracle.graal', 'jdk.internal.jvmci'] | |
1847 for p in mx.projects(): | |
1848 projsetting = getattr(p, 'jacoco', '') | |
1849 if projsetting == 'include': | |
1850 includes.append(p.name) | |
1851 | |
1852 includedirs = set() | |
1853 for p in mx.projects(): | |
1854 projsetting = getattr(p, 'jacoco', '') | |
1855 if projsetting == 'exclude': | |
1856 continue | |
1857 for include in includes: | |
1858 if include in p.dir: | |
1859 includedirs.add(p.dir) | |
1860 | |
1861 for i in includedirs: | |
1862 bindir = i + '/bin' | |
1863 if not os.path.exists(bindir): | |
1864 os.makedirs(bindir) | |
1865 | |
1866 mx.run_java(['-jar', jacocoreport.get_path(True), '--in', 'jacoco.exec', '--out', out] + sorted(includedirs)) | |
1867 | |
1868 def isJVMCIEnabled(vm): | |
1869 return vm != 'original' and not vm.endswith('nojvmci') | |
1870 | |
1871 def jol(args): | |
1872 """Java Object Layout""" | |
1873 joljar = mx.library('JOL_INTERNALS').get_path(resolve=True) | |
1874 candidates = mx.findclass(args, logToConsole=False, matcher=lambda s, classname: s == classname or classname.endswith('.' + s) or classname.endswith('$' + s)) | |
1875 | |
1876 if len(candidates) > 0: | |
1877 candidates = mx.select_items(sorted(candidates)) | |
1878 else: | |
1879 # mx.findclass can be mistaken, don't give up yet | |
1880 candidates = args | |
1881 | |
1882 vm(['-javaagent:' + joljar, '-cp', os.pathsep.join([mx.classpath(), joljar]), "org.openjdk.jol.MainObjectInternals"] + candidates) | |
1883 | |
1884 def checkheaders(args): | |
1885 """check Java source headers against any required pattern""" | |
1886 failures = {} | |
1887 for p in mx.projects(): | |
1888 if p.native: | |
1889 continue | |
1890 | |
1891 csConfig = join(mx.project(p.checkstyleProj).dir, '.checkstyle_checks.xml') | |
1892 if not exists(csConfig): | |
1893 mx.log('Cannot check headers for ' + p.name + ' - ' + csConfig + ' does not exist') | |
1894 continue | |
1895 dom = xml.dom.minidom.parse(csConfig) | |
1896 for module in dom.getElementsByTagName('module'): | |
1897 if module.getAttribute('name') == 'RegexpHeader': | |
1898 for prop in module.getElementsByTagName('property'): | |
1899 if prop.getAttribute('name') == 'header': | |
1900 value = prop.getAttribute('value') | |
1901 matcher = re.compile(value, re.MULTILINE) | |
1902 for sourceDir in p.source_dirs(): | |
1903 for root, _, files in os.walk(sourceDir): | |
1904 for name in files: | |
1905 if name.endswith('.java') and name != 'package-info.java': | |
1906 f = join(root, name) | |
1907 with open(f) as fp: | |
1908 content = fp.read() | |
1909 if not matcher.match(content): | |
1910 failures[f] = csConfig | |
1911 for n, v in failures.iteritems(): | |
1912 mx.log('{0}: header does not match RegexpHeader defined in {1}'.format(n, v)) | |
1913 return len(failures) | |
1914 | |
1915 def mx_init(suite): | |
1916 commands = { | |
1917 'build': [build, ''], | |
1918 'buildjmh': [buildjmh, '[-options]'], | |
1919 'buildvars': [buildvars, ''], | |
1920 'buildvms': [buildvms, '[-options]'], | |
1921 'c1visualizer' : [c1visualizer, ''], | |
1922 'checkheaders': [checkheaders, ''], | |
1923 'clean': [clean, ''], | |
1924 'ctw': [ctw, '[-vmoptions|noinline|nocomplex|full]'], | |
1925 'export': [export, '[-options] [zipfile]'], | |
1926 'hsdis': [hsdis, '[att]'], | |
1927 'hcfdis': [hcfdis, ''], | |
1928 'igv' : [igv, ''], | |
1929 'jdkhome': [print_jdkhome, ''], | |
1930 'jmh': [jmh, '[VM options] [filters|JMH-args-as-json...]'], | |
1931 'gate' : [gate, '[-options]'], | |
1932 'makejmhdeps' : [makejmhdeps, ''], | |
1933 'unittest' : [unittest, '[unittest options] [--] [VM options] [filters...]', mx_unittest.unittestHelpSuffix], | |
1934 'shortunittest' : [shortunittest, '[unittest options] [--] [VM options] [filters...]', mx_unittest.unittestHelpSuffix], | |
1935 'jacocoreport' : [jacocoreport, '[output directory]'], | |
1936 'vm': [vm, '[-options] class [args...]'], | |
1937 'deoptalot' : [deoptalot, '[n]'], | |
1938 'longtests' : [longtests, ''], | |
1939 'jol' : [jol, ''], | |
1940 'makefile' : [mx_jvmci_makefile.build_makefile, 'build makefiles for JDK build'], | |
1941 } | |
1942 | |
1943 mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append']) | |
1944 mx.add_argument('--vmcwd', dest='vm_cwd', help='current directory will be changed to <path> before the VM is executed', default=None, metavar='<path>') | |
1945 mx.add_argument('--installed-jdks', help='the base directory in which the JDKs cloned from $JAVA_HOME exist. ' + | |
1946 'The VM selected by --vm and --vmbuild options is under this directory (i.e., ' + | |
1947 join('<path>', '<jdk-version>', '<vmbuild>', 'jre', 'lib', '<vm>', mx.add_lib_prefix(mx.add_lib_suffix('jvm'))) + ')', default=None, metavar='<path>') | |
1948 | |
1949 mx.add_argument('--vm', action='store', dest='vm', choices=_vmChoices.keys(), help='the VM type to build/run') | |
1950 mx.add_argument('--vmbuild', action='store', dest='vmbuild', choices=_vmbuildChoices, help='the VM build to build/run (default: ' + _vmbuildChoices[0] + ')') | |
1951 mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse') | |
1952 mx.add_argument('--vmprefix', action='store', dest='vm_prefix', help='prefix for running the VM (e.g. "/usr/bin/gdb --args")', metavar='<prefix>') | |
1953 mx.add_argument('--gdb', action='store_const', const='/usr/bin/gdb --args', dest='vm_prefix', help='alias for --vmprefix "/usr/bin/gdb --args"') | |
1954 mx.add_argument('--lldb', action='store_const', const='lldb --', dest='vm_prefix', help='alias for --vmprefix "lldb --"') | |
1955 | |
1956 mx.update_commands(suite, commands) | |
1957 | |
1958 class JVMCIArchiveParticipant: | |
1959 def __init__(self, dist): | |
1960 self.dist = dist | |
1961 self.jvmciServices = {} | |
1962 | |
1963 def __opened__(self, arc, srcArc, services): | |
1964 self.services = services | |
1965 self.arc = arc | |
1966 self.expectedOptionsProviders = set() | |
1967 | |
1968 def __add__(self, arcname, contents): | |
1969 if arcname.startswith('META-INF/jvmci.services/'): | |
1970 service = arcname[len('META-INF/jvmci.services/'):] | |
1971 self.jvmciServices.setdefault(service, []).extend([provider for provider in contents.split('\n')]) | |
1972 return True | |
1973 if arcname.startswith('META-INF/jvmci.providers/'): | |
1974 provider = arcname[len('META-INF/jvmci.providers/'):] | |
1975 for service in contents.split(os.linesep): | |
1976 self.jvmciServices.setdefault(service, []).append(provider) | |
1977 return True | |
1978 elif arcname.startswith('META-INF/jvmci.options/'): | |
1979 # Need to create service files for the providers of the | |
1980 # jdk.internal.jvmci.options.Options service created by | |
1981 # jdk.internal.jvmci.options.processor.OptionProcessor. | |
1982 optionsOwner = arcname[len('META-INF/jvmci.options/'):] | |
1983 provider = optionsOwner + '_Options' | |
1984 self.expectedOptionsProviders.add(provider.replace('.', '/') + '.class') | |
1985 self.services.setdefault('jdk.internal.jvmci.options.Options', []).append(provider) | |
1986 return False | |
1987 | |
1988 def __addsrc__(self, arcname, contents): | |
1989 return False | |
1990 | |
1991 def __closing__(self): | |
1992 self.expectedOptionsProviders -= set(self.arc.zf.namelist()) | |
1993 assert len(self.expectedOptionsProviders) == 0, 'missing generated Options providers:\n ' + '\n '.join(self.expectedOptionsProviders) | |
1994 for service, providers in self.jvmciServices.iteritems(): | |
1995 arcname = 'META-INF/jvmci.services/' + service | |
1996 # Convert providers to a set before printing to remove duplicates | |
1997 self.arc.zf.writestr(arcname, '\n'.join(frozenset(providers))) | |
1998 | |
1999 def mx_post_parse_cmd_line(opts): # | |
2000 # TODO _minVersion check could probably be part of a Suite in mx? | |
2001 def _versionCheck(version): | |
2002 return version >= _minVersion and (not _untilVersion or version >= _untilVersion) | |
2003 versionDesc = ">=" + str(_minVersion) | |
2004 if _untilVersion: | |
2005 versionDesc += " and <=" + str(_untilVersion) | |
2006 mx.java(_versionCheck, versionDescription=versionDesc, defaultJdk=True) | |
2007 | |
2008 if hasattr(opts, 'vm') and opts.vm is not None: | |
2009 global _vm | |
2010 _vm = opts.vm | |
2011 _vm = _vm.replace('graal', 'jvmci') | |
2012 if hasattr(opts, 'vmbuild') and opts.vmbuild is not None: | |
2013 global _vmbuild | |
2014 _vmbuild = opts.vmbuild | |
2015 global _make_eclipse_launch | |
2016 _make_eclipse_launch = getattr(opts, 'make_eclipse_launch', False) | |
2017 global _jacoco | |
2018 _jacoco = opts.jacoco | |
2019 global _vm_cwd | |
2020 _vm_cwd = opts.vm_cwd | |
2021 global _installed_jdks | |
2022 _installed_jdks = opts.installed_jdks | |
2023 global _vm_prefix | |
2024 _vm_prefix = opts.vm_prefix | |
2025 | |
2026 for jdkDist in jdkDeployedDists: | |
2027 def _close(jdkDeployable): | |
2028 def _install(dist): | |
2029 assert dist.name == jdkDeployable.name, dist.name + "!=" + jdkDeployable.name | |
2030 if not jdkDist.partOfHotSpot: | |
2031 _installDistInJdks(jdkDeployable) | |
2032 return _install | |
2033 dist = mx.distribution(jdkDist.name) | |
2034 dist.add_update_listener(_close(jdkDist)) | |
2035 if jdkDist.usesJVMCIClassLoader: | |
2036 dist.set_archiveparticipant(JVMCIArchiveParticipant(dist)) | |
2037 |