aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/java_tools
diff options
context:
space:
mode:
authorGravatar cushon <cushon@google.com>2017-09-05 00:37:27 +0200
committerGravatar Yun Peng <pcloudy@google.com>2017-09-05 09:54:58 +0200
commit98bfd9831168660d10ba4f29b62dc65d90653b13 (patch)
tree2c5d0d7bdc6f7449d702629b8bd75ad74fb21481 /src/java_tools
parentfd4f5ac67942c0a29e75903d04c403edb6ce4d7d (diff)
Support direct classpaths in javac-turbine
PiperOrigin-RevId: 167520688
Diffstat (limited to 'src/java_tools')
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/StrictJavaDepsPlugin.java17
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/BUILD16
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTransitive.java135
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbine.java22
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompileRequest.java23
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompiler.java7
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineJavaCompiler.java12
-rw-r--r--src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTransitiveTest.java48
-rw-r--r--src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java8
9 files changed, 263 insertions, 25 deletions
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/StrictJavaDepsPlugin.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/StrictJavaDepsPlugin.java
index b7d21f69fc..1373daab9b 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/StrictJavaDepsPlugin.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/StrictJavaDepsPlugin.java
@@ -47,7 +47,6 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.annotation.Generated;
-import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
/**
@@ -77,7 +76,6 @@ public final class StrictJavaDepsPlugin extends BlazeJavaCompilerPlugin {
private static Properties targetMap;
- private JavaFileManager fileManager;
private PrintWriter errWriter;
@@ -103,7 +101,6 @@ public final class StrictJavaDepsPlugin extends BlazeJavaCompilerPlugin {
public void init(Context context, Log log, JavaCompiler compiler) {
super.init(context, log, compiler);
errWriter = log.getWriter(WriterKind.ERROR);
- fileManager = context.get(JavaFileManager.class);
implicitDependencyExtractor =
new ImplicitDependencyExtractor(
dependencyModule.getUsedClasspath(),
@@ -113,7 +110,7 @@ public final class StrictJavaDepsPlugin extends BlazeJavaCompilerPlugin {
if (checkingTreeScanner == null) {
Set<String> platformJars = dependencyModule.getPlatformJars();
checkingTreeScanner =
- new CheckingTreeScanner(dependencyModule, log, missingTargets, platformJars, fileManager);
+ new CheckingTreeScanner(dependencyModule, log, missingTargets, platformJars);
context.put(CheckingTreeScanner.class, checkingTreeScanner);
}
initTargetMap();
@@ -202,9 +199,6 @@ public final class StrictJavaDepsPlugin extends BlazeJavaCompilerPlugin {
/** All error reporting is done through javac's log, */
private final Log log;
- /** The compilation's file manager. */
- private final JavaFileManager fileManager;
-
/** The strict_java_deps mode */
private final StrictJavaDeps strictJavaDepsMode;
@@ -229,15 +223,13 @@ public final class StrictJavaDepsPlugin extends BlazeJavaCompilerPlugin {
DependencyModule dependencyModule,
Log log,
Set<JarOwner> missingTargets,
- Set<String> platformJars,
- JavaFileManager fileManager) {
+ Set<String> platformJars) {
this.indirectJarsToTargets = dependencyModule.getIndirectMapping();
this.strictJavaDepsMode = dependencyModule.getStrictJavaDeps();
this.log = log;
this.missingTargets = missingTargets;
this.directDependenciesMap = dependencyModule.getExplicitDependenciesMap();
this.platformJars = platformJars;
- this.fileManager = fileManager;
}
Set<ClassSymbol> getSeenClasses() {
@@ -251,7 +243,7 @@ public final class StrictJavaDepsPlugin extends BlazeJavaCompilerPlugin {
}
Symbol.TypeSymbol sym = node.type.tsym;
- String jarName = getJarName(fileManager, sym.enclClass(), platformJars);
+ String jarName = getJarName(sym.enclClass(), platformJars);
// If this type symbol comes from a class file loaded from a jar, check
// whether that jar was a direct dependency and error out otherwise.
@@ -418,8 +410,7 @@ public final class StrictJavaDepsPlugin extends BlazeJavaCompilerPlugin {
*
* @param platformJars jars on javac's bootclasspath
*/
- static String getJarName(
- JavaFileManager fileManager, ClassSymbol classSymbol, Set<String> platformJars) {
+ public static String getJarName(ClassSymbol classSymbol, Set<String> platformJars) {
if (classSymbol == null) {
return null;
}
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/BUILD b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/BUILD
index 5cccd6ed1e..51631c5aae 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/BUILD
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/BUILD
@@ -9,6 +9,7 @@ java_library(
name = "javac_turbine",
srcs = ["JavacTurbine.java"],
deps = [
+ ":javac_transitive",
":javac_turbine_compile_request",
":javac_turbine_compile_result",
":javac_turbine_compiler",
@@ -28,6 +29,7 @@ java_library(
name = "javac_turbine_compile_request",
srcs = ["JavacTurbineCompileRequest.java"],
deps = [
+ ":javac_transitive",
"//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins:dependency",
"//third_party:guava",
"//third_party:jsr305",
@@ -49,6 +51,7 @@ java_library(
name = "javac_turbine_compiler",
srcs = ["JavacTurbineCompiler.java"],
deps = [
+ ":javac_transitive",
":javac_turbine_compile_request",
":javac_turbine_compile_result",
":javac_turbine_java_compiler",
@@ -64,6 +67,7 @@ java_library(
name = "javac_turbine_java_compiler",
srcs = ["JavacTurbineJavaCompiler.java"],
deps = [
+ ":javac_transitive",
":javac_turbine_compile_request",
":tree_pruner",
"//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins:dependency",
@@ -73,6 +77,18 @@ java_library(
)
java_library(
+ name = "javac_transitive",
+ srcs = ["JavacTransitive.java"],
+ deps = [
+ "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins:dependency",
+ "//third_party:guava",
+ "//third_party:jsr305",
+ "//third_party:turbine",
+ "//third_party/java/jdk/langtools:javac",
+ ],
+)
+
+java_library(
name = "zip_util",
srcs = ["ZipUtil.java"],
deps = [
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTransitive.java b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTransitive.java
new file mode 100644
index 0000000000..f06e1f4d61
--- /dev/null
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTransitive.java
@@ -0,0 +1,135 @@
+// 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.
+
+package com.google.devtools.build.java.turbine.javac;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.io.ByteStreams;
+import com.google.devtools.build.buildjar.javac.plugins.dependency.StrictJavaDepsPlugin;
+import com.google.turbine.bytecode.ClassFile;
+import com.google.turbine.bytecode.ClassReader;
+import com.google.turbine.bytecode.ClassWriter;
+import com.google.turbine.deps.Transitive;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.comp.AttrContext;
+import com.sun.tools.javac.comp.Env;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.tree.TreeScanner;
+import java.io.IOError;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+
+/**
+ * Collects the minimal compile-time API for symbols in the supertype closure of compiled classes.
+ * This allows non-javac header compilations to be performed against a classpath containing only
+ * direct dependencies and no transitive dependencies.
+ *
+ * <p>See {@link Transitive} for the parallel implementation in non-javac turbine.
+ */
+public class JavacTransitive {
+
+ private final ImmutableSet<String> platformJars;
+
+ public JavacTransitive(ImmutableSet<String> platformJars) {
+ this.platformJars = platformJars;
+ }
+
+ private final Set<ClassSymbol> closure = new LinkedHashSet<>();
+ private Map<String, byte[]> transitive = new LinkedHashMap<>();
+
+ /**
+ * Collects re-packaged transitive dependencies, and reset shared state. (The instance may be
+ * re-used, e.g. after fall back from the reduced classpath optimization.)
+ */
+ public Map<String, byte[]> collectTransitiveDependencies() {
+ Map<String, byte[]> result = transitive;
+ transitive = new LinkedHashMap<>();
+ return result;
+ }
+
+ /**
+ * Records the super type closure of all class declarations in the given compilation unit. Called
+ * after attribute is complete for a compilation unit.
+ */
+ public void postAttribute(Env<AttrContext> result) {
+ result.toplevel.accept(
+ new TreeScanner() {
+ @Override
+ public void visitClassDef(JCClassDecl tree) {
+ recordSuperClosure(tree.sym);
+ super.visitClassDef(tree);
+ }
+ });
+ }
+
+ /**
+ * Finish collecting and repackaging. Called while compilation state is still available (e.g. file
+ * objects are still open). This method should be idempotent, as {@link JavaCompiler}s sometimes
+ * get closed twice.
+ */
+ public void finish() {
+ Set<ClassSymbol> directChildren = new LinkedHashSet<>();
+ for (ClassSymbol sym : closure) {
+ for (Symbol member : sym.getEnclosedElements()) {
+ if (member instanceof ClassSymbol) {
+ directChildren.add((ClassSymbol) member);
+ }
+ }
+ }
+ closure.addAll(directChildren);
+ for (ClassSymbol sym : closure) {
+ String name = sym.flatName().toString().replace('.', '/');
+ if (transitive.containsKey(name)) {
+ continue;
+ }
+ if (StrictJavaDepsPlugin.getJarName(sym, platformJars) == null) {
+ // Don't repackage symbols we wouldn't report in jdeps, e.g. because they're on the
+ // bootclasspath.
+ continue;
+ }
+ JavaFileObject jfo = sym.classfile;
+ if (jfo == null || jfo.getKind() != Kind.CLASS) {
+ continue;
+ }
+ ClassFile cf;
+ try {
+ cf = ClassReader.read(ByteStreams.toByteArray(jfo.openInputStream()));
+ } catch (IOException e) {
+ throw new IOError(e);
+ }
+ transitive.put(name, ClassWriter.writeClass(Transitive.trimClass(cf)));
+ }
+ closure.clear();
+ }
+
+ private void recordSuperClosure(Symbol bound) {
+ if (!(bound instanceof ClassSymbol)) {
+ return;
+ }
+ ClassSymbol info = (ClassSymbol) bound;
+ closure.add(info);
+ recordSuperClosure(info.getSuperclass().asElement());
+ for (Type i : info.getInterfaces()) {
+ recordSuperClosure(i.asElement());
+ }
+ }
+}
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbine.java b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbine.java
index afe20e1ae0..5f94142faf 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbine.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbine.java
@@ -27,6 +27,7 @@ import com.google.devtools.build.buildjar.javac.JavacOptions;
import com.google.devtools.build.buildjar.javac.plugins.dependency.DependencyModule;
import com.google.devtools.build.buildjar.javac.plugins.dependency.DependencyModule.StrictJavaDeps;
import com.google.devtools.build.buildjar.javac.plugins.dependency.StrictJavaDepsPlugin;
+import com.google.turbine.binder.ClassPathBinder;
import com.google.turbine.options.TurbineOptions;
import com.google.turbine.options.TurbineOptionsParser;
import com.sun.tools.javac.util.Context;
@@ -171,7 +172,10 @@ public class JavacTurbine implements AutoCloseable {
if (sources.isEmpty()) {
// accept compilations with an empty source list for compatibility with JavaBuilder
- emitClassJar(Paths.get(turbineOptions.outputFile()), ImmutableMap.of());
+ emitClassJar(
+ Paths.get(turbineOptions.outputFile()),
+ /* files= */ ImmutableMap.of(),
+ /* transitive= */ ImmutableMap.of());
dependencyModule.emitDependencyInformation(
/*classpath=*/ ImmutableList.of(), /*successful=*/ true);
return Result.OK_WITH_REDUCED_CLASSPATH;
@@ -187,6 +191,9 @@ public class JavacTurbine implements AutoCloseable {
requestBuilder.setStrictDepsPlugin(new StrictJavaDepsPlugin(dependencyModule));
+ JavacTransitive transitive = new JavacTransitive(turbineOptions.bootClassPath());
+ requestBuilder.setTransitivePlugin(transitive);
+
if (turbineOptions.shouldReduceClassPath()) {
// compile with reduced classpath
actualClasspath = compressedClasspath;
@@ -211,7 +218,10 @@ public class JavacTurbine implements AutoCloseable {
}
if (result.ok()) {
- emitClassJar(Paths.get(turbineOptions.outputFile()), compileResult.files());
+ emitClassJar(
+ Paths.get(turbineOptions.outputFile()),
+ compileResult.files(),
+ transitive.collectTransitiveDependencies());
dependencyModule.emitDependencyInformation(actualClasspath, compileResult.success());
} else {
out.print(compileResult.output());
@@ -260,11 +270,17 @@ public class JavacTurbine implements AutoCloseable {
}
/** Write the class output from a successful compilation to the output jar. */
- private static void emitClassJar(Path outputJar, ImmutableMap<String, byte[]> files)
+ private static void emitClassJar(
+ Path outputJar, Map<String, byte[]> files, Map<String, byte[]> transitive)
throws IOException {
try (OutputStream fos = Files.newOutputStream(outputJar);
ZipOutputStream zipOut =
new ZipOutputStream(new BufferedOutputStream(fos, ZIPFILE_BUFFER_SIZE))) {
+ for (Map.Entry<String, byte[]> entry : transitive.entrySet()) {
+ String name = entry.getKey();
+ byte[] bytes = entry.getValue();
+ ZipUtil.storeEntry(ClassPathBinder.TRANSITIVE_PREFIX + name + ".class", bytes, zipOut);
+ }
for (Map.Entry<String, byte[]> entry : files.entrySet()) {
String name = entry.getKey();
byte[] bytes = entry.getValue();
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompileRequest.java b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompileRequest.java
index 76bc0f0be5..c44de1ba4b 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompileRequest.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompileRequest.java
@@ -30,6 +30,7 @@ class JavacTurbineCompileRequest {
private final ImmutableList<Path> processorClassPath;
private final ImmutableList<String> javacOptions;
@Nullable private final StrictJavaDepsPlugin strictJavaDepsPlugin;
+ private final JavacTransitive transitivePlugin;
JavacTurbineCompileRequest(
ImmutableList<Path> sources,
@@ -37,13 +38,15 @@ class JavacTurbineCompileRequest {
ImmutableList<Path> bootClassPath,
ImmutableList<Path> processorClassPath,
ImmutableList<String> javacOptions,
- @Nullable StrictJavaDepsPlugin strictJavaDepsPlugin) {
+ @Nullable StrictJavaDepsPlugin strictJavaDepsPlugin,
+ JavacTransitive transitivePlugin) {
this.sources = checkNotNull(sources);
this.classPath = checkNotNull(classPath);
this.bootClassPath = checkNotNull(bootClassPath);
this.processorClassPath = checkNotNull(processorClassPath);
this.javacOptions = checkNotNull(javacOptions);
this.strictJavaDepsPlugin = strictJavaDepsPlugin;
+ this.transitivePlugin = checkNotNull(transitivePlugin);
}
/** The sources to compile. */
@@ -79,6 +82,10 @@ class JavacTurbineCompileRequest {
return strictJavaDepsPlugin;
}
+ JavacTransitive transitivePlugin() {
+ return transitivePlugin;
+ }
+
static JavacTurbineCompileRequest.Builder builder() {
return new Builder();
}
@@ -90,12 +97,19 @@ class JavacTurbineCompileRequest {
private ImmutableList<Path> processorClassPath;
private ImmutableList<String> javacOptions;
@Nullable private StrictJavaDepsPlugin strictDepsPlugin;
+ private JavacTransitive transitivePlugin;
private Builder() {}
JavacTurbineCompileRequest build() {
return new JavacTurbineCompileRequest(
- sources, classPath, bootClassPath, processorClassPath, javacOptions, strictDepsPlugin);
+ sources,
+ classPath,
+ bootClassPath,
+ processorClassPath,
+ javacOptions,
+ strictDepsPlugin,
+ transitivePlugin);
}
Builder setSources(ImmutableList<Path> sources) {
@@ -127,5 +141,10 @@ class JavacTurbineCompileRequest {
this.strictDepsPlugin = strictDepsPlugin;
return this;
}
+
+ Builder setTransitivePlugin(JavacTransitive transitivePlugin) {
+ this.transitivePlugin = transitivePlugin;
+ return this;
+ }
}
}
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompiler.java b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompiler.java
index ace06bf385..4f554a7797 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompiler.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompiler.java
@@ -53,7 +53,7 @@ public class JavacTurbineCompiler {
Context context = new Context();
try (PrintWriter pw = new PrintWriter(sw)) {
- setupContext(context, request.strictJavaDepsPlugin());
+ setupContext(context, request.strictJavaDepsPlugin(), request.transitivePlugin());
CacheFSInfo.preRegister(context);
try (FileSystem fs = Jimfs.newFileSystem(Configuration.forCurrentPlatform());
JavacFileManager fm = new JavacFileManager(new Context(), false, UTF_8)) {
@@ -105,7 +105,8 @@ public class JavacTurbineCompiler {
return new JavacTurbineCompileResult(ImmutableMap.copyOf(files), status, sw, context);
}
- static void setupContext(Context context, @Nullable StrictJavaDepsPlugin sjd) {
- JavacTurbineJavaCompiler.preRegister(context, sjd);
+ static void setupContext(
+ Context context, @Nullable StrictJavaDepsPlugin sjd, JavacTransitive transitive) {
+ JavacTurbineJavaCompiler.preRegister(context, sjd, transitive);
}
}
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineJavaCompiler.java b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineJavaCompiler.java
index 4f38892349..74b9b9ee66 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineJavaCompiler.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineJavaCompiler.java
@@ -36,13 +36,16 @@ import javax.tools.JavaFileObject;
class JavacTurbineJavaCompiler extends JavaCompiler implements AutoCloseable {
@Nullable private final StrictJavaDepsPlugin strictJavaDeps;
+ private final JavacTransitive transitive;
- public JavacTurbineJavaCompiler(Context context, @Nullable StrictJavaDepsPlugin strictJavaDeps) {
+ public JavacTurbineJavaCompiler(
+ Context context, @Nullable StrictJavaDepsPlugin strictJavaDeps, JavacTransitive transitive) {
super(context);
this.strictJavaDeps = strictJavaDeps;
if (strictJavaDeps != null) {
strictJavaDeps.init(context, Log.instance(context), this);
}
+ this.transitive = transitive;
}
@Override
@@ -61,6 +64,7 @@ class JavacTurbineJavaCompiler extends JavaCompiler implements AutoCloseable {
if (strictJavaDeps != null) {
strictJavaDeps.postAttribute(result);
}
+ transitive.postAttribute(result);
return result;
}
@@ -78,19 +82,21 @@ class JavacTurbineJavaCompiler extends JavaCompiler implements AutoCloseable {
if (strictJavaDeps != null) {
strictJavaDeps.finish();
}
+ transitive.finish();
}
/**
* Override the default {@link JavaCompiler} implementation with {@link JavacTurbineJavaCompiler}
* for the given compilation context.
*/
- public static void preRegister(Context context, @Nullable final StrictJavaDepsPlugin sjd) {
+ public static void preRegister(
+ Context context, @Nullable final StrictJavaDepsPlugin sjd, JavacTransitive transitive) {
context.put(
compilerKey,
new Context.Factory<JavaCompiler>() {
@Override
public JavaCompiler make(Context c) {
- return new JavacTurbineJavaCompiler(c, sjd);
+ return new JavacTurbineJavaCompiler(c, sjd, transitive);
}
});
}
diff --git a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTransitiveTest.java b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTransitiveTest.java
new file mode 100644
index 0000000000..fd1825748c
--- /dev/null
+++ b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTransitiveTest.java
@@ -0,0 +1,48 @@
+// 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.
+
+package com.google.devtools.build.java.turbine.javac;
+
+import static com.google.common.truth.Truth.assertThat;
+import static java.util.stream.Collectors.toList;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.turbine.deps.AbstractTransitiveTest;
+import com.google.turbine.options.TurbineOptions;
+import java.io.IOException;
+import java.nio.file.Path;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class JavacTransitiveTest extends AbstractTransitiveTest {
+
+ @Override
+ protected Path runTurbine(ImmutableList<Path> sources, ImmutableList<Path> classpath)
+ throws IOException {
+ Path out = temporaryFolder.newFolder().toPath().resolve("out.jar");
+ boolean ok =
+ JavacTurbine.compile(
+ TurbineOptions.builder()
+ .addSources(sources.stream().map(Path::toString).collect(toList()))
+ .addClassPathEntries(classpath.stream().map(Path::toString).collect(toList()))
+ .addBootClassPathEntries(Iterables.transform(BOOTCLASSPATH, Path::toString))
+ .setOutput(out.toString())
+ .build())
+ .ok();
+ assertThat(ok).isTrue();
+ return out;
+ }
+}
diff --git a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java
index 611fdcf426..ac386f7d62 100644
--- a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java
+++ b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java
@@ -14,6 +14,7 @@
package com.google.devtools.build.java.turbine.javac;
+import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -51,6 +52,7 @@ import java.net.URI;
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.ArrayList;
@@ -115,7 +117,11 @@ public class JavacTurbineTest {
.setOutput(output.toString())
.setTempDir(tempdir.toString())
.addBootClassPathEntries(
- ImmutableList.copyOf(Splitter.on(':').split(System.getProperty("sun.boot.class.path"))))
+ Splitter.on(':')
+ .splitToList(System.getProperty("sun.boot.class.path"))
+ .stream()
+ .map(e -> Paths.get(e).toAbsolutePath().toString())
+ .collect(toImmutableList()))
.setOutputDeps(outputDeps.toString())
.addAllJavacOpts(Arrays.asList("-source", "8", "-target", "8"))
.setTargetLabel("//test")