aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/jdk
diff options
context:
space:
mode:
authorGravatar cushon <cushon@google.com>2017-12-20 16:19:56 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2017-12-20 16:21:55 -0800
commit29a96822a3bc5a81094285a995d905a074ef5714 (patch)
tree50cee37e705218b1e0ee3f86826e4530081c54e2 /tools/jdk
parentdb319f8eca064475d5092a756c75f2c3f6526b7e (diff)
Update bootclasspath handling for JDK 9
rt.jar etc. no longer exist, retrieve the default bootclasspath contents using a Java program instead. PiperOrigin-RevId: 179747945
Diffstat (limited to 'tools/jdk')
-rw-r--r--tools/jdk/BUILD26
-rw-r--r--tools/jdk/DumpPlatformClassPath.java143
-rw-r--r--tools/jdk/default_java_toolchain.bzl8
3 files changed, 175 insertions, 2 deletions
diff --git a/tools/jdk/BUILD b/tools/jdk/BUILD
index 7ebec85b58..26a236f598 100644
--- a/tools/jdk/BUILD
+++ b/tools/jdk/BUILD
@@ -138,6 +138,7 @@ BOOTCLASS_JARS = [
"charsets.jar",
]
+# TODO(cushon): this isn't compatible with JDK 9
alias(
name = "bootclasspath",
actual = "@local_jdk//:bootclasspath",
@@ -180,6 +181,30 @@ alias(
actual = "@local_jdk//:jdk",
)
+genrule(
+ name = "gen_platformclasspath",
+ srcs = ["DumpPlatformClassPath.java"],
+ outs = ["platformclasspath-impl.jar"],
+ cmd = """
+set -eu
+TMPDIR=$$(mktemp -d)
+$(JAVABASE)/bin/javac $< -d $$TMPDIR
+$(JAVA) -cp $$TMPDIR DumpPlatformClassPath 8 $@
+rm -rf $$TMPDIR
+""",
+ toolchains = ["@bazel_tools//tools/jdk:current_host_java_runtime"],
+ tools = ["@bazel_tools//tools/jdk:current_host_java_runtime"],
+)
+
+# run ijar separately so we can skip it for bootstrapping
+genrule(
+ name = "platformclasspath",
+ srcs = ["platformclasspath-impl.jar"],
+ outs = ["platformclasspath.jar"],
+ cmd = "$(location @bazel_tools//tools/jdk:ijar) $< $@",
+ tools = ["@bazel_tools//tools/jdk:ijar"],
+)
+
default_java_toolchain(
name = "toolchain_jdk8",
jvm_opts = JDK8_JVM_OPTS,
@@ -199,6 +224,7 @@ filegroup(
name = "srcs",
srcs = [
"BUILD-jdk", # Tools are build from the workspace for tests.
+ "DumpPlatformClassPath.java",
"alias_rules.bzl",
"default_java_toolchain.bzl",
"proguard_whitelister.py",
diff --git a/tools/jdk/DumpPlatformClassPath.java b/tools/jdk/DumpPlatformClassPath.java
new file mode 100644
index 0000000000..300e288d88
--- /dev/null
+++ b/tools/jdk/DumpPlatformClassPath.java
@@ -0,0 +1,143 @@
+// Copyright 2017 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.
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.GregorianCalendar;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.zip.CRC32;
+import java.util.zip.ZipEntry;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+/**
+ * Output a jar file containing all classes on the JDK 8 platform classpath of the default java
+ * compiler of the current JDK.
+ *
+ * <p>usage: DumpPlatformClassPath <target release> output.jar
+ */
+public class DumpPlatformClassPath {
+
+ public static void main(String[] args) throws IOException {
+ if (args.length != 2) {
+ System.err.println("usage: DumpPlatformClassPath <target release> <output jar>");
+ System.exit(1);
+ }
+ String targetRelease = args[0];
+ try (OutputStream os = Files.newOutputStream(Paths.get(args[1]));
+ BufferedOutputStream bos = new BufferedOutputStream(os, 65536);
+ JarOutputStream jos = new JarOutputStream(bos)) {
+ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, UTF_8);
+ if (isJdk9OrLater()) {
+ // this configures the filemanager to use a JDK 8 bootclasspath
+ compiler.getTask(
+ null, fileManager, null, Arrays.asList("--release", targetRelease), null, null);
+ Iterable<Path> paths;
+ try {
+ paths =
+ (Iterable<Path>)
+ StandardJavaFileManager.class
+ .getMethod("getLocationAsPaths", Location.class)
+ .invoke(fileManager, StandardLocation.PLATFORM_CLASS_PATH);
+ } catch (ReflectiveOperationException e) {
+ throw new LinkageError(e.getMessage(), e);
+ }
+ for (Path path : paths) {
+ Files.walkFileTree(
+ path,
+ new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ throws IOException {
+ if (file.getFileName().toString().endsWith(".sig")) {
+ String outputPath = path.relativize(file).toString();
+ outputPath =
+ outputPath.substring(0, outputPath.length() - ".sig".length()) + ".class";
+ addEntry(jos, outputPath, Files.readAllBytes(file));
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+ } else {
+ for (JavaFileObject fileObject :
+ fileManager.list(
+ StandardLocation.PLATFORM_CLASS_PATH,
+ "",
+ EnumSet.of(Kind.CLASS),
+ /* recurse= */ true)) {
+ String binaryName =
+ fileManager.inferBinaryName(StandardLocation.PLATFORM_CLASS_PATH, fileObject);
+ addEntry(
+ jos,
+ binaryName.replace('.', '/') + ".class",
+ toByteArray(fileObject.openInputStream()));
+ }
+ }
+ }
+ }
+
+ // Use a fixed timestamp for deterministic jar output.
+ private static final long FIXED_TIMESTAMP =
+ new GregorianCalendar(2010, 0, 1, 0, 0, 0).getTimeInMillis();
+
+ private static void addEntry(JarOutputStream jos, String name, byte[] bytes) throws IOException {
+ JarEntry je = new JarEntry(name);
+ je.setTime(FIXED_TIMESTAMP);
+ je.setMethod(ZipEntry.STORED);
+ je.setSize(bytes.length);
+ CRC32 crc = new CRC32();
+ crc.update(bytes);
+ je.setCrc(crc.getValue());
+ jos.putNextEntry(je);
+ jos.write(bytes);
+ }
+
+ private static byte[] toByteArray(InputStream is) throws IOException {
+ byte[] buffer = new byte[8192];
+ ByteArrayOutputStream boas = new ByteArrayOutputStream();
+ while (true) {
+ int r = is.read(buffer);
+ if (r == -1) {
+ break;
+ }
+ boas.write(buffer, 0, r);
+ }
+ return boas.toByteArray();
+ }
+
+ private static boolean isJdk9OrLater() {
+ return Double.parseDouble(System.getProperty("java.class.version")) >= 53.0;
+ }
+}
diff --git a/tools/jdk/default_java_toolchain.bzl b/tools/jdk/default_java_toolchain.bzl
index ca5615b61d..f6a91ead78 100644
--- a/tools/jdk/default_java_toolchain.bzl
+++ b/tools/jdk/default_java_toolchain.bzl
@@ -51,10 +51,14 @@ DEFAULT_JAVACOPTS = [
]
DEFAULT_TOOLCHAIN_CONFIGURATION = {
- "bootclasspath": [":bootclasspath"],
+ # javac -extdirs is implemented by appending the contents to the platform
+ # class path after -bootclasspath. For convenience, we currently have a
+ # single jar that contains the contents of both the bootclasspath and
+ # extdirs.
+ "bootclasspath": ["platformclasspath.jar"],
+ "extclasspath": [],
"compatible_javacopts": DEFAULT_COMPATIBLE_JAVACOPTS,
"encoding": "UTF-8",
- "extclasspath": [],
"forcibly_disable_header_compilation": 0,
"genclass": ["@bazel_tools//tools/jdk:genclass"],
"header_compiler": ["@bazel_tools//tools/jdk:turbine"],