Implement local_java_repository for local version of Java
Implement local_java_repository for local version of Java.
Repository is a way to verify Java is really present and emit a nice message otherwise.
Resolves #6993
Closes #12078.
PiperOrigin-RevId: 331980488
diff --git a/tools/jdk/BUILD b/tools/jdk/BUILD
index 116b8eb..0b8e37e 100644
--- a/tools/jdk/BUILD
+++ b/tools/jdk/BUILD
@@ -433,7 +433,10 @@
"BUILD-jdk", # Tools are build from the workspace for tests.
"DumpPlatformClassPath.java",
"default_java_toolchain.bzl",
+ "fail_rule.bzl",
"java_toolchain_alias.bzl",
+ "jdk.BUILD",
+ "local_java_repository.bzl",
"nosystemjdk/README",
"proguard_whitelister.py",
"proguard_whitelister_test.py",
diff --git a/tools/jdk/fail_rule.bzl b/tools/jdk/fail_rule.bzl
new file mode 100644
index 0000000..a8a3da2
--- /dev/null
+++ b/tools/jdk/fail_rule.bzl
@@ -0,0 +1,35 @@
+# Copyright 2020 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""A rule than fails during analysis."""
+
+def _fail_rule_impl(ctx):
+ if ctx.attr.header:
+ fail("%s %s" % (ctx.attr.header, ctx.attr.message))
+ else:
+ fail(ctx.attr.message)
+
+fail_rule = rule(
+ doc = "A rule that fails during analysis.",
+ implementation = _fail_rule_impl,
+ attrs = {
+ "header": attr.string(
+ doc = "Header of the message.",
+ ),
+ "message": attr.string(
+ mandatory = True,
+ doc = "Message to display.",
+ ),
+ },
+)
diff --git a/tools/jdk/jdk.BUILD b/tools/jdk/jdk.BUILD
new file mode 100644
index 0000000..0cd0b36
--- /dev/null
+++ b/tools/jdk/jdk.BUILD
@@ -0,0 +1,227 @@
+package(default_visibility = ["//visibility:public"])
+
+load("@rules_java//java:defs.bzl", "java_runtime", "java_import")
+
+exports_files(["BUILD.bazel"])
+
+DEPRECATION_MESSAGE = ("Don't depend on targets in the JDK workspace;" +
+ " use @bazel_tools//tools/jdk:current_java_runtime instead" +
+ " (see https://github.com/bazelbuild/bazel/issues/5594)")
+
+filegroup(
+ name = "jni_header",
+ srcs = ["include/jni.h"],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "jni_md_header-darwin",
+ srcs = ["include/darwin/jni_md.h"],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "jni_md_header-linux",
+ srcs = ["include/linux/jni_md.h"],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "jni_md_header-freebsd",
+ srcs = ["include/freebsd/jni_md.h"],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "jni_md_header-openbsd",
+ srcs = ["include/openbsd/jni_md.h"],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "jni_md_header-windows",
+ srcs = ["include/win32/jni_md.h"],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "java",
+ srcs = select({
+ ":windows": ["bin/java.exe"],
+ "//conditions:default": ["bin/java"],
+ }),
+ data = [":jdk"],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "jar",
+ srcs = select({
+ ":windows": ["bin/jar.exe"],
+ "//conditions:default": ["bin/jar"],
+ }),
+ data = [":jdk"],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "javac",
+ srcs = select({
+ ":windows": ["bin/javac.exe"],
+ "//conditions:default": ["bin/javac"],
+ }),
+ data = [":jdk"],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "javadoc",
+ srcs = select({
+ ":windows": ["bin/javadoc.exe"],
+ "//conditions:default": ["bin/javadoc"],
+ }),
+ data = [":jdk"],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "xjc",
+ srcs = ["bin/xjc"],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "wsimport",
+ srcs = ["bin/wsimport"],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+BOOTCLASS_JARS = [
+ "rt.jar",
+ "resources.jar",
+ "jsse.jar",
+ "jce.jar",
+ "charsets.jar",
+]
+
+# TODO(cushon): this isn't compatible with JDK 9
+filegroup(
+ name = "bootclasspath",
+ srcs = ["jre/lib/%s" % jar for jar in BOOTCLASS_JARS],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+# TODO(cushon): migrate to extclasspath and delete
+filegroup(
+ name = "extdir",
+ srcs = glob(
+ ["jre/lib/ext/*.jar"],
+ allow_empty = True,
+ ),
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "extclasspath",
+ srcs = glob(
+ ["jre/lib/ext/*.jar"],
+ allow_empty = True,
+ ),
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "jre-bin",
+ srcs = select({
+ # In some configurations, Java browser plugin is considered harmful and
+ # common antivirus software blocks access to npjp2.dll interfering with Bazel,
+ # so do not include it in JRE on Windows.
+ ":windows": glob(
+ ["jre/bin/**"],
+ allow_empty = True,
+ exclude = ["jre/bin/plugin2/**"],
+ ),
+ "//conditions:default": glob(
+ ["jre/bin/**"],
+ allow_empty = True,
+ ),
+ }),
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "jre-lib",
+ srcs = glob(
+ ["jre/lib/**"],
+ allow_empty = True,
+ ),
+)
+
+filegroup(
+ name = "jre",
+ srcs = [":jre-default"],
+)
+
+filegroup(
+ name = "jre-default",
+ srcs = [
+ ":jre-bin",
+ ":jre-lib",
+ ],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+ name = "jdk-bin",
+ srcs = glob(
+ ["bin/**"],
+ # The JDK on Windows sometimes contains a directory called
+ # "%systemroot%", which is not a valid label.
+ exclude = ["**/*%*/**"],
+ ),
+)
+
+filegroup(
+ name = "jdk-include",
+ srcs = glob(["include/**"]),
+)
+
+filegroup(
+ name = "jdk-lib",
+ srcs = glob(
+ ["lib/**"],
+ exclude = [
+ "lib/missioncontrol/**",
+ "lib/visualvm/**",
+ ],
+ ),
+)
+
+java_runtime(
+ name = "jdk",
+ srcs = [
+ ":jdk-bin",
+ ":jdk-include",
+ ":jdk-lib",
+ ":jre-default",
+ ],
+)
+
+filegroup(
+ name = "langtools",
+ srcs = ["lib/tools.jar"],
+ deprecation = DEPRECATION_MESSAGE,
+)
+
+java_import(
+ name = "langtools-neverlink",
+ deprecation = DEPRECATION_MESSAGE,
+ jars = ["lib/tools.jar"],
+ neverlink = 1,
+)
+
+config_setting(
+ name = "windows",
+ values = {"cpu": "x64_windows"},
+ visibility = ["//visibility:private"],
+)
diff --git a/tools/jdk/local_java_repository.bzl b/tools/jdk/local_java_repository.bzl
new file mode 100644
index 0000000..0a68136
--- /dev/null
+++ b/tools/jdk/local_java_repository.bzl
@@ -0,0 +1,74 @@
+# Copyright 2020 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Java repository implementation.
+
+Creates a local repository using jdk.BUILD file.
+
+When Java executable is not present it creates a BUILD file with target "jdk"
+displaying an error message.
+"""
+
+def _local_java_repository_impl(repository_ctx):
+ java_home = repository_ctx.attr.java_home
+ java_home_path = repository_ctx.path(java_home)
+ if not java_home_path.exists:
+ fail('The path indicated by the "java_home" attribute "%s" (absolute: "%s") ' +
+ "does not exist." % (java_home, str(java_home_path)))
+
+ repository_ctx.file(
+ "WORKSPACE",
+ "# DO NOT EDIT: automatically generated WORKSPACE file for local_java_repository\n" +
+ "workspace(name = \"{name}\")\n".format(name = repository_ctx.name),
+ )
+
+ extension = ".exe" if repository_ctx.os.name.lower().find("windows") != -1 else ""
+ if java_home_path.get_child("bin").get_child("java" + extension).exists:
+ repository_ctx.file(
+ "BUILD.bazel",
+ repository_ctx.read(repository_ctx.path(repository_ctx.attr._build_file)),
+ 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
+ # TODO(ilist): replace error message after toolchain implementation
+ repository_ctx.file(
+ "BUILD.bazel",
+ '''load("@bazel_tools//tools/jdk:fail_rule.bzl", "fail_rule")
+
+fail_rule(
+ name = "jdk",
+ header = "Auto-Configuration Error:",
+ message = ("Cannot find Java binary %s in %s; either correct your JAVA_HOME, " +
+ "PATH or specify embedded Java (e.g. " +
+ "--javabase=@bazel_tools//tools/jdk:remote_jdk11)")
+)''' % ("bin/java" + extension, java_home),
+ False,
+ )
+
+local_java_repository = repository_rule(
+ implementation = _local_java_repository_impl,
+ local = True,
+ configure = True,
+ attrs = {
+ "java_home": attr.string(),
+ "_build_file": attr.label(default = "@bazel_tools//tools/jdk:jdk.BUILD"),
+ },
+)