summaryrefslogtreecommitdiffstats
path: root/SCons/Tool/JavaCommon.py
diff options
context:
space:
mode:
authorMats Wichmann <mats@linux.com>2021-11-04 20:03:50 (GMT)
committerMats Wichmann <mats@linux.com>2021-11-04 22:30:05 (GMT)
commit027c15f002610eae38212fe282963553a86a66ef (patch)
treeecfd9c0e3510e90a36c6b9e243097a3ec0996b9d /SCons/Tool/JavaCommon.py
parent1a04e66fdbe9dd5b088c337fa04f66f403dde2ad (diff)
downloadSCons-027c15f002610eae38212fe282963553a86a66ef.zip
SCons-027c15f002610eae38212fe282963553a86a66ef.tar.gz
SCons-027c15f002610eae38212fe282963553a86a66ef.tar.bz2
Update Java support for more versions
* on Windows, detect more possible JDK locations. * On all platforms, more Java versions (up to 17.0 now). * Add some docu on version selection and on JavaH tool in light of javah command dropped since 10.0. * Try to be better about preserving user's passed-in JAVA* consvars. Signed-off-by: Mats Wichmann <mats@linux.com>
Diffstat (limited to 'SCons/Tool/JavaCommon.py')
-rw-r--r--SCons/Tool/JavaCommon.py158
1 files changed, 113 insertions, 45 deletions
diff --git a/SCons/Tool/JavaCommon.py b/SCons/Tool/JavaCommon.py
index d869b38..dac7d50 100644
--- a/SCons/Tool/JavaCommon.py
+++ b/SCons/Tool/JavaCommon.py
@@ -1,11 +1,6 @@
-"""SCons.Tool.JavaCommon
-
-Stuff for processing Java.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -25,16 +20,16 @@ Stuff for processing Java.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Common routines for processing Java. """
import os
-import os.path
import re
import glob
+from pathlib import Path
+from typing import List
-java_parsing = 1
+java_parsing = True
default_java_version = '1.4'
@@ -43,13 +38,18 @@ default_java_version = '1.4'
scopeStateVersions = ('1.8',)
# Glob patterns for use in finding where the JDK is.
-# These are pairs, *dir_glob used in the general case,
-# *version_dir_glob if matching only a specific version.
-# For now only used for Windows.
-java_win32_dir_glob = 'C:/Program Files*/Java/jdk*/bin'
+#
+# These are pairs, (*dir_glob, *version_dir_glob) depending on whether
+# a JDK version was requested or not.
+# For now only used for Windows, which doesn't install JDK in a
+# path that would be in env['ENV']['PATH']. The specific tool will
+# add the discovered path to this. Since Oracle changed the rules,
+# there are many possible vendors, we can't guess them all, but take a shot.
+java_win32_dir_glob = 'C:/Program Files*/*/*jdk*/bin'
+
# On windows, since Java 9, there is a dash between 'jdk' and the version
# string that wasn't there before. this glob should catch either way.
-java_win32_version_dir_glob = 'C:/Program Files*/Java/jdk*%s*/bin'
+java_win32_version_dir_glob = 'C:/Program Files*/*/*jdk*%s*/bin'
# Glob patterns for use in finding where the JDK headers are.
# These are pairs, *dir_glob used in the general case,
@@ -98,9 +98,27 @@ if java_parsing:
interfaces, and anonymous inner classes."""
def __init__(self, version=default_java_version):
-
- if version not in ('1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7',
- '1.8', '5', '6', '9.0', '10.0', '11.0', '12.0'):
+ if version not in (
+ '1.1',
+ '1.2',
+ '1.3',
+ '1.4',
+ '1.5',
+ '1.6',
+ '1.7',
+ '1.8',
+ '5',
+ '6',
+ '9.0',
+ '10.0',
+ '11.0',
+ '12.0',
+ '13.0',
+ '14.0',
+ '15.0',
+ '16.0',
+ '17.0',
+ ):
msg = "Java version %s not supported" % version
raise NotImplementedError(msg)
@@ -207,7 +225,24 @@ if java_parsing:
if self.version in ('1.1', '1.2', '1.3', '1.4'):
clazz = self.listClasses[0]
self.listOutputs.append('%s$%d' % (clazz, self.nextAnon))
- elif self.version in ('1.5', '1.6', '1.7', '1.8', '5', '6', '9.0', '10.0', '11.0', '12.0'):
+ # TODO: shouldn't need to repeat versions here and in OuterState
+ elif self.version in (
+ '1.5',
+ '1.6',
+ '1.7',
+ '1.8',
+ '5',
+ '6',
+ '9.0',
+ '10.0',
+ '11.0',
+ '12.0',
+ '13.0',
+ '14.0',
+ '15.0',
+ '16.0',
+ '17.0',
+ ):
self.stackAnonClassBrackets.append(self.brackets)
className = []
className.extend(self.listClasses)
@@ -443,49 +478,82 @@ else:
return os.path.split(fn)
-def get_java_install_dirs(platform, version=None):
- """
- Find the java jdk installation directories.
+def get_java_install_dirs(platform, version=None) -> List[str]:
+ """ Find possible java jdk installation directories.
+
+ Returns a list for use as `default_paths` when looking up actual
+ java binaries with :meth:`SCons.Tool.find_program_path`.
+ The paths are sorted by version, latest first.
- This list is intended to supply as "default paths" for use when looking
- up actual java binaries.
+ Args:
+ platform: selector for search algorithm.
+ version: if not None, restrict the search to this version.
- :param platform: selector for search algorithm.
- :param version: If specified, only look for java sdk's of this version
- :return: list of default paths for java.
+ Returns:
+ list of default paths for jdk.
"""
- paths = []
if platform == 'win32':
+ paths = []
if version:
paths = glob.glob(java_win32_version_dir_glob % version)
else:
paths = glob.glob(java_win32_dir_glob)
- else:
- # other platforms, do nothing for now
- pass
- return sorted(paths)
+ def win32getvnum(java):
+ """ Generates a sort key for win32 jdk versions.
+ We'll have gotten a path like ...something/*jdk*/bin because
+ that is the pattern we glob for. To generate the sort key,
+ extracts the next-to-last component, then trims it further if
+ it had a complex name, like 'java-1.8.0-openjdk-1.8.0.312-1',
+ to try and put it on a common footing with the more common style,
+ which looks like 'jdk-11.0.2'.
+
+ This is certainly fragile, and if someone has a 9.0 it won't
+ sort right since this will still be alphabetic, BUT 9.0 was
+ not an LTS release and is 30 mos out of support as this note
+ is written so just assume it will be okay.
+ """
+ d = Path(java).parts[-2]
+ if not d.startswith('jdk'):
+ d = 'jdk' + d.rsplit('jdk', 1)[-1]
+ return d
+
+ return sorted(paths, key=win32getvnum, reverse=True)
+
+ # other platforms, do nothing for now: we expect the standard
+ # paths to be enough to find a jdk (e.g. use alternatives system)
+ return []
-def get_java_include_paths(env, javac, version):
- """
- Find java include paths for JNI building.
- :param env: construction environment, used to extract platform.
- :param javac: path to detected javac.
- :return: list of paths.
+def get_java_include_paths(env, javac, version) -> List[str]:
+ """Find java include paths for JNI building.
+
+ Cannot be called in isolation - `javac` refers to an already detected
+ compiler. Normally would would call :func:`get_java_install_dirs` first
+ and then do lookups on the paths it returns before calling us.
+
+ Args:
+ env: construction environment, used to extract platform.
+ javac: path to detected javac.
+ version: if not None, restrict the search to this version.
+
+ Returns:
+ list of include directory paths.
"""
- paths = []
if not javac:
- # there are no paths if we've not detected javac.
- pass
- elif env['PLATFORM'] == 'win32':
- # on Windows, we have the right path to javac, so look locally
+ return []
+
+ # on Windows, we have a path to the actual javac, so look locally
+ if env['PLATFORM'] == 'win32':
javac_bin_dir = os.path.dirname(javac)
java_inc_dir = os.path.normpath(os.path.join(javac_bin_dir, '..', 'include'))
paths = [java_inc_dir, os.path.join(java_inc_dir, 'win32')]
+
+ # for the others, we probably found something which isn't in the JDK dir,
+ # so use the predefined patterns to glob for an include directory.
elif env['PLATFORM'] == 'darwin':
if not version:
paths = [java_macos_include_dir_glob]
@@ -500,10 +568,10 @@ def get_java_include_paths(env, javac, version):
for p in java_linux_version_include_dirs_glob:
base_paths.extend(glob.glob(p % version))
+ paths = []
for p in base_paths:
paths.extend([p, os.path.join(p, 'linux')])
- # print("PATHS:%s"%paths)
return paths
# Local Variables: