comparison mxtool/mx.py @ 18876:c446d00f2cdf

mx: added support for Jython 2.7b3 and made ordering in generated files more deterministic\nContributed-by: Igor Ignatyev <igor.ignatyev@oracle.com>
author Doug Simon <doug.simon@oracle.com>
date Sat, 17 Jan 2015 11:26:18 +0100
parents c3bb622095f1
children 19d99eec8876 765bc32a4311
comparison
equal deleted inserted replaced
18875:d71bf1009d71 18876:c446d00f2cdf
32 32
33 Full documentation can be found at https://wiki.openjdk.java.net/display/Graal/The+mx+Tool 33 Full documentation can be found at https://wiki.openjdk.java.net/display/Graal/The+mx+Tool
34 """ 34 """
35 35
36 import sys, os, errno, time, subprocess, shlex, types, StringIO, zipfile, signal, xml.sax.saxutils, tempfile, fnmatch, platform 36 import sys, os, errno, time, subprocess, shlex, types, StringIO, zipfile, signal, xml.sax.saxutils, tempfile, fnmatch, platform
37 import multiprocessing
38 import textwrap 37 import textwrap
39 import socket 38 import socket
40 import tarfile 39 import tarfile
41 import hashlib 40 import hashlib
42 import xml.parsers.expat 41 import xml.parsers.expat
59 cmd = popenargs[0] 58 cmd = popenargs[0]
60 error = subprocess.CalledProcessError(retcode, cmd) 59 error = subprocess.CalledProcessError(retcode, cmd)
61 error.output = output 60 error.output = output
62 raise error 61 raise error
63 return output 62 return output
63
64 # Support for jython
65 def is_jython():
66 return sys.platform.startswith('java')
67
68 if not is_jython():
69 import multiprocessing
70
71 def cpu_count():
72 if is_jython():
73 from java.lang import Runtime
74 runtime = Runtime.getRuntime()
75 return runtime.availableProcessors()
76 else:
77 return multiprocessing.cpu_count()
78
64 79
65 try: subprocess.check_output 80 try: subprocess.check_output
66 except: subprocess.check_output = check_output 81 except: subprocess.check_output = check_output
67 82
68 try: zipfile.ZipFile.__enter__ 83 try: zipfile.ZipFile.__enter__
249 class Dependency: 264 class Dependency:
250 def __init__(self, suite, name): 265 def __init__(self, suite, name):
251 self.name = name 266 self.name = name
252 self.suite = suite 267 self.suite = suite
253 268
269 def __cmp__(self, other):
270 return cmp(self.name, other.name)
271
254 def __str__(self): 272 def __str__(self):
255 return self.name 273 return self.name
256 274
257 def __eq__(self, other): 275 def __eq__(self, other):
258 return self.name == other.name 276 return self.name == other.name
305 def all_deps(self, deps, includeLibs, includeSelf=True, includeJreLibs=False, includeAnnotationProcessors=False): 323 def all_deps(self, deps, includeLibs, includeSelf=True, includeJreLibs=False, includeAnnotationProcessors=False):
306 """ 324 """
307 Add the transitive set of dependencies for this project, including 325 Add the transitive set of dependencies for this project, including
308 libraries if 'includeLibs' is true, to the 'deps' list. 326 libraries if 'includeLibs' is true, to the 'deps' list.
309 """ 327 """
310 return self._all_deps_helper(deps, [], includeLibs, includeSelf, includeJreLibs, includeAnnotationProcessors) 328 return sorted(self._all_deps_helper(deps, [], includeLibs, includeSelf, includeJreLibs, includeAnnotationProcessors))
311 329
312 def _all_deps_helper(self, deps, dependants, includeLibs, includeSelf=True, includeJreLibs=False, includeAnnotationProcessors=False): 330 def _all_deps_helper(self, deps, dependants, includeLibs, includeSelf=True, includeJreLibs=False, includeAnnotationProcessors=False):
313 if self in dependants: 331 if self in dependants:
314 abort(str(self) + 'Project dependency cycle found:\n ' + 332 abort(str(self) + 'Project dependency cycle found:\n ' +
315 '\n |\n V\n '.join(map(str, dependants[dependants.index(self):])) + 333 '\n |\n V\n '.join(map(str, dependants[dependants.index(self):])) +
525 aps.add(p.name) 543 aps.add(p.name)
526 544
527 # Inherit annotation processors from dependencies 545 # Inherit annotation processors from dependencies
528 aps.update(p.annotation_processors()) 546 aps.update(p.annotation_processors())
529 547
530 self._annotationProcessors = list(aps) 548 self._annotationProcessors = sorted(list(aps))
531 return self._annotationProcessors 549 return self._annotationProcessors
532 550
533 """ 551 """
534 Gets the class path composed of the distribution jars containing the 552 Gets the class path composed of the distribution jars containing the
535 annotation processors that will be applied when compiling this project. 553 annotation processors that will be applied when compiling this project.
587 break 605 break
588 d.update(buf) 606 d.update(buf)
589 return d.hexdigest() 607 return d.hexdigest()
590 608
591 def download_file_with_sha1(name, path, urls, sha1, sha1path, resolve, mustExist, sources=False, canSymlink=True): 609 def download_file_with_sha1(name, path, urls, sha1, sha1path, resolve, mustExist, sources=False, canSymlink=True):
610 canSymlink = canSymlink and not (get_os() == 'windows' or get_os() == 'cygwin')
592 def _download_lib(): 611 def _download_lib():
593 cacheDir = get_env('MX_CACHE_DIR', join(_opts.user_home, '.mx', 'cache')) 612 cacheDir = _cygpathW2U(get_env('MX_CACHE_DIR', join(_opts.user_home, '.mx', 'cache')))
594 if not exists(cacheDir): 613 if not exists(cacheDir):
595 os.makedirs(cacheDir) 614 os.makedirs(cacheDir)
596 base = basename(path) 615 base = basename(path)
597 cachePath = join(cacheDir, base + '_' + sha1) 616 cachePath = join(cacheDir, base + '_' + sha1)
598 617
678 """ 697 """
679 Add the transitive set of dependencies for this JRE library to the 'deps' list. 698 Add the transitive set of dependencies for this JRE library to the 'deps' list.
680 """ 699 """
681 if includeJreLibs and includeSelf and not self in deps: 700 if includeJreLibs and includeSelf and not self in deps:
682 deps.append(self) 701 deps.append(self)
683 return deps 702 return sorted(deps)
684 703
685 class Library(BaseLibrary): 704 class Library(BaseLibrary):
686 def __init__(self, suite, name, path, optional, urls, sha1, sourcePath, sourceUrls, sourceSha1, deps): 705 def __init__(self, suite, name, path, optional, urls, sha1, sourcePath, sourceUrls, sourceSha1, deps):
687 BaseLibrary.__init__(self, suite, name, optional) 706 BaseLibrary.__init__(self, suite, name, optional)
688 self.path = path.replace('/', os.sep) 707 self.path = path.replace('/', os.sep)
751 def all_deps(self, deps, includeLibs, includeSelf=True, includeJreLibs=False, includeAnnotationProcessors=False): 770 def all_deps(self, deps, includeLibs, includeSelf=True, includeJreLibs=False, includeAnnotationProcessors=False):
752 """ 771 """
753 Add the transitive set of dependencies for this library to the 'deps' list. 772 Add the transitive set of dependencies for this library to the 'deps' list.
754 """ 773 """
755 if not includeLibs: 774 if not includeLibs:
756 return deps 775 return sorted(deps)
757 childDeps = list(self.deps) 776 childDeps = list(self.deps)
758 if self in deps: 777 if self in deps:
759 return deps 778 return sorted(deps)
760 for name in childDeps: 779 for name in childDeps:
761 assert name != self.name 780 assert name != self.name
762 dep = library(name) 781 dep = library(name)
763 if not dep in deps: 782 if not dep in deps:
764 dep.all_deps(deps, includeLibs=includeLibs, includeJreLibs=includeJreLibs, includeAnnotationProcessors=includeAnnotationProcessors) 783 dep.all_deps(deps, includeLibs=includeLibs, includeJreLibs=includeJreLibs, includeAnnotationProcessors=includeAnnotationProcessors)
765 if not self in deps and includeSelf: 784 if not self in deps and includeSelf:
766 deps.append(self) 785 deps.append(self)
767 return deps 786 return sorted(deps)
768 787
769 class HgConfig: 788 class HgConfig:
770 """ 789 """
771 Encapsulates access to Mercurial (hg) 790 Encapsulates access to Mercurial (hg)
772 """ 791 """
959 return [] 978 return []
960 if not isinstance(v, list): 979 if not isinstance(v, list):
961 abort('Attribute "' + name + '" for ' + context + ' must be a list') 980 abort('Attribute "' + name + '" for ' + context + ' must be a list')
962 return v 981 return v
963 982
964 for name, attrs in projsMap.iteritems(): 983 for name, attrs in sorted(projsMap.iteritems()):
965 context = 'project ' + name 984 context = 'project ' + name
966 srcDirs = pop_list(attrs, 'sourceDirs', context) 985 srcDirs = pop_list(attrs, 'sourceDirs', context)
967 deps = pop_list(attrs, 'dependencies', context) 986 deps = pop_list(attrs, 'dependencies', context)
968 ap = pop_list(attrs, 'annotationProcessors', context) 987 ap = pop_list(attrs, 'annotationProcessors', context)
969 javaCompliance = attrs.pop('javaCompliance', None) 988 javaCompliance = attrs.pop('javaCompliance', None)
981 if len(ap) > 0: 1000 if len(ap) > 0:
982 p._declaredAnnotationProcessors = ap 1001 p._declaredAnnotationProcessors = ap
983 p.__dict__.update(attrs) 1002 p.__dict__.update(attrs)
984 self.projects.append(p) 1003 self.projects.append(p)
985 1004
986 for name, attrs in jreLibsMap.iteritems(): 1005 for name, attrs in sorted(jreLibsMap.iteritems()):
987 jar = attrs.pop('jar') 1006 jar = attrs.pop('jar')
988 # JRE libraries are optional by default 1007 # JRE libraries are optional by default
989 optional = attrs.pop('optional', 'true') != 'false' 1008 optional = attrs.pop('optional', 'true') != 'false'
990 l = JreLibrary(self, name, jar, optional) 1009 l = JreLibrary(self, name, jar, optional)
991 self.jreLibs.append(l) 1010 self.jreLibs.append(l)
992 1011
993 for name, attrs in libsMap.iteritems(): 1012 for name, attrs in sorted(libsMap.iteritems()):
994 context = 'library ' + name 1013 context = 'library ' + name
995 if "|" in name: 1014 if "|" in name:
996 if name.count('|') != 2: 1015 if name.count('|') != 2:
997 abort("Format error in library name: " + name + "\nsyntax: libname|os-platform|architecture") 1016 abort("Format error in library name: " + name + "\nsyntax: libname|os-platform|architecture")
998 name, platform, architecture = name.split("|") 1017 name, platform, architecture = name.split("|")
1009 optional = False 1028 optional = False
1010 l = Library(self, name, path, optional, urls, sha1, sourcePath, sourceUrls, sourceSha1, deps) 1029 l = Library(self, name, path, optional, urls, sha1, sourcePath, sourceUrls, sourceSha1, deps)
1011 l.__dict__.update(attrs) 1030 l.__dict__.update(attrs)
1012 self.libs.append(l) 1031 self.libs.append(l)
1013 1032
1014 for name, attrs in distsMap.iteritems(): 1033 for name, attrs in sorted(distsMap.iteritems()):
1015 context = 'distribution ' + name 1034 context = 'distribution ' + name
1016 path = attrs.pop('path') 1035 path = attrs.pop('path')
1017 sourcesPath = attrs.pop('sourcesPath', None) 1036 sourcesPath = attrs.pop('sourcesPath', None)
1018 deps = pop_list(attrs, 'dependencies', context) 1037 deps = pop_list(attrs, 'dependencies', context)
1019 mainClass = attrs.pop('mainClass', None) 1038 mainClass = attrs.pop('mainClass', None)
1287 result = xml.sax.saxutils.escape(result, entities) 1306 result = xml.sax.saxutils.escape(result, entities)
1288 if standalone is not None: 1307 if standalone is not None:
1289 result = result.replace('encoding="UTF-8"?>', 'encoding="UTF-8" standalone="' + str(standalone) + '"?>') 1308 result = result.replace('encoding="UTF-8"?>', 'encoding="UTF-8" standalone="' + str(standalone) + '"?>')
1290 return result 1309 return result
1291 1310
1311 def get_jython_os():
1312 from java.lang import System as System
1313 os_name = System.getProperty('os.name').lower()
1314 if System.getProperty('isCygwin'):
1315 return 'cygwin'
1316 elif os_name.startswith('mac'):
1317 return 'darwin'
1318 elif os_name.startswith('linux'):
1319 return 'linux'
1320 elif os_name.startswith('sunos'):
1321 return 'solaris'
1322 elif os_name.startswith('win'):
1323 return 'windows'
1324 else:
1325 abort('Unknown operating system ' + os_name)
1326
1292 def get_os(): 1327 def get_os():
1293 """ 1328 """
1294 Get a canonical form of sys.platform. 1329 Get a canonical form of sys.platform.
1295 """ 1330 """
1296 if sys.platform.startswith('darwin'): 1331 if is_jython():
1332 return get_jython_os()
1333 elif sys.platform.startswith('darwin'):
1297 return 'darwin' 1334 return 'darwin'
1298 elif sys.platform.startswith('linux'): 1335 elif sys.platform.startswith('linux'):
1299 return 'linux' 1336 return 'linux'
1300 elif sys.platform.startswith('sunos'): 1337 elif sys.platform.startswith('sunos'):
1301 return 'solaris' 1338 return 'solaris'
1311 Translate a path from unix-style to windows-style. 1348 Translate a path from unix-style to windows-style.
1312 This method has no effects on other platforms than cygwin. 1349 This method has no effects on other platforms than cygwin.
1313 """ 1350 """
1314 if p is None or get_os() != "cygwin": 1351 if p is None or get_os() != "cygwin":
1315 return p 1352 return p
1316 return subprocess.check_output(['cygpath', '-w', p]).strip() 1353 return subprocess.check_output(['cygpath', '-a', '-w', p]).strip()
1317 1354
1318 def _cygpathW2U(p): 1355 def _cygpathW2U(p):
1319 """ 1356 """
1320 Translate a path from windows-style to unix-style. 1357 Translate a path from windows-style to unix-style.
1321 This method has no effects on other platforms than cygwin. 1358 This method has no effects on other platforms than cygwin.
1322 """ 1359 """
1323 if p is None or get_os() != "cygwin": 1360 if p is None or get_os() != "cygwin":
1324 return p 1361 return p
1325 return subprocess.check_output(['cygpath', '-u', p]).strip() 1362 return subprocess.check_output(['cygpath', '-a', '-u', p]).strip()
1326 1363
1327 def _separatedCygpathU2W(p): 1364 def _separatedCygpathU2W(p):
1328 """ 1365 """
1329 Translate a group of paths, separated by a path separator. 1366 Translate a group of paths, separated by a path separator.
1330 unix-style to windows-style. 1367 unix-style to windows-style.
1663 self.add_argument('-V', action='store_true', dest='very_verbose', help='enable very verbose output') 1700 self.add_argument('-V', action='store_true', dest='very_verbose', help='enable very verbose output')
1664 self.add_argument('-w', action='store_true', dest='warn', help='enable warning messages') 1701 self.add_argument('-w', action='store_true', dest='warn', help='enable warning messages')
1665 self.add_argument('-p', '--primary-suite-path', help='set the primary suite directory', metavar='<path>') 1702 self.add_argument('-p', '--primary-suite-path', help='set the primary suite directory', metavar='<path>')
1666 self.add_argument('--dbg', type=int, dest='java_dbg_port', help='make Java processes wait on <port> for a debugger', metavar='<port>') 1703 self.add_argument('--dbg', type=int, dest='java_dbg_port', help='make Java processes wait on <port> for a debugger', metavar='<port>')
1667 self.add_argument('-d', action='store_const', const=8000, dest='java_dbg_port', help='alias for "-dbg 8000"') 1704 self.add_argument('-d', action='store_const', const=8000, dest='java_dbg_port', help='alias for "-dbg 8000"')
1705 self.add_argument('--backup-modified', action='store_true', help='backup generated files if they pre-existed and are modified')
1668 self.add_argument('--cp-pfx', dest='cp_prefix', help='class path prefix', metavar='<arg>') 1706 self.add_argument('--cp-pfx', dest='cp_prefix', help='class path prefix', metavar='<arg>')
1669 self.add_argument('--cp-sfx', dest='cp_suffix', help='class path suffix', metavar='<arg>') 1707 self.add_argument('--cp-sfx', dest='cp_suffix', help='class path suffix', metavar='<arg>')
1670 self.add_argument('--J', dest='java_args', help='Java VM arguments (e.g. --J @-dsa)', metavar='@<args>') 1708 self.add_argument('--J', dest='java_args', help='Java VM arguments (e.g. --J @-dsa)', metavar='@<args>')
1671 self.add_argument('--Jp', action='append', dest='java_args_pfx', help='prefix Java VM arguments (e.g. --Jp @-dsa)', metavar='@<args>', default=[]) 1709 self.add_argument('--Jp', action='append', dest='java_args_pfx', help='prefix Java VM arguments (e.g. --Jp @-dsa)', metavar='@<args>', default=[])
1672 self.add_argument('--Ja', action='append', dest='java_args_sfx', help='suffix Java VM arguments (e.g. --Ja @-dsa)', metavar='@<args>', default=[]) 1710 self.add_argument('--Ja', action='append', dest='java_args_sfx', help='suffix Java VM arguments (e.g. --Ja @-dsa)', metavar='@<args>', default=[])
1846 try: 1884 try:
1847 # On Unix, the new subprocess should be in a separate group so that a timeout alarm 1885 # On Unix, the new subprocess should be in a separate group so that a timeout alarm
1848 # can use os.killpg() to kill the whole subprocess group 1886 # can use os.killpg() to kill the whole subprocess group
1849 preexec_fn = None 1887 preexec_fn = None
1850 creationflags = 0 1888 creationflags = 0
1851 if get_os() == 'windows': 1889 if not is_jython():
1852 creationflags = subprocess.CREATE_NEW_PROCESS_GROUP 1890 if get_os() == 'windows':
1853 else: 1891 creationflags = subprocess.CREATE_NEW_PROCESS_GROUP
1854 preexec_fn = os.setsid 1892 else:
1855 1893 preexec_fn = os.setsid
1856 def redirect(stream, f): 1894 def redirect(stream, f):
1857 for line in iter(stream.readline, ''): 1895 for line in iter(stream.readline, ''):
1858 f(line) 1896 f(line)
1859 stream.close() 1897 stream.close()
1860 stdout = out if not callable(out) else subprocess.PIPE 1898 stdout = out if not callable(out) else subprocess.PIPE
2078 if not exists(outDir): 2116 if not exists(outDir):
2079 os.makedirs(outDir) 2117 os.makedirs(outDir)
2080 javaSource = join(myDir, 'ClasspathDump.java') 2118 javaSource = join(myDir, 'ClasspathDump.java')
2081 if not exists(join(outDir, 'ClasspathDump.class')): 2119 if not exists(join(outDir, 'ClasspathDump.class')):
2082 subprocess.check_call([self.javac, '-d', _cygpathU2W(outDir), _cygpathU2W(javaSource)], stderr=subprocess.PIPE, stdout=subprocess.PIPE) 2120 subprocess.check_call([self.javac, '-d', _cygpathU2W(outDir), _cygpathU2W(javaSource)], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
2083 self._bootclasspath, self._extdirs, self._endorseddirs = [x if x != 'null' else None for x in subprocess.check_output([self.java, '-cp', _separatedCygpathU2W(outDir), 'ClasspathDump'], stderr=subprocess.PIPE).split('|')] 2121 self._bootclasspath, self._extdirs, self._endorseddirs = [x if x != 'null' else None for x in subprocess.check_output([self.java, '-cp', _cygpathU2W(outDir), 'ClasspathDump'], stderr=subprocess.PIPE).split('|')]
2084 if not self._bootclasspath or not self._extdirs or not self._endorseddirs: 2122 if not self._bootclasspath or not self._extdirs or not self._endorseddirs:
2085 warn("Could not find all classpaths: boot='" + str(self._bootclasspath) + "' extdirs='" + str(self._extdirs) + "' endorseddirs='" + str(self._endorseddirs) + "'") 2123 warn("Could not find all classpaths: boot='" + str(self._bootclasspath) + "' extdirs='" + str(self._extdirs) + "' endorseddirs='" + str(self._endorseddirs) + "'")
2086 self._bootclasspath = _filter_non_existant_paths(self._bootclasspath) 2124 self._bootclasspath = _filter_non_existant_paths(self._bootclasspath)
2087 self._extdirs = _filter_non_existant_paths(self._extdirs) 2125 self._extdirs = _filter_non_existant_paths(self._extdirs)
2088 self._endorseddirs = _filter_non_existant_paths(self._endorseddirs) 2126 self._endorseddirs = _filter_non_existant_paths(self._endorseddirs)
2226 _send_sigquit() 2264 _send_sigquit()
2227 2265
2228 def is_alive(p): 2266 def is_alive(p):
2229 if isinstance(p, subprocess.Popen): 2267 if isinstance(p, subprocess.Popen):
2230 return p.poll() is None 2268 return p.poll() is None
2231 assert isinstance(p, multiprocessing.Process), p 2269 assert is_jython() or isinstance(p, multiprocessing.Process), p
2232 return p.is_alive() 2270 return p.is_alive()
2233 2271
2234 for p, args in _currentSubprocesses: 2272 for p, args in _currentSubprocesses:
2235 if is_alive(p): 2273 if is_alive(p):
2236 try: 2274 try:
2285 with open(path, 'rb') as f: 2323 with open(path, 'rb') as f:
2286 old = f.read() 2324 old = f.read()
2287 2325
2288 if old == content: 2326 if old == content:
2289 return False 2327 return False
2328
2329 if existed and _opts.backup_modified:
2330 shutil.move(path, path + '.orig')
2290 2331
2291 with open(path, 'wb') as f: 2332 with open(path, 'wb') as f:
2292 f.write(content) 2333 f.write(content)
2293 2334
2294 log(('modified ' if existed else 'created ') + path) 2335 log(('modified ' if existed else 'created ') + path)
2432 parser = ArgumentParser(prog='mx build') 2473 parser = ArgumentParser(prog='mx build')
2433 2474
2434 parser = parser if parser is not None else ArgumentParser(prog='mx build') 2475 parser = parser if parser is not None else ArgumentParser(prog='mx build')
2435 parser.add_argument('-f', action='store_true', dest='force', help='force build (disables timestamp checking)') 2476 parser.add_argument('-f', action='store_true', dest='force', help='force build (disables timestamp checking)')
2436 parser.add_argument('-c', action='store_true', dest='clean', help='removes existing build output') 2477 parser.add_argument('-c', action='store_true', dest='clean', help='removes existing build output')
2437 parser.add_argument('-p', action='store_true', dest='parallelize', help='parallelizes Java compilation') 2478 parser.add_argument('-p', action='store_true', dest='parallelize', help='parallelizes Java compilation if possible')
2438 parser.add_argument('--source', dest='compliance', help='Java compliance level for projects without an explicit one') 2479 parser.add_argument('--source', dest='compliance', help='Java compliance level for projects without an explicit one')
2439 parser.add_argument('--Wapi', action='store_true', dest='warnAPI', help='show warnings about using internal APIs') 2480 parser.add_argument('--Wapi', action='store_true', dest='warnAPI', help='show warnings about using internal APIs')
2440 parser.add_argument('--projects', action='store', help='comma separated projects to build (omit to build all projects)') 2481 parser.add_argument('--projects', action='store', help='comma separated projects to build (omit to build all projects)')
2441 parser.add_argument('--only', action='store', help='comma separated projects to build, without checking their dependencies (omit to build all projects)') 2482 parser.add_argument('--only', action='store', help='comma separated projects to build, without checking their dependencies (omit to build all projects)')
2442 parser.add_argument('--no-java', action='store_false', dest='java', help='do not build Java projects') 2483 parser.add_argument('--no-java', action='store_false', dest='java', help='do not build Java projects')
2452 if suppliedParser: 2493 if suppliedParser:
2453 parser.add_argument('remainder', nargs=REMAINDER, metavar='...') 2494 parser.add_argument('remainder', nargs=REMAINDER, metavar='...')
2454 2495
2455 args = parser.parse_args(args) 2496 args = parser.parse_args(args)
2456 2497
2498 if is_jython():
2499 if args.parallelize:
2500 logv('[multiprocessing not available in jython]')
2501 args.parallelize = False
2502
2457 jdtJar = None 2503 jdtJar = None
2458 if not args.javac and args.jdt is not None: 2504 if not args.javac and args.jdt is not None:
2459 if not args.jdt.endswith('.jar'): 2505 if not args.jdt.endswith('.jar'):
2460 abort('Path for Eclipse batch compiler does not look like a jar file: ' + args.jdt) 2506 abort('Path for Eclipse batch compiler does not look like a jar file: ' + args.jdt)
2461 jdtJar = args.jdt 2507 jdtJar = args.jdt
2608 def sortWorklist(tasks): 2654 def sortWorklist(tasks):
2609 for t in tasks: 2655 for t in tasks:
2610 t._d = None 2656 t._d = None
2611 return sorted(tasks, compareTasks) 2657 return sorted(tasks, compareTasks)
2612 2658
2613 cpus = multiprocessing.cpu_count() 2659 cpus = cpu_count()
2614 worklist = sortWorklist(tasks.values()) 2660 worklist = sortWorklist(tasks.values())
2615 active = [] 2661 active = []
2616 failed = [] 2662 failed = []
2617 while len(worklist) != 0: 2663 while len(worklist) != 0:
2618 while True: 2664 while True:
3562 else: 3608 else:
3563 libraryDeps.add(dep) 3609 libraryDeps.add(dep)
3564 elif dep.isProject(): 3610 elif dep.isProject():
3565 projectDeps.add(dep) 3611 projectDeps.add(dep)
3566 3612
3567 for dep in containerDeps: 3613 for dep in sorted(containerDeps):
3568 out.element('classpathentry', {'exported' : 'true', 'kind' : 'con', 'path' : dep}) 3614 out.element('classpathentry', {'exported' : 'true', 'kind' : 'con', 'path' : dep})
3569 3615
3570 for dep in libraryDeps: 3616 for dep in sorted(libraryDeps):
3571 path = dep.path 3617 path = dep.path
3572 dep.get_path(resolve=True) 3618 dep.get_path(resolve=True)
3573 3619
3574 # Relative paths for "lib" class path entries have various semantics depending on the Eclipse 3620 # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
3575 # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's 3621 # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
3583 attributes['sourcepath'] = sourcePath 3629 attributes['sourcepath'] = sourcePath
3584 out.element('classpathentry', attributes) 3630 out.element('classpathentry', attributes)
3585 if libFiles: 3631 if libFiles:
3586 libFiles.append(path) 3632 libFiles.append(path)
3587 3633
3588 for dep in projectDeps: 3634 for dep in sorted(projectDeps):
3589 out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + dep.name}) 3635 out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + dep.name})
3590 3636
3591 out.element('classpathentry', {'kind' : 'output', 'path' : getattr(p, 'eclipse.output', 'bin')}) 3637 out.element('classpathentry', {'kind' : 'output', 'path' : getattr(p, 'eclipse.output', 'bin')})
3592 out.close('classpath') 3638 out.close('classpath')
3593 classpathFile = join(p.dir, '.classpath') 3639 classpathFile = join(p.dir, '.classpath')
4459 compilerXml.element('entry', attributes={'name': '!?*.java'}) 4505 compilerXml.element('entry', attributes={'name': '!?*.java'})
4460 compilerXml.close('wildcardResourcePatterns') 4506 compilerXml.close('wildcardResourcePatterns')
4461 4507
4462 if annotationProcessorProfiles: 4508 if annotationProcessorProfiles:
4463 compilerXml.open('annotationProcessing') 4509 compilerXml.open('annotationProcessing')
4464 for processors, modules in annotationProcessorProfiles.items(): 4510 for processors, modules in sorted(annotationProcessorProfiles.iteritems()):
4465 compilerXml.open('profile', attributes={'default': 'false', 'name': '-'.join(processors), 'enabled': 'true'}) 4511 compilerXml.open('profile', attributes={'default': 'false', 'name': '-'.join(processors), 'enabled': 'true'})
4466 compilerXml.element('sourceOutputDir', attributes={'name': 'src_gen'}) # TODO use p.source_gen_dir() ? 4512 compilerXml.element('sourceOutputDir', attributes={'name': 'src_gen'}) # TODO use p.source_gen_dir() ?
4467 compilerXml.element('outputRelativeToContentRoot', attributes={'value': 'true'}) 4513 compilerXml.element('outputRelativeToContentRoot', attributes={'value': 'true'})
4468 compilerXml.open('processorPath', attributes={'useClasspath': 'false'}) 4514 compilerXml.open('processorPath', attributes={'useClasspath': 'false'})
4469 for apName in processors: 4515 for apName in processors:
5234 abort('mx: command \'{0}\' is ambiguous\n {1}'.format(command, ' '.join(hits))) 5280 abort('mx: command \'{0}\' is ambiguous\n {1}'.format(command, ' '.join(hits)))
5235 5281
5236 c, _ = _commands[command][:2] 5282 c, _ = _commands[command][:2]
5237 def term_handler(signum, frame): 5283 def term_handler(signum, frame):
5238 abort(1) 5284 abort(1)
5239 signal.signal(signal.SIGTERM, term_handler) 5285 if not is_jython():
5286 signal.signal(signal.SIGTERM, term_handler)
5240 5287
5241 def quit_handler(signum, frame): 5288 def quit_handler(signum, frame):
5242 _send_sigquit() 5289 _send_sigquit()
5243 if get_os() != 'windows': 5290 if not is_jython() and get_os() != 'windows':
5244 signal.signal(signal.SIGQUIT, quit_handler) 5291 signal.signal(signal.SIGQUIT, quit_handler)
5245 5292
5246 try: 5293 try:
5247 if opts.timeout != 0: 5294 if opts.timeout != 0:
5248 def alarm_handler(signum, frame): 5295 def alarm_handler(signum, frame):