Add compile toolchains using system's JDK (but not register).
This was not foreseen by design document, but RBE and appengine want to use system JDK for compilation as well. Before hostjdk8 toolchain was used to achieve this. Just rewriting the toolchain into something that uses local_jdk version 8 does not achieve this objective.
So when a system JDK is imported, its version is detected and this also give us a chance to provide compilation toolchains for it. We keep them unregistered though, so that the user can decide what to do.
Use case of using local JDK for compilation is achieved using flags:
```
--extra_toolchains=@local_jdk//:all # add local JDK toolchains
--java_language_version=8 # Select to compile to Java language 8 (and will use local JDK for compilation)
```
Closes #12713.
PiperOrigin-RevId: 348016908
diff --git a/tools/jdk/local_java_repository.bzl b/tools/jdk/local_java_repository.bzl
index b354d9a..51aa1d3 100644
--- a/tools/jdk/local_java_repository.bzl
+++ b/tools/jdk/local_java_repository.bzl
@@ -14,6 +14,8 @@
"""Rules for importing and registering a local JDK."""
+load(":default_java_toolchain.bzl", "JVM8_TOOLCHAIN_CONFIGURATION", "default_java_toolchain")
+
def _detect_java_version(repository_ctx, java_bin):
properties_out = repository_ctx.execute([java_bin, "-XshowSettings:properties"]).stderr
# This returns an indented list of properties separated with newlines:
@@ -33,7 +35,78 @@
return minor
return major
+def local_java_runtime(name, java_home, version, runtime_name = None):
+ """Defines a java_runtime target together with Java runtime and compile toolchain definitions.
+
+ Java runtime toolchain is constrained by flag --java_runtime_version having
+ value set to either name or version argument.
+
+ Java compile toolchains are created for --java_language_version flags values
+ between 8 and version (inclusive). Java compile toolchains use the same
+ (local) JDK for compilation. This requires a different configuration for JDK8
+ than the newer versions.
+
+ Args:
+ name: name of the target.
+ java_home: Path to the JDK.
+ version: Version of the JDK.
+ runtime_name: name of java_runtime target if it already exists.
+ """
+ if runtime_name == None:
+ runtime_name = name
+ native.java_runtime(
+ name = runtime_name,
+ java_home = java_home,
+ )
+
+ native.config_setting(
+ name = name + "_name_setting",
+ values = {"java_runtime_version": name},
+ visibility = ["//visibility:private"],
+ )
+ native.config_setting(
+ name = name + "_version_setting",
+ values = {"java_runtime_version": version},
+ visibility = ["//visibility:private"],
+ )
+ native.alias(
+ name = name + "_version_or_name_setting",
+ actual = select({
+ name + "_version_setting": name + "_version_setting",
+ "//conditions:default": name + "_name_setting",
+ }),
+ visibility = ["//visibility:private"],
+ )
+ native.toolchain(
+ name = "runtime_toolchain_definition",
+ target_settings = [":%s_version_or_name_setting" % name],
+ toolchain_type = "@bazel_tools//tools/jdk:runtime_toolchain_type",
+ toolchain = runtime_name,
+ )
+
+ if version == "8":
+ default_java_toolchain(
+ name = name + "_toolchain_java8",
+ configuration = JVM8_TOOLCHAIN_CONFIGURATION,
+ source_version = version,
+ target_version = version,
+ java_runtime = runtime_name,
+ )
+ else:
+ for version in range(8, int(version) + 1):
+ default_java_toolchain(
+ name = name + "_toolchain_java" + str(version),
+ source_version = str(version),
+ target_version = str(version),
+ java_runtime = runtime_name,
+ )
+
def _local_java_repository_impl(repository_ctx):
+ """Repository rule local_java_repository implementation.
+
+ Args:
+ repository_ctx: repository context
+ """
java_home = repository_ctx.attr.java_home
java_home_path = repository_ctx.path(java_home)
if not java_home_path.exists:
@@ -48,86 +121,70 @@
extension = ".exe" if repository_ctx.os.name.lower().find("windows") != -1 else ""
java_bin = java_home_path.get_child("bin").get_child("java" + extension)
- if java_bin.exists:
- version = repository_ctx.attr.version if repository_ctx.attr.version != "" else _detect_java_version(repository_ctx, java_bin)
- if repository_ctx.attr.build_file != None:
- build_file = repository_ctx.read(repository_ctx.path(repository_ctx.attr.build_file))
- else:
- build_file = """
-java_runtime(
- name = "jdk",
- java_home = "{java_home}"
-) """.format(java_home = java_home)
-
+ if not java_bin.exists:
+ # Java binary does not exist
repository_ctx.file(
"BUILD.bazel",
- build_file +
- """
-config_setting(
- name = "name_setting",
- values = {{"java_runtime_version": "{local_jdk}"}},
- visibility = ["//visibility:private"],
-)
-config_setting(
- name = "version_setting",
- values = {{"java_runtime_version": "{version}"}},
- visibility = ["//visibility:private"],
-)
-alias(
- name = "version_or_name_setting",
- actual = select({{
- ":version_setting": ":version_setting",
- "//conditions:default": ":name_setting",
- }}),
- visibility = ["//visibility:private"],
-)
-toolchain(
- name = "toolchain",
- target_settings = [":version_or_name_setting"],
- toolchain_type = "@bazel_tools//tools/jdk:runtime_toolchain_type",
- toolchain = ":jdk",
-)
-""".format(local_jdk = repository_ctx.name, version = version),
+ _NOJDK_BUILD_TPL.format(
+ local_jdk = repository_ctx.name,
+ java_binary = "bin/java" + extension,
+ java_home = java_home,
+ ),
False,
)
-
- # Symlink all files
- for file in repository_ctx.path(java_home).readdir():
- repository_ctx.symlink(file, file.basename)
-
return
- # Java binary does not exist
+ # Detect version
+ version = repository_ctx.attr.version if repository_ctx.attr.version != "" else _detect_java_version(repository_ctx, java_bin)
+
+ # Prepare BUILD file using "local_java_runtime" macro
+ build_file = ""
+ if repository_ctx.attr.build_file != None:
+ build_file = repository_ctx.read(repository_ctx.path(repository_ctx.attr.build_file))
+
+ runtime_name = '"jdk"' if repository_ctx.attr.build_file else None
+ local_java_runtime_macro = """
+local_java_runtime(
+ name = "%s",
+ runtime_name = %s,
+ java_home = "%s",
+ version = "%s",
+)
+""" % (repository_ctx.name, runtime_name, java_home, version)
+
repository_ctx.file(
"BUILD.bazel",
- '''load("@bazel_tools//tools/jdk:fail_rule.bzl", "fail_rule")
+ 'load("@bazel_tools//tools/jdk:local_java_repository.bzl", "local_java_runtime")\n' +
+ build_file +
+ local_java_runtime_macro,
+ )
+ # Symlink all files
+ for file in repository_ctx.path(java_home).readdir():
+ repository_ctx.symlink(file, file.basename)
+
+# Build file template, when JDK does not exist
+_NOJDK_BUILD_TPL = '''load("@bazel_tools//tools/jdk:fail_rule.bzl", "fail_rule")
fail_rule(
- name = "jdk",
- header = "Auto-Configuration Error:",
- message = ("Cannot find Java binary {java_binary} in {java_home}; either correct your JAVA_HOME, " +
- "PATH or specify Java from remote repository (e.g. " +
- "--java_runtime_version=remotejdk_11")
+ name = "jdk",
+ header = "Auto-Configuration Error:",
+ message = ("Cannot find Java binary {java_binary} in {java_home}; either correct your JAVA_HOME, " +
+ "PATH or specify Java from remote repository (e.g. " +
+ "--java_runtime_version=remotejdk_11")
)
config_setting(
- name = "localjdk_setting",
- values = {{"java_runtime_version": "{local_jdk}"}},
- visibility = ["//visibility:private"],
+ name = "localjdk_setting",
+ values = {{"java_runtime_version": "{local_jdk}"}},
+ visibility = ["//visibility:private"],
)
toolchain(
- name = "toolchain",
- target_settings = [":localjdk_setting"],
- toolchain_type = "@bazel_tools//tools/jdk:runtime_toolchain_type",
- toolchain = ":jdk",
+ name = "runtime_toolchain_definition",
+ target_settings = [":localjdk_setting"],
+ toolchain_type = "@bazel_tools//tools/jdk:runtime_toolchain_type",
+ toolchain = ":jdk",
)
-'''.format(
- local_jdk = repository_ctx.name,
- java_binary = "bin/java" + extension,
- java_home = java_home,
- ),
- False,
- )
+'''
_local_java_repository_rule = repository_rule(
implementation = _local_java_repository_impl,
@@ -141,10 +198,16 @@
)
def local_java_repository(name, java_home, version = "", build_file = None):
- """Imports and registers a local JDK.
+ """Registers a runtime toolchain for local JDK and creates an unregistered compile toolchain.
Toolchain resolution is constrained with --java_runtime_version flag
- having value of the "name" parameter.
+ having value of the "name" or "version" parameter.
+
+ Java compile toolchains are created for --java_language_version flags values
+ between 8 and version (inclusive). Java compile toolchains use the same
+ (local) JDK for compilation.
+
+ If there is no JDK "virtual" targets are created, which fail only when actually needed.
Args:
name: A unique name for this rule.
@@ -153,4 +216,4 @@
version: optionally java version
"""
_local_java_repository_rule(name = name, java_home = java_home, version = version, build_file = build_file)
- native.register_toolchains("@" + name + "//:toolchain")
+ native.register_toolchains("@" + name + "//:runtime_toolchain_definition")