Skip to content

Commit

Permalink
Invoke javac using the API, instead of main()
Browse files Browse the repository at this point in the history
This unifies the test and production javac invocations. Location arguments
(e.g. classpath, sources) are now set programatically from Paths, instead
of going through string args.

The classloader masking plugin is now just a custom filemanager, since javac
uses the same context for the entire compilation and we don't need a plugin
to carry it across annotation processing rounds.

--
PiperOrigin-RevId: 144110025
MOS_MIGRATED_REVID=144110025
  • Loading branch information
cushon authored and hlopko committed Jan 10, 2017
1 parent 4d3dbbc commit 3c5e55f
Show file tree
Hide file tree
Showing 15 changed files with 348 additions and 306 deletions.
Expand Up @@ -17,6 +17,7 @@
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.io.Files; import com.google.common.io.Files;
import com.google.devtools.build.buildjar.javac.BlazeJavacArguments;
import com.google.devtools.build.buildjar.javac.BlazeJavacMain; import com.google.devtools.build.buildjar.javac.BlazeJavacMain;
import com.google.devtools.build.buildjar.javac.JavacRunner; import com.google.devtools.build.buildjar.javac.JavacRunner;
import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin; import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin;
Expand Down Expand Up @@ -60,8 +61,10 @@ public Result compileJavaLibrary(final JavaLibraryBuildRequest build, final Prin
new JavacRunner() { new JavacRunner() {
@Override @Override
public Result invokeJavac( public Result invokeJavac(
ImmutableList<BlazeJavaCompilerPlugin> plugins, String[] args, PrintWriter output) { ImmutableList<BlazeJavaCompilerPlugin> plugins,
return new BlazeJavacMain(output, plugins).compile(args); BlazeJavacArguments arguments,
PrintWriter output) {
return new BlazeJavacMain(output, plugins).compile(arguments);
} }
}; };
Result result = compileSources(build, javacRunner, err); Result result = compileSources(build, javacRunner, err);
Expand Down
Expand Up @@ -34,7 +34,7 @@
* *
* <p>Implements common functionality like source files preparation and output jar creation. * <p>Implements common functionality like source files preparation and output jar creation.
*/ */
public abstract class AbstractLibraryBuilder extends CommonJavaLibraryProcessor { public abstract class AbstractLibraryBuilder {


/** /**
* Prepares a compilation run. This involves cleaning up temporary directories and writing the * Prepares a compilation run. This involves cleaning up temporary directories and writing the
Expand Down
Expand Up @@ -37,6 +37,7 @@ java_library(
":invalid_command_line_exception", ":invalid_command_line_exception",
":javac_options", ":javac_options",
"//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins", "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins",
"//third_party:auto_value",
"//third_party:guava", "//third_party:guava",
"//third_party:jsr305", "//third_party:jsr305",
"//third_party/java/jdk/langtools:javac", "//third_party/java/jdk/langtools:javac",
Expand All @@ -63,7 +64,6 @@ java_library(
":javac_options", ":javac_options",
"//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper", "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper",
"//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins", "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins",
"//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins:classloader",
"//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins:dependency", "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins:dependency",
"//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins:errorprone", "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins:errorprone",
"//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins:processing", "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins:processing",
Expand Down
Expand Up @@ -19,7 +19,6 @@
import com.google.devtools.build.buildjar.instrumentation.JacocoInstrumentationProcessor; import com.google.devtools.build.buildjar.instrumentation.JacocoInstrumentationProcessor;
import com.google.devtools.build.buildjar.javac.JavacOptions; import com.google.devtools.build.buildjar.javac.JavacOptions;
import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin; import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin;
import com.google.devtools.build.buildjar.javac.plugins.classloader.ClassLoaderMaskingPlugin;
import com.google.devtools.build.buildjar.javac.plugins.dependency.DependencyModule; import com.google.devtools.build.buildjar.javac.plugins.dependency.DependencyModule;
import com.google.devtools.build.buildjar.javac.plugins.errorprone.ErrorPronePlugin; import com.google.devtools.build.buildjar.javac.plugins.errorprone.ErrorPronePlugin;
import com.google.devtools.build.lib.worker.WorkerProtocol.WorkRequest; import com.google.devtools.build.lib.worker.WorkerProtocol.WorkRequest;
Expand Down Expand Up @@ -133,7 +132,6 @@ public static JavaLibraryBuildRequest parse(List<String> args)
throws IOException, InvalidCommandLineException { throws IOException, InvalidCommandLineException {
OptionsParser optionsParser = new OptionsParser(args); OptionsParser optionsParser = new OptionsParser(args);
ImmutableList.Builder<BlazeJavaCompilerPlugin> plugins = ImmutableList.builder(); ImmutableList.Builder<BlazeJavaCompilerPlugin> plugins = ImmutableList.builder();
plugins.add(new ClassLoaderMaskingPlugin());


// Support for -extra_checks:off was removed from ErrorPronePlugin, but Bazel still needs it, // Support for -extra_checks:off was removed from ErrorPronePlugin, but Bazel still needs it,
// so we'll emulate support for this here by handling the flag ourselves and not loading the // so we'll emulate support for this here by handling the flag ourselves and not loading the
Expand Down

This file was deleted.

Expand Up @@ -14,11 +14,20 @@


package com.google.devtools.build.buildjar; package com.google.devtools.build.buildjar;


import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.buildjar.javac.BlazeJavacArguments;
import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin; import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin;
import com.google.devtools.build.buildjar.javac.plugins.dependency.DependencyModule; import com.google.devtools.build.buildjar.javac.plugins.dependency.DependencyModule;
import com.google.devtools.build.buildjar.javac.plugins.processing.AnnotationProcessingModule; import com.google.devtools.build.buildjar.javac.plugins.processing.AnnotationProcessingModule;
import java.io.File;
import java.io.IOError;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
Expand All @@ -45,7 +54,7 @@ public final class JavaLibraryBuildRequest {
private final ImmutableList<String> rootResourceFiles; private final ImmutableList<String> rootResourceFiles;


private final String classPath; private final String classPath;

private final String bootClassPath;
private final String extdir; private final String extdir;


private final String processorPath; private final String processorPath;
Expand Down Expand Up @@ -142,6 +151,7 @@ public JavaLibraryBuildRequest(
this.resourceJars = ImmutableList.copyOf(optionsParser.getResourceJars()); this.resourceJars = ImmutableList.copyOf(optionsParser.getResourceJars());
this.rootResourceFiles = ImmutableList.copyOf(optionsParser.getRootResourceFiles()); this.rootResourceFiles = ImmutableList.copyOf(optionsParser.getRootResourceFiles());
this.classPath = optionsParser.getClassPath(); this.classPath = optionsParser.getClassPath();
this.bootClassPath = optionsParser.getBootClassPath();
this.extdir = optionsParser.getExtdir(); this.extdir = optionsParser.getExtdir();
this.processorPath = optionsParser.getProcessorPath(); this.processorPath = optionsParser.getProcessorPath();
this.processorNames = optionsParser.getProcessorNames(); this.processorNames = optionsParser.getProcessorNames();
Expand Down Expand Up @@ -218,6 +228,10 @@ public String getClassPath() {
return classPath; return classPath;
} }


public String getBootClassPath() {
return bootClassPath;
}

public String getExtdir() { public String getExtdir() {
return extdir; return extdir;
} }
Expand Down Expand Up @@ -263,4 +277,95 @@ public AnnotationProcessingModule getProcessingModule() {
public ImmutableList<BlazeJavaCompilerPlugin> getPlugins() { public ImmutableList<BlazeJavaCompilerPlugin> getPlugins() {
return plugins; return plugins;
} }

public BlazeJavacArguments toBlazeJavacArguments(final String classPath) {
return BlazeJavacArguments.builder()
.classPath(toPaths(classPath))
.classOutput(Paths.get(getClassDir()))
.bootClassPath(
ImmutableList.copyOf(Iterables.concat(toPaths(getBootClassPath()), getExtJars())))
.javacOptions(makeJavacArguments())
.sourceFiles(toPaths(getSourceFiles()))
.processors(null)
.sourceOutput(getSourceGenDir() != null ? Paths.get(getSourceGenDir()) : null)
.processorPath(toPaths(getProcessorPath()))
.build();
}

// TODO(cushon): make Bazel pass the individual files instead of inferring a directory and
// listing it here
List<Path> getExtJars() {
if (getExtdir() == null) {
return ImmutableList.of();
}
ImmutableList.Builder<Path> jars = ImmutableList.builder();
for (String file : Splitter.on(File.pathSeparatorChar).split(getExtdir())) {
try {
Path path = Paths.get(file);
if (Files.isDirectory(path)) {
Files.list(path).forEach(jars::add);
} else {
jars.add(path);
}
} catch (IOException e) {
throw new IOError(e);
}
}
return jars.build();
}

static ImmutableList<Path> toPaths(List<String> files) {
if (files == null) {
return ImmutableList.of();
}
ImmutableList.Builder<Path> result = ImmutableList.builder();
for (String e : files) {
result.add(Paths.get(e));
}
return result.build();
}

static ImmutableList<Path> toPaths(String classPath) {
if (classPath == null) {
return ImmutableList.of();
}
ImmutableList.Builder<Path> result = ImmutableList.builder();
for (String e : Splitter.on(File.pathSeparatorChar).split(classPath)) {
result.add(Paths.get(e));
}
return result.build();
}

/** Constructs a command line that can be used for a javac invocation. */
ImmutableList<String> makeJavacArguments() {
ImmutableList.Builder<String> javacArguments = ImmutableList.builder();
javacArguments.addAll(getJavacOpts());

if (!getProcessors().isEmpty() && !getSourceFiles().isEmpty()) {
// ImmutableSet.copyOf maintains order
ImmutableSet<String> deduplicatedProcessorNames = ImmutableSet.copyOf(getProcessors());
javacArguments.add("-processor");
javacArguments.add(Joiner.on(',').join(deduplicatedProcessorNames));
} else {
// This is necessary because some jars contain discoverable annotation processors that
// previously didn't run, and they break builds if the "-proc:none" option is not passed to
// javac.
javacArguments.add("-proc:none");
}

for (String option : getJavacOpts()) {
if (option.startsWith("-J")) { // ignore the VM options.
continue;
}
if (option.equals("-processor") || option.equals("-processorpath")) {
throw new IllegalStateException(
"Using "
+ option
+ " in javacopts is no longer supported."
+ " Use a java_plugin() rule instead.");
}
}

return javacArguments.build();
}
} }
Expand Up @@ -27,6 +27,7 @@
import java.util.Deque; import java.util.Deque;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
Expand Down Expand Up @@ -64,7 +65,7 @@ public final class OptionsParser {
private final List<String> rootResourceFiles = new ArrayList<>(); private final List<String> rootResourceFiles = new ArrayList<>();


private String classPath = ""; private String classPath = "";

private String bootClassPath;
private String extdir; private String extdir;


private String processorPath = ""; private String processorPath = "";
Expand Down Expand Up @@ -107,6 +108,7 @@ private void processCommandlineArgs(Deque<String> argQueue) throws InvalidComman
// otherwise we have to do something like adding a "--" // otherwise we have to do something like adding a "--"
// terminator to the passed arguments. // terminator to the passed arguments.
collectFlagArguments(javacOpts, argQueue, "--"); collectFlagArguments(javacOpts, argQueue, "--");
bootClassPathFromJavacOpts();
break; break;
case "--direct_dependency": case "--direct_dependency":
{ {
Expand Down Expand Up @@ -167,6 +169,9 @@ private void processCommandlineArgs(Deque<String> argQueue) throws InvalidComman
case "--classpath": case "--classpath":
classPath = getArgument(argQueue, arg); classPath = getArgument(argQueue, arg);
break; break;
case "--bootclasspath":
bootClassPath = getArgument(argQueue, arg);
break;
case "--processorpath": case "--processorpath":
processorPath = getArgument(argQueue, arg); processorPath = getArgument(argQueue, arg);
break; break;
Expand Down Expand Up @@ -314,6 +319,19 @@ private void addExternalPostProcessor(Deque<String> args, String arg)
postProcessors.put(processorName, arguments); postProcessors.put(processorName, arguments);
} }


// TODO(cushon): update Blaze to set --bootclasspath directly
private void bootClassPathFromJavacOpts() {
Iterator<String> it = javacOpts.iterator();
while (it.hasNext()) {
String curr = it.next();
if (curr.equals("-bootclasspath") && it.hasNext()) {
it.remove();
bootClassPath = it.next();
it.remove();
}
}
}

public List<String> getJavacOpts() { public List<String> getJavacOpts() {
return javacOpts; return javacOpts;
} }
Expand Down Expand Up @@ -386,6 +404,10 @@ public String getClassPath() {
return classPath; return classPath;
} }


public String getBootClassPath() {
return bootClassPath;
}

public String getExtdir() { public String getExtdir() {
return extdir; return extdir;
} }
Expand Down
Expand Up @@ -56,12 +56,15 @@ Result compileSources(JavaLibraryBuildRequest build, JavacRunner javacRunner, Pr
// class output directory to prevent that from happening. // class output directory to prevent that from happening.
compressedClasspath = build.getClassDir(); compressedClasspath = build.getClassDir();
} }
String[] javacArguments = makeJavacArguments(build, compressedClasspath);


// Compile! // Compile!
StringWriter javacOutput = new StringWriter(); StringWriter javacOutput = new StringWriter();
PrintWriter javacOutputWriter = new PrintWriter(javacOutput); PrintWriter javacOutputWriter = new PrintWriter(javacOutput);
Result result = javacRunner.invokeJavac(build.getPlugins(), javacArguments, javacOutputWriter); Result result =
javacRunner.invokeJavac(
build.getPlugins(),
build.toBlazeJavacArguments(compressedClasspath),
javacOutputWriter);
javacOutputWriter.close(); javacOutputWriter.close();


// If javac errored out because of missing entries on the classpath, give it another try. // If javac errored out because of missing entries on the classpath, give it another try.
Expand All @@ -75,8 +78,9 @@ Result compileSources(JavaLibraryBuildRequest build, JavacRunner javacRunner, Pr
prepareSourceCompilation(build); prepareSourceCompilation(build);


// Fall back to the regular compile, but add extra checks to catch transitive uses // Fall back to the regular compile, but add extra checks to catch transitive uses
javacArguments = makeJavacArguments(build); result =
result = javacRunner.invokeJavac(build.getPlugins(), javacArguments, err); javacRunner.invokeJavac(
build.getPlugins(), build.toBlazeJavacArguments(build.getClassPath()), err);
} else { } else {
err.print(javacOutput.getBuffer()); err.print(javacOutput.getBuffer());
} }
Expand Down

0 comments on commit 3c5e55f

Please sign in to comment.