comparison mxtool/mx.py @ 15528:a3f897fb3289

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Mon, 05 May 2014 22:18:46 +0200
parents 1f28c463e452
children 406a94c03ffa
comparison
equal deleted inserted replaced
15527:ff5cacf47b68 15528:a3f897fb3289
1298 abort('Process timed out after {0} seconds: {1}'.format(timeout, ' '.join(args))) 1298 abort('Process timed out after {0} seconds: {1}'.format(timeout, ' '.join(args)))
1299 delay = min(delay * 2, remaining, .05) 1299 delay = min(delay * 2, remaining, .05)
1300 time.sleep(delay) 1300 time.sleep(delay)
1301 1301
1302 # Makes the current subprocess accessible to the abort() function 1302 # Makes the current subprocess accessible to the abort() function
1303 # This is a tuple of the Popen object and args. 1303 # This is a list of tuples of the subprocess.Popen or
1304 _currentSubprocess = (None, None) 1304 # multiprocessing.Process object and args.
1305 _currentSubprocesses = []
1306
1307 def _addSubprocess(p, args):
1308 entry = (p, args)
1309 _currentSubprocesses.append(entry)
1310 return entry
1311
1312 def _removeSubprocess(entry):
1313 if entry and entry in _currentSubprocesses:
1314 try:
1315 _currentSubprocesses.remove(entry)
1316 except:
1317 pass
1305 1318
1306 def waitOn(p): 1319 def waitOn(p):
1307 if get_os() == 'windows': 1320 if get_os() == 'windows':
1308 # on windows use a poll loop, otherwise signal does not get handled 1321 # on windows use a poll loop, otherwise signal does not get handled
1309 retcode = None 1322 retcode = None
1338 log(' '.join(map(pipes.quote, args))) 1351 log(' '.join(map(pipes.quote, args)))
1339 1352
1340 if timeout is None and _opts.ptimeout != 0: 1353 if timeout is None and _opts.ptimeout != 0:
1341 timeout = _opts.ptimeout 1354 timeout = _opts.ptimeout
1342 1355
1343 global _currentSubprocess 1356 sub = None
1344
1345 try: 1357 try:
1346 # On Unix, the new subprocess should be in a separate group so that a timeout alarm 1358 # On Unix, the new subprocess should be in a separate group so that a timeout alarm
1347 # can use os.killpg() to kill the whole subprocess group 1359 # can use os.killpg() to kill the whole subprocess group
1348 preexec_fn = None 1360 preexec_fn = None
1349 creationflags = 0 1361 creationflags = 0
1357 f(line) 1369 f(line)
1358 stream.close() 1370 stream.close()
1359 stdout = out if not callable(out) else subprocess.PIPE 1371 stdout = out if not callable(out) else subprocess.PIPE
1360 stderr = err if not callable(err) else subprocess.PIPE 1372 stderr = err if not callable(err) else subprocess.PIPE
1361 p = subprocess.Popen(args, cwd=cwd, stdout=stdout, stderr=stderr, preexec_fn=preexec_fn, creationflags=creationflags, env=env) 1373 p = subprocess.Popen(args, cwd=cwd, stdout=stdout, stderr=stderr, preexec_fn=preexec_fn, creationflags=creationflags, env=env)
1362 _currentSubprocess = (p, args) 1374 sub = _addSubprocess(p, args)
1363 if callable(out): 1375 if callable(out):
1364 t = Thread(target=redirect, args=(p.stdout, out)) 1376 t = Thread(target=redirect, args=(p.stdout, out))
1365 t.daemon = True # thread dies with the program 1377 t.daemon = True # thread dies with the program
1366 t.start() 1378 t.start()
1367 if callable(err): 1379 if callable(err):
1380 raise e 1392 raise e
1381 abort(e.errno) 1393 abort(e.errno)
1382 except KeyboardInterrupt: 1394 except KeyboardInterrupt:
1383 abort(1) 1395 abort(1)
1384 finally: 1396 finally:
1385 _currentSubprocess = (None, None) 1397 _removeSubprocess(sub)
1386 1398
1387 if retcode and nonZeroIsFatal: 1399 if retcode and nonZeroIsFatal:
1388 if _opts.verbose: 1400 if _opts.verbose:
1389 if _opts.very_verbose: 1401 if _opts.very_verbose:
1390 raise subprocess.CalledProcessError(retcode, ' '.join(args)) 1402 raise subprocess.CalledProcessError(retcode, ' '.join(args))
1661 if '$' in result or '%' in result: 1673 if '$' in result or '%' in result:
1662 abort('Property contains an undefined environment variable: ' + value) 1674 abort('Property contains an undefined environment variable: ' + value)
1663 return result 1675 return result
1664 1676
1665 def _send_sigquit(): 1677 def _send_sigquit():
1666 p, args = _currentSubprocess 1678 for p, args in _currentSubprocesses:
1667 1679
1668 def _isJava(): 1680 def _isJava():
1669 if args: 1681 if args:
1670 name = args[0].split(os.sep)[-1] 1682 name = args[0].split(os.sep)[-1]
1671 return name == "java" 1683 return name == "java"
1672 return False 1684 return False
1673 1685
1674 if p is not None and _isJava(): 1686 if p is not None and _isJava():
1675 if get_os() == 'windows': 1687 if get_os() == 'windows':
1676 log("mx: implement me! want to send SIGQUIT to my child process") 1688 log("mx: implement me! want to send SIGQUIT to my child process")
1677 else: 1689 else:
1678 _kill_process_group(p.pid, sig=signal.SIGQUIT) 1690 _kill_process_group(p.pid, sig=signal.SIGQUIT)
1679 time.sleep(0.1) 1691 time.sleep(0.1)
1680
1681 1692
1682 def abort(codeOrMessage): 1693 def abort(codeOrMessage):
1683 """ 1694 """
1684 Aborts the program with a SystemExit exception. 1695 Aborts the program with a SystemExit exception.
1685 If 'codeOrMessage' is a plain integer, it specifies the system exit status; 1696 If 'codeOrMessage' is a plain integer, it specifies the system exit status;
1690 if _opts.killwithsigquit: 1701 if _opts.killwithsigquit:
1691 _send_sigquit() 1702 _send_sigquit()
1692 1703
1693 # import traceback 1704 # import traceback
1694 # traceback.print_stack() 1705 # traceback.print_stack()
1695 p, _ = _currentSubprocess 1706 for p, args in _currentSubprocesses:
1696 if p is not None: 1707 try:
1697 if get_os() == 'windows': 1708 if get_os() == 'windows':
1698 p.kill() 1709 p.terminate()
1699 else: 1710 else:
1700 _kill_process_group(p.pid, signal.SIGKILL) 1711 _kill_process_group(p.pid, signal.SIGKILL)
1712 except BaseException as e:
1713 log('error while killing subprocess {} "{}": {}'.format(p.pid, ' '.join(args), e))
1701 1714
1702 raise SystemExit(codeOrMessage) 1715 raise SystemExit(codeOrMessage)
1703 1716
1704 def download(path, urls, verbose=False): 1717 def download(path, urls, verbose=False):
1705 """ 1718 """
1796 1809
1797 def _defaultEcjPath(): 1810 def _defaultEcjPath():
1798 return get_env('JDT', join(_primary_suite.mxDir, 'ecj.jar')) 1811 return get_env('JDT', join(_primary_suite.mxDir, 'ecj.jar'))
1799 1812
1800 class JavaCompileTask: 1813 class JavaCompileTask:
1801 def __init__(self, args, proj, reason, javafilelist, jdk, outputDir, deps): 1814 def __init__(self, args, proj, reason, javafilelist, jdk, outputDir, jdtJar, deps):
1802 self.proj = proj 1815 self.proj = proj
1803 self.reason = reason 1816 self.reason = reason
1804 self.javafilelist = javafilelist 1817 self.javafilelist = javafilelist
1805 self.deps = deps 1818 self.deps = deps
1806 self.jdk = jdk 1819 self.jdk = jdk
1807 self.outputDir = outputDir 1820 self.outputDir = outputDir
1808 self.done = False 1821 self.done = False
1822 self.jdtJar = jdtJar
1809 self.args = args 1823 self.args = args
1810 1824
1811 def __str__(self): 1825 def __str__(self):
1812 return self.proj.name 1826 return self.proj.name
1813 1827
1838 outputDir = self.outputDir 1852 outputDir = self.outputDir
1839 compliance = str(jdk.javaCompliance) 1853 compliance = str(jdk.javaCompliance)
1840 cp = classpath(self.proj.name, includeSelf=True) 1854 cp = classpath(self.proj.name, includeSelf=True)
1841 toBeDeleted = [argfileName] 1855 toBeDeleted = [argfileName]
1842 1856
1843 jdtJar = None
1844 if not args.javac and args.jdt is not None:
1845 if not args.jdt.endswith('.jar'):
1846 abort('Path for Eclipse batch compiler does not look like a jar file: ' + args.jdt)
1847 jdtJar = args.jdt
1848 if not exists(jdtJar):
1849 if os.path.abspath(jdtJar) == os.path.abspath(_defaultEcjPath()) and get_env('JDT', None) is None:
1850 # Silently ignore JDT if default location is used but does not exist
1851 jdtJar = None
1852 else:
1853 abort('Eclipse batch compiler jar does not exist: ' + args.jdt)
1854
1855 try: 1857 try:
1856 if not jdtJar: 1858 if not self.jdtJar:
1857 mainJava = java() 1859 mainJava = java()
1858 if not args.error_prone: 1860 if not args.error_prone:
1859 self.logCompilation('javac') 1861 self.logCompilation('javac')
1860 javacCmd = [mainJava.javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir, '-bootclasspath', jdk.bootclasspath(), '-endorseddirs', jdk.endorseddirs(), '-extdirs', jdk.extdirs()] 1862 javacCmd = [mainJava.javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir, '-bootclasspath', jdk.bootclasspath(), '-endorseddirs', jdk.endorseddirs(), '-extdirs', jdk.extdirs()]
1861 if jdk.debug_port is not None: 1863 if jdk.debug_port is not None:
1876 javacArgs.append('-XDignore.symbol.file') 1878 javacArgs.append('-XDignore.symbol.file')
1877 run_java(javaArgs + ['-cp', os.pathsep.join([mainJava.toolsjar, args.error_prone]), 'com.google.errorprone.ErrorProneCompiler'] + javacArgs) 1879 run_java(javaArgs + ['-cp', os.pathsep.join([mainJava.toolsjar, args.error_prone]), 'com.google.errorprone.ErrorProneCompiler'] + javacArgs)
1878 else: 1880 else:
1879 self.logCompilation('JDT') 1881 self.logCompilation('JDT')
1880 1882
1881 jdtVmArgs = ['-Xmx1g', '-jar', jdtJar] 1883 jdtVmArgs = ['-Xmx1g', '-jar', self.jdtJar]
1882 1884
1883 jdtArgs = ['-' + compliance, 1885 jdtArgs = ['-' + compliance,
1884 '-cp', cp, '-g', '-enableJavadoc', 1886 '-cp', cp, '-g', '-enableJavadoc',
1885 '-d', outputDir, 1887 '-d', outputDir,
1886 '-bootclasspath', jdk.bootclasspath(), 1888 '-bootclasspath', jdk.bootclasspath(),
1944 compilerSelect = parser.add_mutually_exclusive_group() 1946 compilerSelect = parser.add_mutually_exclusive_group()
1945 compilerSelect.add_argument('--error-prone', dest='error_prone', help='path to error-prone.jar', metavar='<path>') 1947 compilerSelect.add_argument('--error-prone', dest='error_prone', help='path to error-prone.jar', metavar='<path>')
1946 compilerSelect.add_argument('--jdt', help='path to ecj.jar, the Eclipse batch compiler', default=_defaultEcjPath(), metavar='<path>') 1948 compilerSelect.add_argument('--jdt', help='path to ecj.jar, the Eclipse batch compiler', default=_defaultEcjPath(), metavar='<path>')
1947 compilerSelect.add_argument('--force-javac', action='store_true', dest='javac', help='use javac despite ecj.jar is found or not') 1949 compilerSelect.add_argument('--force-javac', action='store_true', dest='javac', help='use javac despite ecj.jar is found or not')
1948 1950
1949
1950 if suppliedParser: 1951 if suppliedParser:
1951 parser.add_argument('remainder', nargs=REMAINDER, metavar='...') 1952 parser.add_argument('remainder', nargs=REMAINDER, metavar='...')
1952 1953
1953 args = parser.parse_args(args) 1954 args = parser.parse_args(args)
1955
1956 jdtJar = None
1957 if not args.javac and args.jdt is not None:
1958 if not args.jdt.endswith('.jar'):
1959 abort('Path for Eclipse batch compiler does not look like a jar file: ' + args.jdt)
1960 jdtJar = args.jdt
1961 if not exists(jdtJar):
1962 if os.path.abspath(jdtJar) == os.path.abspath(_defaultEcjPath()) and get_env('JDT', None) is None:
1963 # Silently ignore JDT if default location is used but does not exist
1964 jdtJar = None
1965 else:
1966 abort('Eclipse batch compiler jar does not exist: ' + args.jdt)
1954 1967
1955 if args.only is not None: 1968 if args.only is not None:
1956 # N.B. This build will not include dependencies including annotation processor dependencies 1969 # N.B. This build will not include dependencies including annotation processor dependencies
1957 sortedProjects = [project(name) for name in args.only.split(',')] 1970 sortedProjects = [project(name) for name in args.only.split(',')]
1958 else: 1971 else:
2085 2098
2086 if len(javafilelist) == 0: 2099 if len(javafilelist) == 0:
2087 logv('[no Java sources for {0} - skipping]'.format(p.name)) 2100 logv('[no Java sources for {0} - skipping]'.format(p.name))
2088 continue 2101 continue
2089 2102
2090 task = JavaCompileTask(args, p, buildReason, javafilelist, jdk, outputDir, taskDeps) 2103 task = JavaCompileTask(args, p, buildReason, javafilelist, jdk, outputDir, jdtJar, taskDeps)
2091 2104
2092 if args.parallelize: 2105 if args.parallelize:
2093 # Best to initialize class paths on main process 2106 # Best to initialize class paths on main process
2094 jdk.bootclasspath() 2107 jdk.bootclasspath()
2095 task.proc = None 2108 task.proc = None
2111 active = [] 2124 active = []
2112 for t in tasks: 2125 for t in tasks:
2113 if t.proc.is_alive(): 2126 if t.proc.is_alive():
2114 active.append(t) 2127 active.append(t)
2115 else: 2128 else:
2129 _removeSubprocess(t.sub)
2116 if t.proc.exitcode != 0: 2130 if t.proc.exitcode != 0:
2117 return ([], joinTasks(tasks)) 2131 return ([], joinTasks(tasks))
2118 return (active, []) 2132 return (active, [])
2119 2133
2120 def remainingDepsDepth(task): 2134 def remainingDepsDepth(task):
2124 task._d = 0 2138 task._d = 0
2125 else: 2139 else:
2126 task._d = max([remainingDepsDepth(t) for t in incompleteDeps]) + 1 2140 task._d = max([remainingDepsDepth(t) for t in incompleteDeps]) + 1
2127 return task._d 2141 return task._d
2128 2142
2143 def compareTasks(t1, t2):
2144 d = remainingDepsDepth(t1) - remainingDepsDepth(t2)
2145 if d == 0:
2146 t1Work = (1 + len(t1.proj.annotation_processors())) * len(t1.javafilelist)
2147 t2Work = (1 + len(t2.proj.annotation_processors())) * len(t2.javafilelist)
2148 d = t1Work - t2Work
2149 return d
2150
2129 def sortWorklist(tasks): 2151 def sortWorklist(tasks):
2130 for t in tasks: 2152 for t in tasks:
2131 t._d = None 2153 t._d = None
2132 return sorted(tasks, lambda x, y: remainingDepsDepth(x) - remainingDepsDepth(y)) 2154 return sorted(tasks, compareTasks)
2133 2155
2134 import multiprocessing 2156 import multiprocessing
2135 cpus = multiprocessing.cpu_count() 2157 cpus = multiprocessing.cpu_count()
2136 worklist = sortWorklist(tasks.values()) 2158 worklist = sortWorklist(tasks.values())
2137 active = [] 2159 active = []
2160 if depsDone(task): 2182 if depsDone(task):
2161 worklist.remove(task) 2183 worklist.remove(task)
2162 task.proc = multiprocessing.Process(target=executeTask, args=(task,)) 2184 task.proc = multiprocessing.Process(target=executeTask, args=(task,))
2163 task.proc.start() 2185 task.proc.start()
2164 active.append(task) 2186 active.append(task)
2187 task.sub = _addSubprocess(task.proc, ['JavaCompileTask', str(task)])
2165 if len(active) == cpus: 2188 if len(active) == cpus:
2166 break 2189 break
2167 2190
2168 worklist = sortWorklist(worklist) 2191 worklist = sortWorklist(worklist)
2169 joinTasks(active) 2192 joinTasks(active)