comparison mxtool/mx.py @ 21165:bdeaa5a7b83c

Look for JDKs on demand, add --strict-compliance flag. Allow more precise search for JDK versions (use it for IGV)
author Gilles Duboscq <gilles.m.duboscq@oracle.com>
date Thu, 30 Apr 2015 18:49:00 +0200
parents 53b2d64f8ad1
children f383ff4c9af8
comparison
equal deleted inserted replaced
21164:a394890fd474 21165:bdeaa5a7b83c
92 _suites = dict() 92 _suites = dict()
93 _annotationProcessors = None 93 _annotationProcessors = None
94 _primary_suite_path = None 94 _primary_suite_path = None
95 _primary_suite = None 95 _primary_suite = None
96 _opts = None 96 _opts = None
97 _java_homes = None 97 _extra_java_homes = []
98 _default_java_home = None
98 _warn = False 99 _warn = False
99 100
100 """ 101 """
101 A distribution is a jar or zip file containing the output from one or more Java projects. 102 A distribution is a jar or zip file containing the output from one or more Java projects.
102 """ 103 """
210 p = dep 211 p = dep
211 212
212 if self.javaCompliance: 213 if self.javaCompliance:
213 if p.javaCompliance > self.javaCompliance: 214 if p.javaCompliance > self.javaCompliance:
214 abort("Compliance level doesn't match: Distribution {0} requires {1}, but {2} is {3}.".format(self.name, self.javaCompliance, p.name, p.javaCompliance)) 215 abort("Compliance level doesn't match: Distribution {0} requires {1}, but {2} is {3}.".format(self.name, self.javaCompliance, p.name, p.javaCompliance))
215
216 # skip a Java project if its Java compliance level is "higher" than the configured JDK
217 jdk = java(p.javaCompliance)
218 assert jdk
219 216
220 logv('[' + self.path + ': adding project ' + p.name + ']') 217 logv('[' + self.path + ': adding project ' + p.name + ']')
221 outputDir = p.output_dir() 218 outputDir = p.output_dir()
222 for root, _, files in os.walk(outputDir): 219 for root, _, files in os.walk(outputDir):
223 relpath = root[len(outputDir) + 1:] 220 relpath = root[len(outputDir) + 1:]
304 301
305 # The annotation processors defined by this project 302 # The annotation processors defined by this project
306 self.definedAnnotationProcessors = None 303 self.definedAnnotationProcessors = None
307 self.definedAnnotationProcessorsDist = None 304 self.definedAnnotationProcessorsDist = None
308 305
309
310 # Verify that a JDK exists for this project if its compliance level is
311 # less than the compliance level of the default JDK
312 jdk = java(self.javaCompliance)
313 if jdk is None and self.javaCompliance < java().javaCompliance:
314 abort('Cannot find ' + str(self.javaCompliance) + ' JDK required by ' + name + '. ' +
315 'Specify it with --extra-java-homes option or EXTRA_JAVA_HOMES environment variable.')
316
317 # Create directories for projects that don't yet exist 306 # Create directories for projects that don't yet exist
318 if not exists(d): 307 if not exists(d):
319 os.mkdir(d) 308 os.mkdir(d)
320 for s in self.source_dirs(): 309 for s in self.source_dirs():
321 if not exists(s): 310 if not exists(s):
753 def get_path(self, resolve): 742 def get_path(self, resolve):
754 path = _make_absolute(self.path, self.suite.dir) 743 path = _make_absolute(self.path, self.suite.dir)
755 sha1path = path + '.sha1' 744 sha1path = path + '.sha1'
756 745
757 includedInJDK = getattr(self, 'includedInJDK', None) 746 includedInJDK = getattr(self, 'includedInJDK', None)
747 # TODO since we don't know which JDK will be used, this check is dubious
758 if includedInJDK and java().javaCompliance >= JavaCompliance(includedInJDK): 748 if includedInJDK and java().javaCompliance >= JavaCompliance(includedInJDK):
759 return None 749 return None
760 750
761 bootClassPathAgent = getattr(self, 'bootClassPathAgent').lower() == 'true' if hasattr(self, 'bootClassPathAgent') else False 751 bootClassPathAgent = getattr(self, 'bootClassPathAgent').lower() == 'true' if hasattr(self, 'bootClassPathAgent') else False
762 752
1228 if not path: 1218 if not path:
1229 logv('[omitting optional library {0} as {1} does not exist]'.format(d, d.path)) 1219 logv('[omitting optional library {0} as {1} does not exist]'.format(d, d.path))
1230 del _libs[d.name] 1220 del _libs[d.name]
1231 self.libs.remove(d) 1221 self.libs.remove(d)
1232 elif d.isProject(): 1222 elif d.isProject():
1233 if java(d.javaCompliance) is None: 1223 if java(d.javaCompliance, cancel='some projects will be omitted which may result in errrors') is None:
1234 logv('[omitting project {0} as Java compliance {1} cannot be satisfied by configured JDKs]'.format(d, d.javaCompliance)) 1224 logv('[omitting project {0} as Java compliance {1} cannot be satisfied by configured JDKs]'.format(d, d.javaCompliance))
1235 del _projects[d.name] 1225 del _projects[d.name]
1236 self.projects.remove(d) 1226 self.projects.remove(d)
1237 else: 1227 else:
1238 for name in list(d.deps): 1228 for name in list(d.deps):
1654 deps = [] 1644 deps = []
1655 for p in projects: 1645 for p in projects:
1656 p.all_deps(deps, includeLibs=includeLibs, includeJreLibs=includeJreLibs, includeAnnotationProcessors=includeAnnotationProcessors) 1646 p.all_deps(deps, includeLibs=includeLibs, includeJreLibs=includeJreLibs, includeAnnotationProcessors=includeAnnotationProcessors)
1657 return deps 1647 return deps
1658 1648
1659 def _handle_lookup_java_home(jdk):
1660 return _handle_lookup_jdk(jdk, 'JAVA_HOME', '--java-home', False)
1661
1662 def _handle_lookup_extra_java_homes(jdk):
1663 return _handle_lookup_jdk(jdk, 'EXTRA_JAVA_HOMES', '--extra-java-homes', True)
1664
1665 def _handle_lookup_jdk(jdk, varName, flagName, allowMultiple):
1666 if jdk != None and jdk != '':
1667 return jdk
1668 jdk = os.environ.get(varName)
1669 if jdk != None and jdk != '':
1670 return jdk
1671
1672 if not sys.stdout.isatty():
1673 abort('Could not find bootstrap {0}. Use {1} option or ensure {2} environment variable is set.'.format(varName, flagName, varName))
1674
1675 candidateJdks = []
1676 if get_os() == 'darwin':
1677 base = '/Library/Java/JavaVirtualMachines'
1678 if exists(base):
1679 candidateJdks = [join(base, n, 'Contents/Home') for n in os.listdir(base) if exists(join(base, n, 'Contents/Home'))]
1680 elif get_os() == 'linux':
1681 base = '/usr/lib/jvm'
1682 if exists(base):
1683 candidateJdks = [join(base, n) for n in os.listdir(base) if exists(join(base, n, 'jre/lib/rt.jar'))]
1684 base = '/usr/java'
1685 if exists(base):
1686 candidateJdks += [join(base, n) for n in os.listdir(base) if exists(join(base, n, 'jre/lib/rt.jar'))]
1687 elif get_os() == 'solaris':
1688 base = '/usr/jdk/instances'
1689 if exists(base):
1690 candidateJdks = [join(base, n) for n in os.listdir(base) if exists(join(base, n, 'jre/lib/rt.jar'))]
1691 elif get_os() == 'windows':
1692 base = r'C:\Program Files\Java'
1693 if exists(base):
1694 candidateJdks = [join(base, n) for n in os.listdir(base) if exists(join(base, n, r'jre\lib\rt.jar'))]
1695
1696 javaHome = None
1697 if len(candidateJdks) != 0:
1698 log('Missing value for {0}.'.format(varName))
1699 javaHome = select_items(candidateJdks + ['<other>'], allowMultiple=allowMultiple)
1700 if javaHome == '<other>':
1701 javaHome = None
1702 if javaHome != None and allowMultiple:
1703 javaHome = os.pathsep.join(javaHome)
1704
1705 while javaHome is None:
1706 javaHome = raw_input('Enter path of JDK for {0}: '.format(varName))
1707 rtJarPath = join(javaHome, 'jre', 'lib', 'rt.jar')
1708 if not exists(rtJarPath):
1709 log('Does not appear to be a valid JDK as ' + rtJarPath + ' does not exist')
1710 javaHome = None
1711 else:
1712 break
1713
1714 envPath = join(_primary_suite.mxDir, 'env')
1715 if ask_yes_no('Persist this setting by adding "{0}={1}" to {2}'.format(varName, javaHome, envPath), 'y'):
1716 with open(envPath, 'a') as fp:
1717 print >> fp, varName + '=' + javaHome
1718
1719 return javaHome
1720
1721 class ArgParser(ArgumentParser): 1649 class ArgParser(ArgumentParser):
1722 # Override parent to append the list of available commands 1650 # Override parent to append the list of available commands
1723 def format_help(self): 1651 def format_help(self):
1724 return ArgumentParser.format_help(self) + _format_commands() 1652 return ArgumentParser.format_help(self) + _format_commands()
1725 1653
1742 self.add_argument('--Jp', action='append', dest='java_args_pfx', help='prefix Java VM arguments (e.g. --Jp @-dsa)', metavar='@<args>', default=[]) 1670 self.add_argument('--Jp', action='append', dest='java_args_pfx', help='prefix Java VM arguments (e.g. --Jp @-dsa)', metavar='@<args>', default=[])
1743 self.add_argument('--Ja', action='append', dest='java_args_sfx', help='suffix Java VM arguments (e.g. --Ja @-dsa)', metavar='@<args>', default=[]) 1671 self.add_argument('--Ja', action='append', dest='java_args_sfx', help='suffix Java VM arguments (e.g. --Ja @-dsa)', metavar='@<args>', default=[])
1744 self.add_argument('--user-home', help='users home directory', metavar='<path>', default=os.path.expanduser('~')) 1672 self.add_argument('--user-home', help='users home directory', metavar='<path>', default=os.path.expanduser('~'))
1745 self.add_argument('--java-home', help='primary JDK directory (must be JDK 7 or later)', metavar='<path>') 1673 self.add_argument('--java-home', help='primary JDK directory (must be JDK 7 or later)', metavar='<path>')
1746 self.add_argument('--extra-java-homes', help='secondary JDK directories separated by "' + os.pathsep + '"', metavar='<path>') 1674 self.add_argument('--extra-java-homes', help='secondary JDK directories separated by "' + os.pathsep + '"', metavar='<path>')
1675 self.add_argument('--strict-compliance', action='store_true', dest='strict_compliance', help='Projects of a certain compliance will only be built with a JDK of this exact compliance', default=bool(os.environ.get('STRICT_COMPLIANCE')))
1747 self.add_argument('--ignore-project', action='append', dest='ignored_projects', help='name of project to ignore', metavar='<name>', default=[]) 1676 self.add_argument('--ignore-project', action='append', dest='ignored_projects', help='name of project to ignore', metavar='<name>', default=[])
1748 self.add_argument('--kill-with-sigquit', action='store_true', dest='killwithsigquit', help='send sigquit first before killing child processes') 1677 self.add_argument('--kill-with-sigquit', action='store_true', dest='killwithsigquit', help='send sigquit first before killing child processes')
1749 if get_os() != 'windows': 1678 if get_os() != 'windows':
1750 # Time outs are (currently) implemented with Unix specific functionality 1679 # Time outs are (currently) implemented with Unix specific functionality
1751 self.add_argument('--timeout', help='timeout (in seconds) for command', type=int, default=0, metavar='<secs>') 1680 self.add_argument('--timeout', help='timeout (in seconds) for command', type=int, default=0, metavar='<secs>')
1767 opts.__dict__.setdefault('ptimeout', 0) 1696 opts.__dict__.setdefault('ptimeout', 0)
1768 1697
1769 if opts.very_verbose: 1698 if opts.very_verbose:
1770 opts.verbose = True 1699 opts.verbose = True
1771 1700
1772 opts.java_home = _handle_lookup_java_home(opts.java_home)
1773 opts.extra_java_homes = _handle_lookup_extra_java_homes(opts.extra_java_homes)
1774
1775 if opts.user_home is None or opts.user_home == '': 1701 if opts.user_home is None or opts.user_home == '':
1776 abort('Could not find user home. Use --user-home option or ensure HOME environment variable is set.') 1702 abort('Could not find user home. Use --user-home option or ensure HOME environment variable is set.')
1777 1703
1778 os.environ['JAVA_HOME'] = opts.java_home 1704 if opts.java_home:
1705 os.environ['JAVA_HOME'] = opts.java_home
1779 os.environ['HOME'] = opts.user_home 1706 os.environ['HOME'] = opts.user_home
1780 1707
1781 opts.ignored_projects = opts.ignored_projects + os.environ.get('IGNORED_PROJECTS', '').split(',') 1708 opts.ignored_projects = opts.ignored_projects + os.environ.get('IGNORED_PROJECTS', '').split(',')
1782 1709
1783 commandAndArgs = opts.__dict__.pop('commandAndArgs') 1710 commandAndArgs = opts.__dict__.pop('commandAndArgs')
1794 if doc is None: 1721 if doc is None:
1795 doc = '' 1722 doc = ''
1796 msg += ' {0:<20} {1}\n'.format(cmd, doc.split('\n', 1)[0]) 1723 msg += ' {0:<20} {1}\n'.format(cmd, doc.split('\n', 1)[0])
1797 return msg + '\n' 1724 return msg + '\n'
1798 1725
1799 def java(requiredCompliance=None): 1726 _canceled_java_requests = set()
1727
1728 def java(requiredCompliance=None, purpose=None, cancel=None):
1800 """ 1729 """
1801 Get a JavaConfig object containing Java commands launch details. 1730 Get a JavaConfig object containing Java commands launch details.
1802 If requiredCompliance is None, the compliance level specified by --java-home/JAVA_HOME 1731 If requiredCompliance is None, the compliance level specified by --java-home/JAVA_HOME
1803 is returned. Otherwise, the JavaConfig exactly matching requiredCompliance is returned 1732 is returned. Otherwise, the JavaConfig exactly matching requiredCompliance is returned
1804 or None if there is no exact match. 1733 or None if there is no exact match.
1805 """ 1734 """
1806 assert _java_homes 1735
1736 global _default_java_home
1737 if cancel and (requiredCompliance, purpose) in _canceled_java_requests:
1738 return None
1739
1807 if not requiredCompliance: 1740 if not requiredCompliance:
1808 return _java_homes[0] 1741 if not _default_java_home:
1809 for java in _java_homes: 1742 _default_java_home = _find_jdk(purpose=purpose, cancel=cancel)
1810 if java.javaCompliance == requiredCompliance: 1743 if not _default_java_home:
1744 assert cancel
1745 _canceled_java_requests.add((requiredCompliance, purpose))
1746 return _default_java_home
1747
1748 if _opts.strict_compliance:
1749 complianceCheck = requiredCompliance.exactMatch
1750 desc = str(requiredCompliance)
1751 else:
1752 compVersion = VersionSpec(str(requiredCompliance))
1753 complianceCheck = lambda version: version >= compVersion
1754 desc = '>=' + str(requiredCompliance)
1755
1756 for java in _extra_java_homes:
1757 if complianceCheck(java.version):
1811 return java 1758 return java
1759
1760 jdk = _find_jdk(versionCheck=complianceCheck, versionDescription=desc, purpose=purpose, cancel=cancel)
1761 if jdk:
1762 assert jdk not in _extra_java_homes
1763 _extra_java_homes.append(jdk)
1764 else:
1765 assert cancel
1766 _canceled_java_requests.add((requiredCompliance, purpose))
1767 return jdk
1768
1769 def java_version(versionCheck, versionDescription=None, purpose=None):
1770 if _default_java_home and versionCheck(_default_java_home.version):
1771 return _default_java_home
1772 for java in _extra_java_homes:
1773 if versionCheck(java.version):
1774 return java
1775 jdk = _find_jdk(versionCheck, versionDescription, purpose)
1776 assert jdk not in _extra_java_homes
1777 _extra_java_homes.append(jdk)
1778 return jdk
1779
1780 def _find_jdk(versionCheck=None, versionDescription=None, purpose=None, cancel=None):
1781 if not versionCheck:
1782 versionCheck = lambda v: True
1783 assert not versionDescription or versionCheck
1784 if not versionCheck and not purpose:
1785 isDefaultJdk = True
1786 else:
1787 isDefaultJdk = False
1788
1789 candidateJdks = []
1790 source = ''
1791 if _opts.java_home:
1792 candidateJdks.append(_opts.java_home)
1793 source = '--java-home'
1794 elif os.environ.get('JAVA_HOME'):
1795 candidateJdks.append(os.environ.get('JAVA_HOME'))
1796 source = 'JAVA_HOME'
1797
1798 result = _find_jdk_in_candidates(candidateJdks, versionCheck, warn=True, source=source)
1799 if result:
1800 return result
1801
1802 candidateJdks = []
1803
1804 if _opts.extra_java_homes:
1805 candidateJdks += _opts.extra_java_homes.split(os.pathsep)
1806 source = '--extra-java-homes'
1807 elif os.environ.get('EXTRA_JAVA_HOMES'):
1808 candidateJdks += os.environ.get('EXTRA_JAVA_HOMES').split(os.pathsep)
1809 source = 'EXTRA_JAVA_HOMES'
1810
1811 result = _find_jdk_in_candidates(candidateJdks, versionCheck, warn=True, source=source)
1812 if not result:
1813 candidateJdks = []
1814 source = ''
1815
1816 if get_os() == 'darwin':
1817 base = '/Library/Java/JavaVirtualMachines'
1818 if exists(base):
1819 candidateJdks = [join(base, n, 'Contents/Home') for n in os.listdir(base)]
1820 elif get_os() == 'linux':
1821 base = '/usr/lib/jvm'
1822 if exists(base):
1823 candidateJdks = [join(base, n) for n in os.listdir(base)]
1824 base = '/usr/java'
1825 if exists(base):
1826 candidateJdks += [join(base, n) for n in os.listdir(base)]
1827 elif get_os() == 'solaris':
1828 base = '/usr/jdk/instances'
1829 if exists(base):
1830 candidateJdks = [join(base, n) for n in os.listdir(base)]
1831 elif get_os() == 'windows':
1832 base = r'C:\Program Files\Java'
1833 if exists(base):
1834 candidateJdks = [join(base, n) for n in os.listdir(base)]
1835
1836 configs = _filtered_jdk_configs(candidateJdks, versionCheck)
1837 else:
1838 if not isDefaultJdk:
1839 log('find_jdk(versionCheck={0}, versionDescription={1}, purpose={2}, cancel={3})={4}'.format(versionCheck, versionDescription, purpose, cancel, result))
1840 return result
1841 configs = [result]
1842
1843 if len(configs) > 1:
1844 msg = 'Please select a '
1845 if isDefaultJdk:
1846 msg += 'default '
1847 msg += 'JDK'
1848 if purpose:
1849 msg += ' for' + purpose
1850 msg += ': '
1851 if versionDescription:
1852 msg = msg + '(' + versionDescription + ')'
1853 log(msg)
1854 choices = configs + ['<other>']
1855 if cancel:
1856 choices.append('Cancel (' + cancel + ')')
1857 selected = select_items(choices, allowMultiple=False)
1858 if isinstance(selected, types.StringTypes) and selected == '<other>':
1859 selected = None
1860 if isinstance(selected, types.StringTypes) and selected == 'Cancel (' + cancel + ')':
1861 return None
1862 elif len(configs) == 1:
1863 selected = configs[0]
1864 msg = 'Selected ' + str(selected) + ' as '
1865 if isDefaultJdk:
1866 msg += 'default'
1867 msg += 'JDK'
1868 if versionDescription:
1869 msg = msg + ' ' + versionDescription
1870 if purpose:
1871 msg += ' for' + purpose
1872 log(msg)
1873 else:
1874 msg = 'Could not find any JDK'
1875 if purpose:
1876 msg += ' for' + purpose
1877 msg += ' '
1878 if versionDescription:
1879 msg = msg + '(' + versionDescription + ')'
1880 log(msg)
1881 selected = None
1882
1883 while not selected:
1884 jdkLocation = raw_input('Enter path of JDK: ')
1885 selected = _find_jdk_in_candidates([jdkLocation], versionCheck, warn=True)
1886
1887 varName = 'JAVA_HOME' if isDefaultJdk else 'EXTRA_JAVA_HOMES'
1888 allowMultiple = not isDefaultJdk
1889 envPath = join(_primary_suite.mxDir, 'env')
1890 if ask_yes_no('Persist this setting by adding "{0}={1}" to {2}'.format(varName, selected.jdk, envPath), 'y'):
1891 envLines = []
1892 with open(envPath) as fp:
1893 append = True
1894 for line in fp:
1895 if line.rstrip().startswith(varName):
1896 _, currentValue = line.split('=', 1)
1897 currentValue = currentValue.strip()
1898 if not allowMultiple and currentValue:
1899 if not ask_yes_no('{0} is already set to {1}, overwrite with {2}?'.format(varName, currentValue, selected.jdk), 'n'):
1900 return selected
1901 else:
1902 line = varName + '=' + selected.jdk + os.linesep
1903 else:
1904 line = line.rstrip()
1905 if currentValue:
1906 line += os.pathsep
1907 line += selected.jdk + os.linesep
1908 append = False
1909 envLines.append(line)
1910 if append:
1911 envLines.append(varName + '=' + selected.jdk)
1912
1913 with open(envPath, 'w') as fp:
1914 for line in envLines:
1915 fp.write(line)
1916
1917 if varName == 'JAVA_HOME':
1918 os.environ['JAVA_HOME'] = selected.jdk
1919
1920 return selected
1921
1922 def _filtered_jdk_configs(candidates, versionCheck, warn=False, source=None):
1923 filtered = []
1924 for candidate in candidates:
1925 try:
1926 config = JavaConfig(candidate)
1927 if versionCheck(config.version):
1928 filtered.append(config)
1929 except JavaConfigException as e:
1930 if warn:
1931 log('Path in ' + source + "' is not pointing to a JDK (" + e.message + ")")
1932 return filtered
1933
1934 def _find_jdk_in_candidates(candidates, versionCheck, warn=False, source=None):
1935 filtered = _filtered_jdk_configs(candidates, versionCheck, warn, source)
1936 if filtered:
1937 return filtered[0]
1812 return None 1938 return None
1813 1939
1814 1940
1815 def run_java(args, nonZeroIsFatal=True, out=None, err=None, cwd=None, addDefaultArgs=True, javaConfig=None): 1941 def run_java(args, nonZeroIsFatal=True, out=None, err=None, cwd=None, addDefaultArgs=True, javaConfig=None):
1816 if not javaConfig: 1942 if not javaConfig:
2077 return cmp(self.value, other.value) 2203 return cmp(self.value, other.value)
2078 2204
2079 def __hash__(self): 2205 def __hash__(self):
2080 return self.value.__hash__() 2206 return self.value.__hash__()
2081 2207
2208 def exactMatch(self, version):
2209 assert isinstance(version, VersionSpec)
2210 return len(version.parts) > 1 and version.parts[0] == 1 and version.parts[1] == self.value
2211
2082 """ 2212 """
2083 A version specification as defined in JSR-56 2213 A version specification as defined in JSR-56
2084 """ 2214 """
2085 class VersionSpec: 2215 class VersionSpec:
2086 def __init__(self, versionString): 2216 def __init__(self, versionString):
2100 def _filter_non_existant_paths(paths): 2230 def _filter_non_existant_paths(paths):
2101 if paths: 2231 if paths:
2102 return os.pathsep.join([path for path in _separatedCygpathW2U(paths).split(os.pathsep) if exists(path)]) 2232 return os.pathsep.join([path for path in _separatedCygpathW2U(paths).split(os.pathsep) if exists(path)])
2103 return None 2233 return None
2104 2234
2235 class JavaConfigException(Exception):
2236 def __init__(self, value):
2237 Exception.__init__(self, value)
2238
2105 """ 2239 """
2106 A JavaConfig object encapsulates info on how Java commands are run. 2240 A JavaConfig object encapsulates info on how Java commands are run.
2107 """ 2241 """
2108 class JavaConfig: 2242 class JavaConfig:
2109 def __init__(self, java_home, java_dbg_port): 2243 def __init__(self, java_home):
2110 self.jdk = java_home 2244 self.jdk = java_home
2111 self.debug_port = java_dbg_port
2112 self.jar = exe_suffix(join(self.jdk, 'bin', 'jar')) 2245 self.jar = exe_suffix(join(self.jdk, 'bin', 'jar'))
2113 self.java = exe_suffix(join(self.jdk, 'bin', 'java')) 2246 self.java = exe_suffix(join(self.jdk, 'bin', 'java'))
2114 self.javac = exe_suffix(join(self.jdk, 'bin', 'javac')) 2247 self.javac = exe_suffix(join(self.jdk, 'bin', 'javac'))
2115 self.javap = exe_suffix(join(self.jdk, 'bin', 'javap')) 2248 self.javap = exe_suffix(join(self.jdk, 'bin', 'javap'))
2116 self.javadoc = exe_suffix(join(self.jdk, 'bin', 'javadoc')) 2249 self.javadoc = exe_suffix(join(self.jdk, 'bin', 'javadoc'))
2120 self._bootclasspath = None 2253 self._bootclasspath = None
2121 self._extdirs = None 2254 self._extdirs = None
2122 self._endorseddirs = None 2255 self._endorseddirs = None
2123 2256
2124 if not exists(self.java): 2257 if not exists(self.java):
2125 abort('Java launcher does not exist: ' + self.java) 2258 raise JavaConfigException('Java launcher does not exist: ' + self.java)
2126 2259
2127 def delAtAndSplit(s): 2260 def delAtAndSplit(s):
2128 return shlex.split(s.lstrip('@')) 2261 return shlex.split(s.lstrip('@'))
2129 2262
2130 self.java_args = delAtAndSplit(_opts.java_args) if _opts.java_args else [] 2263 self.java_args = delAtAndSplit(_opts.java_args) if _opts.java_args else []
2137 self.java_args = ['-d64'] + self.java_args 2270 self.java_args = ['-d64'] + self.java_args
2138 except subprocess.CalledProcessError as e: 2271 except subprocess.CalledProcessError as e:
2139 try: 2272 try:
2140 output = subprocess.check_output([self.java, '-version'], stderr=subprocess.STDOUT) 2273 output = subprocess.check_output([self.java, '-version'], stderr=subprocess.STDOUT)
2141 except subprocess.CalledProcessError as e: 2274 except subprocess.CalledProcessError as e:
2142 print e.output 2275 raise JavaConfigException(e.returncode + " :" + e.output)
2143 abort(e.returncode)
2144 2276
2145 def _checkOutput(out): 2277 def _checkOutput(out):
2146 return 'version' in out 2278 return 'version' in out
2147 2279
2148 # hotspot can print a warning, e.g. if there's a .hotspot_compiler file in the cwd 2280 # hotspot can print a warning, e.g. if there's a .hotspot_compiler file in the cwd
2154 version = o 2286 version = o
2155 2287
2156 self.version = VersionSpec(version.split()[2].strip('"')) 2288 self.version = VersionSpec(version.split()[2].strip('"'))
2157 self.javaCompliance = JavaCompliance(self.version.versionString) 2289 self.javaCompliance = JavaCompliance(self.version.versionString)
2158 2290
2159 if self.debug_port is not None: 2291 if _opts.java_dbg_port is not None:
2160 self.java_args += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(self.debug_port)] 2292 self.java_args += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(_opts.java_dbg_port)]
2161 2293
2162 def _init_classpaths(self): 2294 def _init_classpaths(self):
2163 if not self._classpaths_initialized: 2295 if not self._classpaths_initialized:
2164 myDir = dirname(__file__) 2296 myDir = dirname(__file__)
2165 outDir = join(dirname(__file__), '.jdk' + str(self.version)) 2297 outDir = join(dirname(__file__), '.jdk' + str(self.version))
2178 self._extdirs = _filter_non_existant_paths(self._extdirs) 2310 self._extdirs = _filter_non_existant_paths(self._extdirs)
2179 self._endorseddirs = _filter_non_existant_paths(self._endorseddirs) 2311 self._endorseddirs = _filter_non_existant_paths(self._endorseddirs)
2180 self._classpaths_initialized = True 2312 self._classpaths_initialized = True
2181 2313
2182 def __repr__(self): 2314 def __repr__(self):
2183 return "JavaConfig(" + str(self.jdk) + ", " + str(self.debug_port) + ")" 2315 return "JavaConfig(" + str(self.jdk) + ")"
2184 2316
2185 def __str__(self): 2317 def __str__(self):
2186 return "Java " + str(self.version) + " (" + str(self.javaCompliance) + ") from " + str(self.jdk) 2318 return "Java " + str(self.version) + " (" + str(self.javaCompliance) + ") from " + str(self.jdk)
2187 2319
2188 def __hash__(self): 2320 def __hash__(self):
2473 if not args.error_prone: 2605 if not args.error_prone:
2474 javac = args.alt_javac if args.alt_javac else mainJava.javac 2606 javac = args.alt_javac if args.alt_javac else mainJava.javac
2475 self.logCompilation('javac' if not args.alt_javac else args.alt_javac) 2607 self.logCompilation('javac' if not args.alt_javac else args.alt_javac)
2476 javacCmd = [javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir] 2608 javacCmd = [javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir]
2477 jdk.javacLibOptions(javacCmd) 2609 jdk.javacLibOptions(javacCmd)
2478 if jdk.debug_port is not None: 2610 if _opts.java_dbg_port is not None:
2479 javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(jdk.debug_port)] 2611 javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(_opts.java_dbg_port)]
2480 javacCmd += processorArgs 2612 javacCmd += processorArgs
2481 javacCmd += ['@' + _cygpathU2W(argfile.name)] 2613 javacCmd += ['@' + _cygpathU2W(argfile.name)]
2482 2614
2483 if not args.warnAPI: 2615 if not args.warnAPI:
2484 javacCmd.append('-XDignore.symbol.file') 2616 javacCmd.append('-XDignore.symbol.file')
2634 continue 2766 continue
2635 2767
2636 # skip building this Java project if its Java compliance level is "higher" than the configured JDK 2768 # skip building this Java project if its Java compliance level is "higher" than the configured JDK
2637 requiredCompliance = p.javaCompliance if p.javaCompliance else JavaCompliance(args.compliance) if args.compliance else None 2769 requiredCompliance = p.javaCompliance if p.javaCompliance else JavaCompliance(args.compliance) if args.compliance else None
2638 jdk = java(requiredCompliance) 2770 jdk = java(requiredCompliance)
2639 assert jdk
2640 2771
2641 outputDir = p.output_dir() 2772 outputDir = p.output_dir()
2642 2773
2643 sourceDirs = p.source_dirs() 2774 sourceDirs = p.source_dirs()
2644 buildReason = None 2775 buildReason = None
2938 3069
2939 class Batch: 3070 class Batch:
2940 def __init__(self, settingsDir, javaCompliance): 3071 def __init__(self, settingsDir, javaCompliance):
2941 self.path = join(settingsDir, 'org.eclipse.jdt.core.prefs') 3072 self.path = join(settingsDir, 'org.eclipse.jdt.core.prefs')
2942 self.javaCompliance = javaCompliance 3073 self.javaCompliance = javaCompliance
2943 self.javafiles = list()
2944 with open(join(settingsDir, 'org.eclipse.jdt.ui.prefs')) as fp: 3074 with open(join(settingsDir, 'org.eclipse.jdt.ui.prefs')) as fp:
2945 jdtUiPrefs = fp.read() 3075 jdtUiPrefs = fp.read()
2946 self.removeTrailingWhitespace = 'sp_cleanup.remove_trailing_whitespaces_all=true' in jdtUiPrefs 3076 self.removeTrailingWhitespace = 'sp_cleanup.remove_trailing_whitespaces_all=true' in jdtUiPrefs
2947 if self.removeTrailingWhitespace: 3077 if self.removeTrailingWhitespace:
2948 assert 'sp_cleanup.remove_trailing_whitespaces=true' in jdtUiPrefs and 'sp_cleanup.remove_trailing_whitespaces_ignore_empty=false' in jdtUiPrefs 3078 assert 'sp_cleanup.remove_trailing_whitespaces=true' in jdtUiPrefs and 'sp_cleanup.remove_trailing_whitespaces_ignore_empty=false' in jdtUiPrefs
2949 3079 self.cachedHash = None
2950 def settings(self): 3080
3081 def __hash__(self):
3082 if not self.cachedHash:
3083 with open(self.path) as fp:
3084 self.cachedHash = (fp.read(), self.javaCompliance, self.removeTrailingWhitespace).__hash__()
3085 return self.cachedHash
3086
3087 def __eq__(self, other):
3088 if not isinstance(other, Batch):
3089 return False
3090 if self.removeTrailingWhitespace != other.removeTrailingWhitespace:
3091 return False
3092 if self.javaCompliance != other.javaCompliance:
3093 return False
3094 if self.path == other.path:
3095 return True
2951 with open(self.path) as fp: 3096 with open(self.path) as fp:
2952 return fp.read() + java(self.javaCompliance).java + str(self.removeTrailingWhitespace) 3097 with open(other.path) as ofp:
3098 if fp.read() != ofp.read():
3099 return False
3100 return True
2953 3101
2954 class FileInfo: 3102 class FileInfo:
2955 def __init__(self, path): 3103 def __init__(self, path):
2956 self.path = path 3104 self.path = path
2957 with open(path) as fp: 3105 with open(path) as fp:
2990 3138
2991 if not exists(batch.path): 3139 if not exists(batch.path):
2992 if _opts.verbose: 3140 if _opts.verbose:
2993 log('[no Eclipse Code Formatter preferences at {0} - skipping]'.format(batch.path)) 3141 log('[no Eclipse Code Formatter preferences at {0} - skipping]'.format(batch.path))
2994 continue 3142 continue
2995 3143 javafiles = []
2996 for sourceDir in sourceDirs: 3144 for sourceDir in sourceDirs:
2997 for root, _, files in os.walk(sourceDir): 3145 for root, _, files in os.walk(sourceDir):
2998 for f in [join(root, name) for name in files if name.endswith('.java')]: 3146 for f in [join(root, name) for name in files if name.endswith('.java')]:
2999 batch.javafiles.append(FileInfo(f)) 3147 javafiles.append(FileInfo(f))
3000 if len(batch.javafiles) == 0: 3148 if len(javafiles) == 0:
3001 logv('[no Java sources in {0} - skipping]'.format(p.name)) 3149 logv('[no Java sources in {0} - skipping]'.format(p.name))
3002 continue 3150 continue
3003 3151
3004 res = batches.setdefault(batch.settings(), batch) 3152 res = batches.setdefault(batch, javafiles)
3005 if res is not batch: 3153 if res is not javafiles:
3006 res.javafiles = res.javafiles + batch.javafiles 3154 res.extend(javafiles)
3007 3155
3008 log("we have: " + str(len(batches)) + " batches") 3156 log("we have: " + str(len(batches)) + " batches")
3009 for batch in batches.itervalues(): 3157 for batch, javafiles in batches.iteritems():
3010 for chunk in _chunk_files_for_command_line(batch.javafiles, pathFunction=lambda f: f.path): 3158 for chunk in _chunk_files_for_command_line(javafiles, pathFunction=lambda f: f.path):
3011 run([args.eclipse_exe, 3159 run([args.eclipse_exe,
3012 '-nosplash', 3160 '-nosplash',
3013 '-application', 3161 '-application',
3014 'org.eclipse.jdt.core.JavaCodeFormatter', 3162 'org.eclipse.jdt.core.JavaCodeFormatter',
3015 '-vm', java(batch.javaCompliance).java, 3163 '-vm', java(batch.javaCompliance).java,
4863 projectJava = java(p.javaCompliance) 5011 projectJava = java(p.javaCompliance)
4864 5012
4865 # Once https://bugs.openjdk.java.net/browse/JDK-8041628 is fixed, 5013 # Once https://bugs.openjdk.java.net/browse/JDK-8041628 is fixed,
4866 # this should be reverted to: 5014 # this should be reverted to:
4867 # javadocExe = java().javadoc 5015 # javadocExe = java().javadoc
5016 # we can then also respect _opts.relatex_compliance
4868 javadocExe = projectJava.javadoc 5017 javadocExe = projectJava.javadoc
4869 5018
4870 run([javadocExe, memory, 5019 run([javadocExe, memory,
4871 '-XDignore.symbol.file', 5020 '-XDignore.symbol.file',
4872 '-classpath', cp, 5021 '-classpath', cp,
5083 5232
5084 """ 5233 """
5085 if len(items) <= 1: 5234 if len(items) <= 1:
5086 return items 5235 return items
5087 else: 5236 else:
5237 numlen = str(len(str(len(items))))
5088 if allowMultiple: 5238 if allowMultiple:
5089 log('[0] <all>') 5239 log(('[{0:>' + numlen + '}] <all>').format(0))
5090 for i in range(0, len(items)): 5240 for i in range(0, len(items)):
5091 if descriptions is None: 5241 if descriptions is None:
5092 log('[{0}] {1}'.format(i + 1, items[i])) 5242 log(('[{0:>' + numlen + '}] {1}').format(i + 1, items[i]))
5093 else: 5243 else:
5094 assert len(items) == len(descriptions) 5244 assert len(items) == len(descriptions)
5095 wrapper = textwrap.TextWrapper(subsequent_indent=' ') 5245 wrapper = textwrap.TextWrapper(subsequent_indent=' ')
5096 log('\n'.join(wrapper.wrap('[{0}] {1} - {2}'.format(i + 1, items[i], descriptions[i])))) 5246 log('\n'.join(wrapper.wrap(('[{0:>' + numlen + '}] {1} - {2}').format(i + 1, items[i], descriptions[i]))))
5097 while True: 5247 while True:
5098 if allowMultiple: 5248 if allowMultiple:
5099 s = raw_input('Enter number(s) of selection (separate multiple choices with spaces): ').split() 5249 s = raw_input('Enter number(s) of selection (separate multiple choices with spaces): ').split()
5100 else: 5250 else:
5101 s = [raw_input('Enter number of selection: ')] 5251 s = [raw_input('Enter number of selection: ')]
5393 abort('no primary suite found') 5543 abort('no primary suite found')
5394 5544
5395 opts, commandAndArgs = _argParser._parse_cmd_line() 5545 opts, commandAndArgs = _argParser._parse_cmd_line()
5396 assert _opts == opts 5546 assert _opts == opts
5397 5547
5398 global _java_homes
5399 defaultJdk = JavaConfig(opts.java_home, opts.java_dbg_port)
5400 _java_homes = [defaultJdk]
5401 if opts.extra_java_homes:
5402 for java_home in opts.extra_java_homes.split(os.pathsep):
5403 extraJdk = JavaConfig(java_home, opts.java_dbg_port)
5404 if extraJdk.javaCompliance > defaultJdk.javaCompliance:
5405 abort('Secondary JDK ' + extraJdk.jdk + ' has higher compliance level than default JDK ' + defaultJdk.jdk)
5406 _java_homes.append(extraJdk)
5407
5408 for s in suites(): 5548 for s in suites():
5409 s._post_init(opts) 5549 s._post_init(opts)
5410 5550
5411 if len(commandAndArgs) == 0: 5551 if len(commandAndArgs) == 0:
5412 _argParser.print_help() 5552 _argParser.print_help()