blob: b6049bfb72730e49df6274c0b4e1f2cb36f8633b [file] [log] [blame]
// Copyright 2014 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.buildjar;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.buildjar.jarhelper.JarCreator;
import com.google.devtools.build.buildjar.javac.JavacRunner;
import com.sun.tools.javac.main.Main.Result;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
* An implementation of the JavaBuilder that uses in-process javac to compile java files.
*/
public class SimpleJavaLibraryBuilder extends AbstractJavaBuilder {
@Override
Result compileSources(JavaLibraryBuildRequest build, JavacRunner javacRunner, PrintWriter err)
throws IOException {
String[] javacArguments = makeJavacArguments(build, build.getClassPath());
return javacRunner.invokeJavac(javacArguments, err);
}
@Override
protected void prepareSourceCompilation(JavaLibraryBuildRequest build) throws IOException {
super.prepareSourceCompilation(build);
// Create sourceGenDir if necessary.
if (build.getSourceGenDir() != null) {
File sourceGenDir = new File(build.getSourceGenDir());
if (sourceGenDir.exists()) {
try {
cleanupOutputDirectory(sourceGenDir);
} catch (IOException e) {
throw new IOException("Cannot clean output directory '" + sourceGenDir + "'", e);
}
}
sourceGenDir.mkdirs();
}
}
/**
* For the build configuration 'build', construct a command line that
* can be used for a javac invocation.
*/
protected String[] makeJavacArguments(JavaLibraryBuildRequest build) {
return makeJavacArguments(build, build.getClassPath());
}
/**
* For the build configuration 'build', construct a command line that
* can be used for a javac invocation.
*/
protected String[] makeJavacArguments(JavaLibraryBuildRequest build, String classPath) {
List<String> javacArguments = createInitialJavacArgs(build, classPath);
javacArguments.addAll(getAnnotationProcessingOptions(build));
for (String option : build.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.");
}
javacArguments.add(option);
}
javacArguments.addAll(build.getSourceFiles());
return javacArguments.toArray(new String[0]);
}
/**
* Given a JavaLibraryBuildRequest, computes the javac options for the annotation processing
* requested.
*/
private List<String> getAnnotationProcessingOptions(JavaLibraryBuildRequest build) {
List<String> args = new ArrayList<>();
// Javac treats "-processorpath ''" as setting the processor path to an empty list,
// whereas omitting the option is treated as not having a processor path (which causes
// processor path searches to fallback to the class path).
args.add("-processorpath");
args.add(
build.getProcessorPath().isEmpty() ? "" : build.getProcessorPath());
if (!build.getProcessors().isEmpty() && !build.getSourceFiles().isEmpty()) {
// ImmutableSet.copyOf maintains order
ImmutableSet<String> deduplicatedProcessorNames = ImmutableSet.copyOf(build.getProcessors());
args.add("-processor");
args.add(Joiner.on(',').join(deduplicatedProcessorNames));
// Set javac output directory for generated sources.
if (build.getSourceGenDir() != null) {
args.add("-s");
args.add(build.getSourceGenDir());
}
} 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.
args.add("-proc:none");
}
return args;
}
@Override
public void buildGensrcJar(JavaLibraryBuildRequest build, OutputStream err)
throws IOException {
JarCreator jar = new JarCreator(build.getGeneratedSourcesOutputJar());
jar.setNormalize(true);
jar.setCompression(build.compressJar());
jar.addDirectory(build.getSourceGenDir());
jar.execute();
}
}