Replace JavaCompileAction with a regular SpawnAction
PiperOrigin-RevId: 217329815
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index a11f42c..42c7e7f 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -1050,7 +1050,7 @@
"rules/java/JavaCompilationArtifacts.java",
"rules/java/JavaCompilationHelper.java",
"rules/java/JavaCompilationInfoProvider.java",
- "rules/java/JavaCompileAction.java",
+ "rules/java/JavaCompileActionBuilder.java",
"rules/java/JavaConfiguration.java",
"rules/java/JavaExportsProvider.java",
"rules/java/JavaGenJarsProvider.java",
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java
index 6ecfba7..488f330 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java
@@ -78,7 +78,7 @@
NestedSetBuilder<Artifact> metadataFilesBuilder) {
for (Artifact artifact : objectFiles) {
ActionAnalysisMetadata action = analysisEnvironment.getLocalGeneratingAction(artifact);
- if (action instanceof JavaCompileAction) {
+ if (JavaCompileActionBuilder.isJavaCompileAction(action)) {
addOutputs(metadataFilesBuilder, action, JavaSemantics.COVERAGE_METADATA);
} else if (action != null
&& action.getMnemonic().equals(ResourceJarActionBuilder.MNEMONIC)) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java
index 64ad5cd..b94426f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java
@@ -24,6 +24,7 @@
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ExecutionRequirements;
import com.google.devtools.build.lib.analysis.AnalysisEnvironment;
+import com.google.devtools.build.lib.analysis.AnalysisUtils;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.RuleContext;
@@ -203,7 +204,13 @@
createResourceJarAction(outputJar, ImmutableList.of(classJar));
}
- JavaCompileAction.Builder builder = createJavaCompileActionBuilder(semantics);
+ JavaCompileActionBuilder builder = new JavaCompileActionBuilder();
+ builder.setJavaExecutable(hostJavabase.javaBinaryExecPath());
+ builder.setJavaBaseInputs(
+ NestedSetBuilder.fromNestedSet(hostJavabase.javaBaseInputsMiddleman())
+ .addAll(additionalJavaBaseInputs)
+ .build());
+ builder.setTargetLabel(ruleContext.getLabel());
builder.setArtifactForExperimentalCoverage(maybeCreateExperimentalCoverageArtifact(outputJar));
builder.setClasspathEntries(attributes.getCompileTimeClassPath());
builder.setBootclasspathEntries(getBootclasspathOrDefault());
@@ -221,7 +228,7 @@
builder.setMetadata(instrumentationMetadataJar);
builder.setInstrumentationJars(jacocoInstrumentation);
builder.setSourceFiles(attributes.getSourceFiles());
- builder.addSourceJars(attributes.getSourceJars());
+ builder.setSourceJars(attributes.getSourceJars());
builder.setJavacOpts(customJavacOpts);
builder.setJavacJvmOpts(customJavacJvmOpts);
builder.setJavacExecutionInfo(getExecutionInfo());
@@ -239,7 +246,7 @@
attributes.getTargetLabel() == null
? ruleContext.getLabel() : attributes.getTargetLabel());
builder.setInjectingRuleKind(attributes.getInjectingRuleKind());
- getAnalysisEnvironment().registerAction(builder.build());
+ getAnalysisEnvironment().registerAction(builder.build(ruleContext, semantics));
}
private ImmutableMap<String, String> getExecutionInfo() {
@@ -248,7 +255,7 @@
javaToolchain.getJavacSupportsWorkers()
? ExecutionRequirements.WORKER_MODE_ENABLED
: ImmutableMap.of(),
- JavaCompileAction.MNEMONIC);
+ JavaCompileActionBuilder.MNEMONIC);
}
/** Returns the bootclasspath explicit set in attributes if present, or else the default. */
@@ -596,43 +603,35 @@
.build(semantics, ruleContext);
}
- private JavaCompileAction.Builder createJavaCompileActionBuilder(
- JavaSemantics semantics) {
- JavaCompileAction.Builder builder = new JavaCompileAction.Builder(ruleContext, semantics);
- builder.setJavaExecutable(hostJavabase.javaBinaryExecPath());
- builder.setJavaBaseInputs(NestedSetBuilder.fromNestedSet(hostJavabase.javaBaseInputsMiddleman())
- .addAll(additionalJavaBaseInputs)
- .build());
- builder.setTargetLabel(ruleContext.getLabel());
- return builder;
- }
-
/**
* Produces a derived directory where source files generated by annotation processors should be
* stored.
*/
- private PathFragment sourceGenDir(Artifact outputJar) {
+ private static PathFragment sourceGenDir(Artifact outputJar) {
return workDir(outputJar, "_sourcegenfiles");
}
- private PathFragment tempDir(Artifact outputJar) {
+ private static PathFragment tempDir(Artifact outputJar) {
return workDir(outputJar, "_temp");
}
- private PathFragment classDir(Artifact outputJar) {
+ /** Produces a derived directory where class outputs should be stored. */
+ public static PathFragment classDir(Artifact outputJar) {
return workDir(outputJar, "_classes");
}
/**
- * For an output jar and a suffix, produces a derived directory under
- * {@code bin} directory with a given suffix.
+ * For an output jar and a suffix, produces a derived directory under the same root as the output
+ * jar.
*
* <p>Note that this won't work if a rule produces two jars with the same basename.
*/
- private PathFragment workDir(Artifact outputJar, String suffix) {
+ private static PathFragment workDir(Artifact outputJar, String suffix) {
String basename = FileSystemUtils.removeExtension(outputJar.getExecPath().getBaseName());
- return getConfiguration().getBinDirectory(ruleContext.getRule().getRepository()).getExecPath()
- .getRelative(ruleContext.getUniqueDirectory(JAVAC))
+ return outputJar
+ .getRoot()
+ .getExecPath()
+ .getRelative(AnalysisUtils.getUniqueDirectory(outputJar.getOwnerLabel(), JAVAC))
.getRelative(basename + suffix);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java
deleted file mode 100644
index f744607..0000000
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java
+++ /dev/null
@@ -1,1008 +0,0 @@
-// 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.lib.rules.java;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static java.nio.charset.StandardCharsets.ISO_8859_1;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.devtools.build.lib.actions.Action;
-import com.google.devtools.build.lib.actions.ActionEnvironment;
-import com.google.devtools.build.lib.actions.ActionKeyContext;
-import com.google.devtools.build.lib.actions.ActionOwner;
-import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.ArtifactRoot;
-import com.google.devtools.build.lib.actions.CommandLine;
-import com.google.devtools.build.lib.actions.CommandLineExpansionException;
-import com.google.devtools.build.lib.actions.CommandLines;
-import com.google.devtools.build.lib.actions.CommandLines.CommandLineLimits;
-import com.google.devtools.build.lib.actions.ParamFileInfo;
-import com.google.devtools.build.lib.actions.ParameterFile;
-import com.google.devtools.build.lib.actions.ResourceSet;
-import com.google.devtools.build.lib.actions.RunfilesSupplier;
-import com.google.devtools.build.lib.actions.extra.ExtraActionInfo;
-import com.google.devtools.build.lib.actions.extra.JavaCompileInfo;
-import com.google.devtools.build.lib.analysis.AnalysisEnvironment;
-import com.google.devtools.build.lib.analysis.FilesToRunProvider;
-import com.google.devtools.build.lib.analysis.RuleContext;
-import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
-import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorArg;
-import com.google.devtools.build.lib.analysis.actions.LazyWritePathsFileAction;
-import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
-import com.google.devtools.build.lib.analysis.actions.SpawnAction;
-import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
-import com.google.devtools.build.lib.analysis.config.BuildConfiguration.StrictDepsMode;
-import com.google.devtools.build.lib.cmdline.Label;
-import com.google.devtools.build.lib.collect.nestedset.NestedSet;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
-import com.google.devtools.build.lib.collect.nestedset.Order;
-import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
-import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
-import com.google.devtools.build.lib.rules.java.JavaConfiguration.JavaClasspathMode;
-import com.google.devtools.build.lib.rules.java.JavaPluginInfoProvider.JavaPluginInfo;
-import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
-import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
-import com.google.devtools.build.lib.util.LazyString;
-import com.google.devtools.build.lib.util.StringCanonicalizer;
-import com.google.devtools.build.lib.vfs.PathFragment;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Stream;
-import javax.annotation.Nullable;
-
-/** Action that represents a Java compilation. */
-@ThreadCompatible
-@Immutable
-@AutoCodec
-public final class JavaCompileAction extends SpawnAction {
-
- private static final String JACOCO_INSTRUMENTATION_PROCESSOR = "jacoco";
-
- private static final ResourceSet LOCAL_RESOURCES =
- ResourceSet.createWithRamCpuIo(750 /*MB*/, 0.5 /*CPU*/, 0.0 /*IO*/);
-
- /** Environment variable that sets the UTF-8 charset. */
- static final ImmutableMap<String, String> UTF8_ENVIRONMENT =
- ImmutableMap.of("LC_CTYPE", "en_US.UTF-8");
-
- // TODO(#3320): This is missing the configuration's action environment!
- static final ActionEnvironment UTF8_ACTION_ENVIRONMENT =
- ActionEnvironment.create(UTF8_ENVIRONMENT);
- public static final String MNEMONIC = "Javac";
-
- private final CommandLine javaCompileCommandLine;
-
- /**
- * The directory in which generated classfiles are placed.
- * May be erased/created by the JavaBuilder.
- */
- private final PathFragment classDirectory;
-
- private final Artifact outputJar;
-
- /**
- * The list of classpath entries to specify to javac.
- */
- private final NestedSet<Artifact> classpathEntries;
-
- /** The list of bootclasspath entries to specify to javac. */
- private final ImmutableList<Artifact> bootclasspathEntries;
-
- /** The list of sourcepath entries to specify to javac. */
- private final ImmutableList<Artifact> sourcePathEntries;
-
- /**
- * The path to the extdir to specify to javac.
- */
- private final ImmutableList<Artifact> extdirInputs;
-
- /** The list of classpath entries to search for annotation processors. */
- private final NestedSet<Artifact> processorPath;
-
- /** The list of annotation processor classes to run. */
- private final NestedSet<String> processorNames;
-
- /** Set of additional Java source files to compile. */
- private final ImmutableList<Artifact> sourceJars;
-
- /** The set of explicit Java source files to compile. */
- private final ImmutableSet<Artifact> sourceFiles;
-
- /**
- * The compiler options to pass to javac.
- */
- private final ImmutableList<String> javacOpts;
-
- /** The subset of classpath jars provided by direct dependencies. */
- private final NestedSet<Artifact> directJars;
-
- /** The level of strict dependency checks (off, warnings, or errors). */
- private final StrictDepsMode strictJavaDeps;
-
- /** The tool with which to fix dependency errors. */
- private final String fixDepsTool;
-
- /** The set of .jdeps artifacts provided by direct dependencies. */
- private final NestedSet<Artifact> compileTimeDependencyArtifacts;
-
- /**
- * Constructs an action to compile a set of Java source files to class files.
- *
- * @param owner the action owner, typically a java_* RuleConfiguredTarget.
- * @param tools the tools used by the action
- * @param inputs the inputs of the action
- * @param outputs the outputs of the action
- * @param commandLines The invocation command line + possibly the param file command line
- * @param commandLineLimits The command line limits
- * @param javaCompileCommandLine The command line used by the param file
- * @param classDirectory the directory in which generated classfiles are placed
- * @param outputJar the jar file the compilation outputs will be written to
- * @param classpathEntries the compile-time classpath entries
- * @param bootclasspathEntries the compile-time bootclasspath entries
- * @param extdirInputs the compile-time extclasspath entries
- * @param processorPath the classpath to search for annotation processors
- * @param processorNames the annotation processors to run
- * @param sourceJars jars of sources to compile
- * @param sourceFiles source files to compile
- * @param javacOpts the javac options for the compilation
- * @param directJars the subset of classpath jars provided by direct dependencies
- * @param executionInfo the execution info
- * @param strictJavaDeps the Strict Java Deps mode
- * @param fixDepsTool the tool with which to fix dependency errors
- * @param compileTimeDependencyArtifacts the jdeps files for direct dependencies
- * @param progressMessage the progress message
- */
- @VisibleForSerialization
- @AutoCodec.Instantiator
- JavaCompileAction(
- ActionOwner owner,
- NestedSet<Artifact> tools,
- NestedSet<Artifact> inputs,
- Collection<Artifact> outputs,
- CommandLines commandLines,
- CommandLineLimits commandLineLimits,
- CommandLine javaCompileCommandLine,
- PathFragment classDirectory,
- Artifact outputJar,
- NestedSet<Artifact> classpathEntries,
- ImmutableList<Artifact> bootclasspathEntries,
- ImmutableList<Artifact> sourcePathEntries,
- ImmutableList<Artifact> extdirInputs,
- NestedSet<Artifact> processorPath,
- NestedSet<String> processorNames,
- Collection<Artifact> sourceJars,
- ImmutableSet<Artifact> sourceFiles,
- List<String> javacOpts,
- NestedSet<Artifact> directJars,
- Map<String, String> executionInfo,
- StrictDepsMode strictJavaDeps,
- String fixDepsTool,
- NestedSet<Artifact> compileTimeDependencyArtifacts,
- CharSequence progressMessage,
- RunfilesSupplier runfilesSupplier) {
- super(
- owner,
- tools,
- inputs,
- outputs,
- outputJar,
- LOCAL_RESOURCES,
- commandLines,
- commandLineLimits,
- false,
- // TODO(#3320): This is missing the configuration's action environment!
- UTF8_ACTION_ENVIRONMENT,
- ImmutableMap.copyOf(executionInfo),
- progressMessage,
- runfilesSupplier,
- MNEMONIC,
- /* executeUnconditionally= */ false,
- /* extraActionInfoSupplier= */ null);
- this.javaCompileCommandLine = javaCompileCommandLine;
- this.classDirectory = checkNotNull(classDirectory);
- this.outputJar = outputJar;
- this.classpathEntries = classpathEntries;
- this.bootclasspathEntries = ImmutableList.copyOf(bootclasspathEntries);
- this.sourcePathEntries = ImmutableList.copyOf(sourcePathEntries);
- this.extdirInputs = extdirInputs;
- this.processorPath = processorPath;
- this.processorNames = processorNames;
- this.sourceJars = ImmutableList.copyOf(sourceJars);
- this.sourceFiles = sourceFiles;
- this.javacOpts = ImmutableList.copyOf(javacOpts);
- this.directJars = checkNotNull(directJars, "directJars must not be null");
- this.strictJavaDeps = strictJavaDeps;
- this.fixDepsTool = checkNotNull(fixDepsTool);
- this.compileTimeDependencyArtifacts = compileTimeDependencyArtifacts;
- }
-
- /** Returns the given (passed to constructor) source files. */
- @VisibleForTesting
- ImmutableSet<Artifact> getSourceFiles() {
- return sourceFiles;
- }
-
- /**
- * Returns the list of paths that represents the classpath.
- */
- @VisibleForTesting
- public Iterable<Artifact> getClasspath() {
- return classpathEntries;
- }
-
- /** Returns the list of paths that represents the bootclasspath. */
- @VisibleForTesting
- Collection<Artifact> getBootclasspath() {
- return bootclasspathEntries;
- }
-
- /** Returns the list of paths that represents the sourcepath. */
- @VisibleForTesting
- public Collection<Artifact> getSourcePathEntries() {
- return sourcePathEntries;
- }
-
- /**
- * Returns the path to the extdir.
- */
- @VisibleForTesting
- public Collection<Artifact> getExtdir() {
- return extdirInputs;
- }
-
- /**
- * Returns the list of paths that represents the source jars.
- */
- @VisibleForTesting
- public Collection<Artifact> getSourceJars() {
- return sourceJars;
- }
-
- /** Returns the list of paths that represents the processor path. */
- @VisibleForTesting
- public NestedSet<Artifact> getProcessorpath() {
- return processorPath;
- }
-
- @VisibleForTesting
- public List<String> getJavacOpts() {
- return javacOpts;
- }
-
- @VisibleForTesting
- public NestedSet<Artifact> getDirectJars() {
- return directJars;
- }
-
- @VisibleForTesting
- public NestedSet<Artifact> getCompileTimeDependencyArtifacts() {
- return compileTimeDependencyArtifacts;
- }
-
- @VisibleForTesting
- public StrictDepsMode getStrictJavaDepsMode() {
- return strictJavaDeps;
- }
-
- public String getFixDepsTool() {
- return fixDepsTool;
- }
-
- public PathFragment getClassDirectory() {
- return classDirectory;
- }
-
- /**
- * Returns the list of class names of processors that should
- * be run.
- */
- @VisibleForTesting
- public List<String> getProcessorNames() {
- return processorNames.toList();
- }
-
- /**
- * Returns the output jar artifact that gets generated by archiving the results of the Java
- * compilation.
- */
- public Artifact getOutputJar() {
- return outputJar;
- }
-
- @Override
- public Artifact getPrimaryOutput() {
- return getOutputJar();
- }
-
- /**
- * Constructs a command line that can be used to invoke the JavaBuilder.
- *
- * <p>Do not use this method, except for testing (and for the in-process strategy).
- */
- @VisibleForTesting
- public Iterable<String> buildCommandLine() {
- try {
- return javaCompileCommandLine.arguments();
- } catch (CommandLineExpansionException e) {
- throw new AssertionError("JavaCompileAction command line expansion cannot fail");
- }
- }
-
- /** Returns the command and arguments for a java compile action. */
- @VisibleForTesting
- public List<String> getCommand() {
- try {
- return ImmutableList.copyOf(commandLines.getCommandLines().get(0).commandLine.arguments());
- } catch (CommandLineExpansionException e) {
- throw new AssertionError("JavaCompileAction command line expansion cannot fail");
- }
- }
-
- @Override
- public String toString() {
- try {
- StringBuilder result = new StringBuilder();
- result.append("JavaBuilder ");
- Joiner.on(' ').appendTo(result, javaCompileCommandLine.arguments());
- return result.toString();
- } catch (CommandLineExpansionException e) {
- return "Error expanding command line";
- }
- }
-
- @Override
- public ExtraActionInfo.Builder getExtraActionInfo(ActionKeyContext actionKeyContext) {
- JavaCompileInfo.Builder info = JavaCompileInfo.newBuilder();
- info.addAllSourceFile(Artifact.toExecPaths(getSourceFiles()));
- info.addAllClasspath(Artifact.toExecPaths(getClasspath()));
- info.addAllBootclasspath(Artifact.toExecPaths(getBootclasspath()));
- info.addAllSourcepath(Artifact.toExecPaths(getSourceJars()));
- info.addAllJavacOpt(getJavacOpts());
- info.addAllProcessor(getProcessorNames());
- info.addAllProcessorpath(Artifact.toExecPaths(getProcessorpath()));
- info.setOutputjar(getOutputJar().getExecPathString());
-
- try {
- info.addAllArgument(getArguments());
- return super.getExtraActionInfo(actionKeyContext)
- .setExtension(JavaCompileInfo.javaCompileInfo, info.build());
- } catch (CommandLineExpansionException e) {
- throw new AssertionError("JavaCompileAction command line expansion cannot fail");
- }
- }
-
- /**
- * Tells {@link Builder} how to create new artifacts. Is there so that {@link Builder} can be
- * exercised in tests without creating a full {@link RuleContext}.
- */
- public interface ArtifactFactory {
-
- /** Create an artifact with the specified root-relative path under the specified root. */
- Artifact create(PathFragment rootRelativePath, ArtifactRoot root);
- }
-
- @VisibleForTesting
- static ArtifactFactory createArtifactFactory(final AnalysisEnvironment env) {
- return new ArtifactFactory() {
- @Override
- public Artifact create(PathFragment rootRelativePath, ArtifactRoot root) {
- return env.getDerivedArtifact(rootRelativePath, root);
- }
- };
- }
-
- /**
- * Builder class to construct Java compile actions.
- */
- public static class Builder {
- private final ActionOwner owner;
- private final AnalysisEnvironment analysisEnvironment;
- private final ArtifactFactory artifactFactory;
- private final BuildConfiguration configuration;
- private final JavaSemantics semantics;
-
- private PathFragment javaExecutable;
- private List<Artifact> javabaseInputs = ImmutableList.of();
- private Artifact outputJar;
- private Artifact nativeHeaderOutput;
- private Artifact gensrcOutputJar;
- private Artifact manifestProtoOutput;
- private Artifact outputDepsProto;
- private Collection<Artifact> additionalOutputs;
- private Artifact paramFile;
- private Artifact metadata;
- private Artifact artifactForExperimentalCoverage;
- private ImmutableSet<Artifact> sourceFiles = ImmutableSet.of();
- private final Collection<Artifact> sourceJars = new ArrayList<>();
-
- /** @see {@link #setStrictJavaDeps}. */
- private StrictDepsMode strictJavaDeps = StrictDepsMode.ERROR;
-
- private String fixDepsTool = "add_dep";
- private NestedSet<Artifact> directJars = NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
- private NestedSet<Artifact> compileTimeDependencyArtifacts =
- NestedSetBuilder.emptySet(Order.STABLE_ORDER);
- private List<String> javacOpts = new ArrayList<>();
- private ImmutableList<String> javacJvmOpts = ImmutableList.of();
- private ImmutableMap<String, String> executionInfo = ImmutableMap.of();
- private boolean compressJar;
- private NestedSet<Artifact> classpathEntries =
- NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
- private ImmutableList<Artifact> bootclasspathEntries = ImmutableList.of();
- private ImmutableList<Artifact> sourcePathEntries = ImmutableList.of();
- private ImmutableList<Artifact> extdirInputs = ImmutableList.of();
- private FilesToRunProvider javaBuilder;
- private Artifact langtoolsJar;
- private NestedSet<Artifact> toolsJars = NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
- private ImmutableList<Artifact> instrumentationJars = ImmutableList.of();
- private PathFragment sourceGenDirectory;
- private PathFragment tempDirectory;
- private PathFragment classDirectory;
- private JavaPluginInfo plugins = JavaPluginInfo.empty();
- private NestedSet<Artifact> extraData = NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
- private Label targetLabel;
- @Nullable private String injectingRuleKind;
-
- /**
- * Creates a Builder from an owner and a build configuration.
- */
- public Builder(ActionOwner owner, AnalysisEnvironment analysisEnvironment,
- ArtifactFactory artifactFactory, BuildConfiguration configuration,
- JavaSemantics semantics) {
- this.owner = owner;
- this.analysisEnvironment = analysisEnvironment;
- this.artifactFactory = artifactFactory;
- this.configuration = configuration;
- this.semantics = semantics;
- }
-
- /**
- * Creates a Builder from an owner and a build configuration.
- */
- public Builder(final RuleContext ruleContext, JavaSemantics semantics) {
- this(
- ruleContext.getActionOwner(),
- ruleContext.getAnalysisEnvironment(),
- new ArtifactFactory() {
- @Override
- public Artifact create(PathFragment rootRelativePath, ArtifactRoot root) {
- return ruleContext.getDerivedArtifact(rootRelativePath, root);
- }
- },
- ruleContext.getConfiguration(),
- semantics);
- }
-
- public JavaCompileAction build() {
- // TODO(bazel-team): all the params should be calculated before getting here, and the various
- // aggregation code below should go away.
- final String pathSeparator = configuration.getHostPathSeparator();
- final List<String> internedJcopts = new ArrayList<>();
- for (String jcopt : javacOpts) {
- internedJcopts.add(StringCanonicalizer.intern(jcopt));
- }
-
- // Invariant: if strictJavaDeps is OFF, then directJars and
- // dependencyArtifacts are ignored
- if (strictJavaDeps == StrictDepsMode.OFF) {
- directJars = NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
- compileTimeDependencyArtifacts = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
- }
-
- // Invariant: if java_classpath is set to 'off', dependencyArtifacts are ignored
- JavaConfiguration javaConfiguration = configuration.getFragment(JavaConfiguration.class);
- if (javaConfiguration.getReduceJavaClasspath() == JavaClasspathMode.OFF) {
- compileTimeDependencyArtifacts = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
- }
-
- Preconditions.checkState(javaExecutable != null, owner);
-
- ImmutableList.Builder<Artifact> outputsBuilder = ImmutableList.<Artifact>builder();
- Stream.of(
- outputJar,
- metadata,
- gensrcOutputJar,
- manifestProtoOutput,
- outputDepsProto,
- nativeHeaderOutput)
- .filter(x -> x != null)
- .forEachOrdered(outputsBuilder::add);
- if (additionalOutputs != null) {
- outputsBuilder.addAll(additionalOutputs);
- }
- ImmutableList<Artifact> outputs = outputsBuilder.build();
-
- // The actual params-file-based command line executed for a compile action.
- CustomCommandLine.Builder javaBuilderCommandLine = CustomCommandLine.builder();
- Artifact javaBuilderJar = checkNotNull(javaBuilder.getExecutable());
- if (!javaBuilderJar.getExtension().equals("jar")) {
- // JavaBuilder is a non-deploy.jar executable.
- javaBuilderCommandLine.addExecPath(javaBuilderJar);
- } else {
- javaBuilderCommandLine.addPath(javaExecutable).addAll(javacJvmOpts);
- if (!instrumentationJars.isEmpty()) {
- javaBuilderCommandLine
- .addExecPaths(
- "-cp",
- VectorArg.join(pathSeparator)
- .each(
- ImmutableList.<Artifact>builder()
- .addAll(instrumentationJars)
- .add(javaBuilderJar)
- .build()))
- .addDynamicString(semantics.getJavaBuilderMainClass());
- } else {
- // If there are no instrumentation jars, use simpler '-jar' option to launch JavaBuilder.
- javaBuilderCommandLine.addExecPath("-jar", javaBuilderJar);
- }
- }
-
- if (artifactForExperimentalCoverage != null) {
- analysisEnvironment.registerAction(new LazyWritePathsFileAction(
- owner, artifactForExperimentalCoverage, sourceFiles, false));
- }
-
- NestedSet<Artifact> tools =
- NestedSetBuilder.<Artifact>stableOrder()
- .add(langtoolsJar)
- .addTransitive(toolsJars)
- .addTransitive(javaBuilder.getFilesToRun())
- .addAll(instrumentationJars)
- .build();
-
- NestedSetBuilder<Artifact> inputsBuilder =
- NestedSetBuilder.<Artifact>stableOrder()
- .addTransitive(classpathEntries)
- .addTransitive(compileTimeDependencyArtifacts)
- .addTransitive(plugins.processorClasspath())
- .addTransitive(plugins.data())
- .addTransitive(extraData)
- .addAll(sourceJars)
- .addAll(sourceFiles)
- .addAll(javabaseInputs)
- .addAll(bootclasspathEntries)
- .addAll(sourcePathEntries)
- .addAll(extdirInputs)
- .addTransitive(tools);
- if (artifactForExperimentalCoverage != null) {
- inputsBuilder.add(artifactForExperimentalCoverage);
- }
-
- final CommandLines commandLines;
- CustomCommandLine javaCompileCommandLine = buildParamFileContents(internedJcopts);
- if (configuration.deferParamFiles()) {
- commandLines =
- CommandLines.builder()
- .addCommandLine(javaBuilderCommandLine.build())
- .addCommandLine(
- javaCompileCommandLine,
- ParamFileInfo.builder(ParameterFile.ParameterFileType.UNQUOTED)
- .setCharset(ISO_8859_1)
- .setUseAlways(true)
- .build())
- .build();
- } else {
- if (paramFile == null) {
- paramFile =
- artifactFactory.create(
- ParameterFile.derivePath(outputJar.getRootRelativePath()),
- configuration.getBinDirectory(
- targetLabel.getPackageIdentifier().getRepository()));
- }
- inputsBuilder.add(paramFile);
- javaBuilderCommandLine.addFormatted("@%s", paramFile.getExecPath());
- commandLines = CommandLines.of(javaBuilderCommandLine.build());
- Action parameterFileWriteAction =
- new ParameterFileWriteAction(
- owner,
- paramFile,
- javaCompileCommandLine,
- ParameterFile.ParameterFileType.UNQUOTED,
- ISO_8859_1);
- analysisEnvironment.registerAction(parameterFileWriteAction);
- }
-
- NestedSet<Artifact> inputs = inputsBuilder.build();
- return new JavaCompileAction(
- owner,
- tools,
- inputs,
- outputs,
- commandLines,
- configuration.getCommandLineLimits(),
- javaCompileCommandLine,
- classDirectory,
- outputJar,
- classpathEntries,
- bootclasspathEntries,
- sourcePathEntries,
- extdirInputs,
- plugins.processorClasspath(),
- plugins.processorClasses(),
- sourceJars,
- sourceFiles,
- internedJcopts,
- directJars,
- executionInfo,
- strictJavaDeps,
- fixDepsTool,
- compileTimeDependencyArtifacts,
- getProgressMessage(),
- javaBuilder.getRunfilesSupplier());
- }
-
- private CustomCommandLine buildParamFileContents(Collection<String> javacOpts) {
- checkNotNull(classDirectory, "classDirectory should not be null");
- checkNotNull(tempDirectory, "tempDirectory should not be null");
-
- CustomCommandLine.Builder result = CustomCommandLine.builder();
-
- result.add("--classdir").addPath(classDirectory);
- result.add("--tempdir").addPath(tempDirectory);
- if (outputJar != null) {
- result.addExecPath("--output", outputJar);
- }
- if (nativeHeaderOutput != null) {
- result.addExecPath("--native_header_output", nativeHeaderOutput);
- }
- if (sourceGenDirectory != null) {
- result.add("--sourcegendir").addPath(sourceGenDirectory);
- }
- if (gensrcOutputJar != null) {
- result.addExecPath("--generated_sources_output", gensrcOutputJar);
- }
- if (manifestProtoOutput != null) {
- result.addExecPath("--output_manifest_proto", manifestProtoOutput);
- }
- if (compressJar) {
- result.add("--compress_jar");
- }
- if (outputDepsProto != null) {
- result.addExecPath("--output_deps_proto", outputDepsProto);
- }
- if (!extdirInputs.isEmpty()) {
- result.addExecPaths("--extclasspath", extdirInputs);
- }
- if (!bootclasspathEntries.isEmpty()) {
- result.addExecPaths("--bootclasspath", bootclasspathEntries);
- }
- if (!sourcePathEntries.isEmpty()) {
- result.addExecPaths("--sourcepath", sourcePathEntries);
- }
- result.addExecPaths("--processorpath", plugins.processorClasspath());
- result.addAll("--processors", plugins.processorClasses());
- if (!sourceJars.isEmpty()) {
- result.addExecPaths("--source_jars", ImmutableList.copyOf(sourceJars));
- }
- if (!sourceFiles.isEmpty()) {
- result.addExecPaths("--sources", sourceFiles);
- }
- if (!javacOpts.isEmpty()) {
- result.addAll("--javacopts", ImmutableList.copyOf(javacOpts));
- // terminate --javacopts with `--` to support javac flags that start with `--`
- result.add("--");
- }
- if (targetLabel != null) {
- result.add("--target_label");
- if (targetLabel.getPackageIdentifier().getRepository().isDefault()
- || targetLabel.getPackageIdentifier().getRepository().isMain()) {
- result.addLabel(targetLabel);
- } else {
- // @-prefixed strings will be assumed to be filenames and expanded by
- // {@link JavaLibraryBuildRequest}, so add an extra &at; to escape it.
- result.addPrefixedLabel("@", targetLabel);
- }
- }
- if (injectingRuleKind != null) {
- result.add("--injecting_rule_kind", injectingRuleKind);
- }
-
- if (!classpathEntries.isEmpty()) {
- result.addExecPaths("--classpath", classpathEntries);
- }
-
- // strict_java_deps controls whether the mapping from jars to targets is
- // written out and whether we try to minimize the compile-time classpath.
- if (strictJavaDeps != StrictDepsMode.OFF) {
- result.add("--strict_java_deps", strictJavaDeps.toString());
- result.addExecPaths("--direct_dependencies", directJars);
-
- if (configuration.getFragment(JavaConfiguration.class).getReduceJavaClasspath()
- == JavaClasspathMode.JAVABUILDER) {
- result.add("--reduce_classpath");
-
- if (!compileTimeDependencyArtifacts.isEmpty()) {
- result.addExecPaths("--deps_artifacts", compileTimeDependencyArtifacts);
- }
- }
- }
- result.add("--experimental_fix_deps_tool", fixDepsTool);
-
- // Chose what artifact to pass to JavaBuilder, as input to jacoco instrumentation processor.
- // metadata should be null when --experimental_java_coverage is true.
- Artifact coverageArtifact = metadata != null ? metadata : artifactForExperimentalCoverage;
- if (coverageArtifact != null) {
- result.add("--post_processor");
- result.addExecPath(JACOCO_INSTRUMENTATION_PROCESSOR, coverageArtifact);
- result.addPath(
- configuration
- .getCoverageMetadataDirectory(targetLabel.getPackageIdentifier().getRepository())
- .getExecPath());
- result.add("-*Test");
- result.add("-*TestCase");
- }
- return result.build();
- }
-
- private LazyString getProgressMessage() {
- Artifact outputJar = this.outputJar;
- int sourceFileCount = sourceFiles.size();
- int sourceJarCount = sourceJars.size();
- String annotationProcessorNames = getProcessorNames();
- return new LazyString() {
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder("Building ");
- sb.append(outputJar.prettyPrint());
- sb.append(" (");
- boolean first = true;
- first = appendCount(sb, first, sourceFileCount, "source file");
- first = appendCount(sb, first, sourceJarCount, "source jar");
- sb.append(")");
- sb.append(annotationProcessorNames);
- return sb.toString();
- }
- };
- }
-
- private String getProcessorNames() {
- if (plugins.processorClasses().isEmpty()) {
- return "";
- }
- StringBuilder sb = new StringBuilder();
- List<String> shortNames = new ArrayList<>();
- for (String name : plugins.processorClasses()) {
- // Annotation processor names are qualified class names. Omit the package part for the
- // progress message, e.g. `com.google.Foo` -> `Foo`.
- int idx = name.lastIndexOf('.');
- String shortName = idx != -1 ? name.substring(idx + 1) : name;
- shortNames.add(shortName);
- }
- sb.append(" and running annotation processors (");
- Joiner.on(", ").appendTo(sb, shortNames);
- sb.append(")");
- return sb.toString();
- }
-
- /**
- * Append an input count to the progress message, e.g. "2 source jars". If an input count has
- * already been appended, prefix with ", ".
- */
- private static boolean appendCount(StringBuilder sb, boolean first, int count, String name) {
- if (count > 0) {
- if (!first) {
- sb.append(", ");
- } else {
- first = false;
- }
- sb.append(count).append(' ').append(name);
- if (count > 1) {
- sb.append('s');
- }
- }
- return first;
- }
-
- public Builder setJavaExecutable(PathFragment javaExecutable) {
- this.javaExecutable = javaExecutable;
- return this;
- }
-
- public Builder setJavaBaseInputs(Iterable<Artifact> javabaseInputs) {
- this.javabaseInputs = ImmutableList.copyOf(javabaseInputs);
- return this;
- }
-
- public Builder setOutputJar(Artifact outputJar) {
- this.outputJar = outputJar;
- return this;
- }
-
- public Builder setNativeHeaderOutput(Artifact nativeHeaderOutput) {
- this.nativeHeaderOutput = nativeHeaderOutput;
- return this;
- }
-
- public Builder setGensrcOutputJar(Artifact gensrcOutputJar) {
- this.gensrcOutputJar = gensrcOutputJar;
- return this;
- }
-
- public Builder setManifestProtoOutput(Artifact manifestProtoOutput) {
- this.manifestProtoOutput = manifestProtoOutput;
- return this;
- }
-
- public Builder setOutputDepsProto(Artifact outputDepsProto) {
- this.outputDepsProto = outputDepsProto;
- return this;
- }
-
- public Builder setAdditionalOutputs(Collection<Artifact> outputs) {
- this.additionalOutputs = outputs;
- return this;
- }
-
- public Builder setMetadata(Artifact metadata) {
- this.metadata = metadata;
- return this;
- }
-
- public Builder setSourceFiles(ImmutableSet<Artifact> sourceFiles) {
- this.sourceFiles = sourceFiles;
- return this;
- }
-
- public Builder addSourceJars(Collection<Artifact> sourceJars) {
- this.sourceJars.addAll(sourceJars);
- return this;
- }
-
- /**
- * Sets the strictness of Java dependency checking, see {@link
- * com.google.devtools.build.lib.analysis.config.StrictDepsMode}.
- *
- * <p>Defaults to {@link StrictDepsMode#ERROR}.
- */
- public Builder setStrictJavaDeps(StrictDepsMode strictDeps) {
- strictJavaDeps = strictDeps;
- return this;
- }
-
- /** Sets the tool with which to fix dependency errors. */
- public Builder setFixDepsTool(String depsTool) {
- fixDepsTool = depsTool;
- return this;
- }
-
- /** Accumulates the given jar artifacts as being provided by direct dependencies. */
- public Builder setDirectJars(NestedSet<Artifact> directJars) {
- this.directJars = checkNotNull(directJars, "directJars must not be null");
- return this;
- }
-
- public Builder setCompileTimeDependencyArtifacts(NestedSet<Artifact> dependencyArtifacts) {
- checkNotNull(compileTimeDependencyArtifacts, "dependencyArtifacts must not be null");
- this.compileTimeDependencyArtifacts = dependencyArtifacts;
- return this;
- }
-
- public Builder setJavacOpts(Iterable<String> copts) {
- this.javacOpts = ImmutableList.copyOf(copts);
- return this;
- }
-
- public Builder setJavacJvmOpts(ImmutableList<String> opts) {
- this.javacJvmOpts = opts;
- return this;
- }
-
- public Builder setJavacExecutionInfo(ImmutableMap<String, String> executionInfo) {
- this.executionInfo = executionInfo;
- return this;
- }
-
- public Builder setCompressJar(boolean compressJar) {
- this.compressJar = compressJar;
- return this;
- }
-
- public Builder setClasspathEntries(NestedSet<Artifact> classpathEntries) {
- this.classpathEntries = classpathEntries;
- return this;
- }
-
- public Builder setBootclasspathEntries(Iterable<Artifact> bootclasspathEntries) {
- this.bootclasspathEntries = ImmutableList.copyOf(bootclasspathEntries);
- return this;
- }
-
- public Builder setSourcePathEntries(Iterable<Artifact> sourcePathEntries) {
- this.sourcePathEntries = ImmutableList.copyOf(sourcePathEntries);
- return this;
- }
-
- public Builder setExtdirInputs(Iterable<Artifact> extdirEntries) {
- this.extdirInputs = ImmutableList.copyOf(extdirEntries);
- return this;
- }
-
- /**
- * Sets the directory where source files generated by annotation processors should be stored.
- */
- public Builder setSourceGenDirectory(PathFragment sourceGenDirectory) {
- this.sourceGenDirectory = sourceGenDirectory;
- return this;
- }
-
- public Builder setTempDirectory(PathFragment tempDirectory) {
- this.tempDirectory = tempDirectory;
- return this;
- }
-
- public Builder setClassDirectory(PathFragment classDirectory) {
- this.classDirectory = classDirectory;
- return this;
- }
-
- public Builder setPlugins(JavaPluginInfo plugins) {
- checkNotNull(plugins, "plugins must not be null");
- checkState(this.plugins.isEmpty());
- this.plugins = plugins;
- return this;
- }
-
- public void setExtraData(NestedSet<Artifact> extraData) {
- checkNotNull(extraData, "extraData must not be null");
- checkState(this.extraData.isEmpty());
- this.extraData = extraData;
- }
-
- public Builder setLangtoolsJar(Artifact langtoolsJar) {
- this.langtoolsJar = langtoolsJar;
- return this;
- }
-
- /** Sets the tools jars. */
- public Builder setToolsJars(NestedSet<Artifact> toolsJars) {
- checkNotNull(toolsJars, "toolsJars must not be null");
- this.toolsJars = toolsJars;
- return this;
- }
-
- public Builder setJavaBuilder(FilesToRunProvider javaBuilder) {
- this.javaBuilder = javaBuilder;
- return this;
- }
-
- public Builder setInstrumentationJars(Iterable<Artifact> instrumentationJars) {
- this.instrumentationJars = ImmutableList.copyOf(instrumentationJars);
- return this;
- }
-
- public Builder setArtifactForExperimentalCoverage(Artifact artifactForExperimentalCoverage) {
- this.artifactForExperimentalCoverage = artifactForExperimentalCoverage;
- return this;
- }
-
- public Builder setTargetLabel(Label targetLabel) {
- this.targetLabel = targetLabel;
- return this;
- }
-
- public Builder setInjectingRuleKind(@Nullable String injectingRuleKind) {
- this.injectingRuleKind = injectingRuleKind;
- return this;
- }
- }
-}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileActionBuilder.java
new file mode 100644
index 0000000..8f0fc23
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileActionBuilder.java
@@ -0,0 +1,714 @@
+// 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.lib.rules.java;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.ImmutableList.toImmutableList;
+import static java.nio.charset.StandardCharsets.ISO_8859_1;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
+import com.google.devtools.build.lib.actions.ActionEnvironment;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandLineExpansionException;
+import com.google.devtools.build.lib.actions.CommandLines;
+import com.google.devtools.build.lib.actions.ParamFileInfo;
+import com.google.devtools.build.lib.actions.ParameterFile;
+import com.google.devtools.build.lib.actions.ResourceSet;
+import com.google.devtools.build.lib.actions.extra.ExtraActionInfo;
+import com.google.devtools.build.lib.actions.extra.JavaCompileInfo;
+import com.google.devtools.build.lib.analysis.FilesToRunProvider;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
+import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorArg;
+import com.google.devtools.build.lib.analysis.actions.LazyWritePathsFileAction;
+import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction.ExtraActionInfoSupplier;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration.StrictDepsMode;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
+import com.google.devtools.build.lib.rules.java.JavaConfiguration.JavaClasspathMode;
+import com.google.devtools.build.lib.rules.java.JavaPluginInfoProvider.JavaPluginInfo;
+import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
+import com.google.devtools.build.lib.util.LazyString;
+import com.google.devtools.build.lib.util.StringCanonicalizer;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Stream;
+import javax.annotation.Nullable;
+
+/** Java compilation action builder. */
+public final class JavaCompileActionBuilder {
+
+ private static final String JACOCO_INSTRUMENTATION_PROCESSOR = "jacoco";
+
+ private static final ResourceSet LOCAL_RESOURCES =
+ ResourceSet.createWithRamCpuIo(750 /*MB*/, 0.5 /*CPU*/, 0.0 /*IO*/);
+
+ /** Environment variable that sets the UTF-8 charset. */
+ static final ImmutableMap<String, String> UTF8_ENVIRONMENT =
+ ImmutableMap.of("LC_CTYPE", "en_US.UTF-8");
+
+ // TODO(#3320): This is missing the configuration's action environment!
+ static final ActionEnvironment UTF8_ACTION_ENVIRONMENT =
+ ActionEnvironment.create(UTF8_ENVIRONMENT);
+
+ static final String MNEMONIC = "Javac";
+
+ /** Returns true if this is a Java compile action. */
+ public static boolean isJavaCompileAction(ActionAnalysisMetadata action) {
+ return action != null && action.getMnemonic().equals(MNEMONIC);
+ }
+
+ @ThreadCompatible
+ @Immutable
+ @AutoCodec
+ static class JavaCompileExtraActionInfoSupplier implements ExtraActionInfoSupplier {
+
+ private final Artifact outputJar;
+
+ /** The list of classpath entries to specify to javac. */
+ private final NestedSet<Artifact> classpathEntries;
+
+ /** The list of bootclasspath entries to specify to javac. */
+ private final ImmutableList<Artifact> bootclasspathEntries;
+
+ /** The list of classpath entries to search for annotation processors. */
+ private final NestedSet<Artifact> processorPath;
+
+ /** The list of annotation processor classes to run. */
+ private final NestedSet<String> processorNames;
+
+ /** Set of additional Java source files to compile. */
+ private final ImmutableList<Artifact> sourceJars;
+
+ /** The set of explicit Java source files to compile. */
+ private final ImmutableSet<Artifact> sourceFiles;
+
+ /** The compiler options to pass to javac. */
+ private final ImmutableList<String> javacOpts;
+
+ private CommandLines commandLines;
+
+ JavaCompileExtraActionInfoSupplier(
+ Artifact outputJar,
+ NestedSet<Artifact> classpathEntries,
+ ImmutableList<Artifact> bootclasspathEntries,
+ NestedSet<Artifact> processorPath,
+ NestedSet<String> processorNames,
+ ImmutableList<Artifact> sourceJars,
+ ImmutableSet<Artifact> sourceFiles,
+ ImmutableList<String> javacOpts,
+ CommandLines commandLines) {
+ this.outputJar = outputJar;
+ this.classpathEntries = classpathEntries;
+ this.bootclasspathEntries = bootclasspathEntries;
+ this.processorPath = processorPath;
+ this.processorNames = processorNames;
+ this.sourceJars = sourceJars;
+ this.sourceFiles = sourceFiles;
+ this.javacOpts = javacOpts;
+ this.commandLines = commandLines;
+ }
+
+ @Override
+ public void extend(ExtraActionInfo.Builder builder) {
+ JavaCompileInfo.Builder info = JavaCompileInfo.newBuilder();
+ info.addAllSourceFile(Artifact.toExecPaths(sourceFiles));
+ info.addAllClasspath(Artifact.toExecPaths(classpathEntries));
+ info.addAllBootclasspath(Artifact.toExecPaths(bootclasspathEntries));
+ info.addAllSourcepath(Artifact.toExecPaths(sourceJars));
+ info.addAllJavacOpt(javacOpts);
+ info.addAllProcessor(processorNames);
+ info.addAllProcessorpath(Artifact.toExecPaths(processorPath));
+ info.setOutputjar(outputJar.getExecPathString());
+ try {
+ info.addAllArgument(commandLines.allArguments());
+ } catch (CommandLineExpansionException e) {
+ throw new AssertionError("JavaCompileAction command line expansion cannot fail", e);
+ }
+ builder.setExtension(JavaCompileInfo.javaCompileInfo, info.build());
+ }
+ }
+
+ private PathFragment javaExecutable;
+ private List<Artifact> javabaseInputs = ImmutableList.of();
+ private Artifact outputJar;
+ private Artifact nativeHeaderOutput;
+ private Artifact gensrcOutputJar;
+ private Artifact manifestProtoOutput;
+ private Artifact outputDepsProto;
+ private Collection<Artifact> additionalOutputs;
+ private Artifact paramFile;
+ private Artifact metadata;
+ private Artifact artifactForExperimentalCoverage;
+ private ImmutableSet<Artifact> sourceFiles = ImmutableSet.of();
+ private ImmutableList<Artifact> sourceJars = ImmutableList.of();
+ private StrictDepsMode strictJavaDeps = StrictDepsMode.ERROR;
+ private String fixDepsTool = "add_dep";
+ private NestedSet<Artifact> directJars = NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
+ private NestedSet<Artifact> compileTimeDependencyArtifacts =
+ NestedSetBuilder.emptySet(Order.STABLE_ORDER);
+ private List<String> javacOpts = new ArrayList<>();
+ private ImmutableList<String> javacJvmOpts = ImmutableList.of();
+ private ImmutableMap<String, String> executionInfo = ImmutableMap.of();
+ private boolean compressJar;
+ private NestedSet<Artifact> classpathEntries = NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
+ private ImmutableList<Artifact> bootclasspathEntries = ImmutableList.of();
+ private ImmutableList<Artifact> sourcePathEntries = ImmutableList.of();
+ private ImmutableList<Artifact> extdirInputs = ImmutableList.of();
+ private FilesToRunProvider javaBuilder;
+ private Artifact langtoolsJar;
+ private NestedSet<Artifact> toolsJars = NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
+ private ImmutableList<Artifact> instrumentationJars = ImmutableList.of();
+ private PathFragment sourceGenDirectory;
+ private PathFragment tempDirectory;
+ private PathFragment classDirectory;
+ private JavaPluginInfo plugins = JavaPluginInfo.empty();
+ private NestedSet<Artifact> extraData = NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
+ private Label targetLabel;
+ @Nullable private String injectingRuleKind;
+
+ public SpawnAction build(RuleContext ruleContext, JavaSemantics javaSemantics) {
+ // TODO(bazel-team): all the params should be calculated before getting here, and the various
+ // aggregation code below should go away.
+ final String pathSeparator = ruleContext.getConfiguration().getHostPathSeparator();
+ ImmutableList<String> internedJcopts =
+ javacOpts.stream().map(StringCanonicalizer::intern).collect(toImmutableList());
+
+ // Invariant: if strictJavaDeps is OFF, then directJars and
+ // dependencyArtifacts are ignored
+ if (strictJavaDeps == StrictDepsMode.OFF) {
+ directJars = NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
+ compileTimeDependencyArtifacts = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
+ }
+
+ // Invariant: if java_classpath is set to 'off', dependencyArtifacts are ignored
+ JavaConfiguration javaConfiguration =
+ ruleContext.getConfiguration().getFragment(JavaConfiguration.class);
+ if (javaConfiguration.getReduceJavaClasspath() == JavaClasspathMode.OFF) {
+ compileTimeDependencyArtifacts = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
+ }
+
+ Preconditions.checkState(javaExecutable != null, ruleContext.getActionOwner());
+
+ ImmutableList.Builder<Artifact> outputsBuilder = ImmutableList.<Artifact>builder();
+ Stream.of(
+ outputJar,
+ metadata,
+ gensrcOutputJar,
+ manifestProtoOutput,
+ outputDepsProto,
+ nativeHeaderOutput)
+ .filter(x -> x != null)
+ .forEachOrdered(outputsBuilder::add);
+ if (additionalOutputs != null) {
+ outputsBuilder.addAll(additionalOutputs);
+ }
+ ImmutableList<Artifact> outputs = outputsBuilder.build();
+
+ // The actual params-file-based command line executed for a compile action.
+ CustomCommandLine.Builder javaBuilderCommandLine = CustomCommandLine.builder();
+ Artifact javaBuilderJar = checkNotNull(javaBuilder.getExecutable());
+ if (!javaBuilderJar.getExtension().equals("jar")) {
+ // JavaBuilder is a non-deploy.jar executable.
+ javaBuilderCommandLine.addExecPath(javaBuilderJar);
+ } else {
+ javaBuilderCommandLine.addPath(javaExecutable).addAll(javacJvmOpts);
+ if (!instrumentationJars.isEmpty()) {
+ javaBuilderCommandLine
+ .addExecPaths(
+ "-cp",
+ VectorArg.join(pathSeparator)
+ .each(
+ ImmutableList.<Artifact>builder()
+ .addAll(instrumentationJars)
+ .add(javaBuilderJar)
+ .build()))
+ .addDynamicString(javaSemantics.getJavaBuilderMainClass());
+ } else {
+ // If there are no instrumentation jars, use simpler '-jar' option to launch JavaBuilder.
+ javaBuilderCommandLine.addExecPath("-jar", javaBuilderJar);
+ }
+ }
+
+ if (artifactForExperimentalCoverage != null) {
+ ruleContext.registerAction(
+ new LazyWritePathsFileAction(
+ ruleContext.getActionOwner(), artifactForExperimentalCoverage, sourceFiles, false));
+ }
+
+ NestedSet<Artifact> tools =
+ NestedSetBuilder.<Artifact>stableOrder()
+ .add(langtoolsJar)
+ .addTransitive(toolsJars)
+ .addTransitive(javaBuilder.getFilesToRun())
+ .addAll(instrumentationJars)
+ .build();
+
+ NestedSetBuilder<Artifact> inputsBuilder =
+ NestedSetBuilder.<Artifact>stableOrder()
+ .addTransitive(classpathEntries)
+ .addTransitive(compileTimeDependencyArtifacts)
+ .addTransitive(plugins.processorClasspath())
+ .addTransitive(plugins.data())
+ .addTransitive(extraData)
+ .addAll(sourceJars)
+ .addAll(sourceFiles)
+ .addAll(javabaseInputs)
+ .addAll(bootclasspathEntries)
+ .addAll(sourcePathEntries)
+ .addAll(extdirInputs)
+ .addTransitive(tools);
+ if (artifactForExperimentalCoverage != null) {
+ inputsBuilder.add(artifactForExperimentalCoverage);
+ }
+
+ final CommandLines commandLines;
+ CustomCommandLine javaCompileCommandLine =
+ buildParamFileContents(ruleContext.getConfiguration(), internedJcopts);
+ if (ruleContext.getConfiguration().deferParamFiles()) {
+ commandLines =
+ CommandLines.builder()
+ .addCommandLine(javaBuilderCommandLine.build())
+ .addCommandLine(
+ javaCompileCommandLine,
+ ParamFileInfo.builder(ParameterFile.ParameterFileType.UNQUOTED)
+ .setCharset(ISO_8859_1)
+ .setUseAlways(true)
+ .build())
+ .build();
+ } else {
+ if (paramFile == null) {
+ paramFile =
+ ruleContext.getDerivedArtifact(
+ ParameterFile.derivePath(outputJar.getRootRelativePath()),
+ ruleContext
+ .getConfiguration()
+ .getBinDirectory(targetLabel.getPackageIdentifier().getRepository()));
+ }
+ inputsBuilder.add(paramFile);
+ javaBuilderCommandLine.addFormatted("@%s", paramFile.getExecPath());
+ commandLines = CommandLines.of(javaBuilderCommandLine.build());
+ Action parameterFileWriteAction =
+ new ParameterFileWriteAction(
+ ruleContext.getActionOwner(),
+ paramFile,
+ javaCompileCommandLine,
+ ParameterFile.ParameterFileType.UNQUOTED,
+ ISO_8859_1);
+ ruleContext.registerAction(parameterFileWriteAction);
+ }
+
+ NestedSet<Artifact> inputs = inputsBuilder.build();
+
+ return new SpawnAction(
+ ruleContext.getActionOwner(),
+ tools,
+ inputs,
+ outputs,
+ outputJar,
+ LOCAL_RESOURCES,
+ commandLines,
+ ruleContext.getConfiguration().getCommandLineLimits(),
+ /* isShellCommand= */ false,
+ // TODO(#3320): This is missing the configuration's action environment!
+ UTF8_ACTION_ENVIRONMENT,
+ ImmutableMap.copyOf(executionInfo),
+ getProgressMessage(),
+ javaBuilder.getRunfilesSupplier(),
+ MNEMONIC,
+ /* executeUnconditionally= */ false,
+ /* extraActionInfoSupplier= */ new JavaCompileExtraActionInfoSupplier(
+ outputJar,
+ classpathEntries,
+ bootclasspathEntries,
+ plugins.processorClasspath(),
+ plugins.processorClasses(),
+ sourceJars,
+ sourceFiles,
+ internedJcopts,
+ commandLines));
+ }
+
+ private CustomCommandLine buildParamFileContents(
+ BuildConfiguration configuration, Collection<String> javacOpts) {
+ checkNotNull(classDirectory, "classDirectory should not be null");
+ checkNotNull(tempDirectory, "tempDirectory should not be null");
+
+ CustomCommandLine.Builder result = CustomCommandLine.builder();
+
+ result.add("--classdir").addPath(classDirectory);
+ result.add("--tempdir").addPath(tempDirectory);
+ if (outputJar != null) {
+ result.addExecPath("--output", outputJar);
+ }
+ if (nativeHeaderOutput != null) {
+ result.addExecPath("--native_header_output", nativeHeaderOutput);
+ }
+ if (sourceGenDirectory != null) {
+ result.add("--sourcegendir").addPath(sourceGenDirectory);
+ }
+ if (gensrcOutputJar != null) {
+ result.addExecPath("--generated_sources_output", gensrcOutputJar);
+ }
+ if (manifestProtoOutput != null) {
+ result.addExecPath("--output_manifest_proto", manifestProtoOutput);
+ }
+ if (compressJar) {
+ result.add("--compress_jar");
+ }
+ if (outputDepsProto != null) {
+ result.addExecPath("--output_deps_proto", outputDepsProto);
+ }
+ if (!extdirInputs.isEmpty()) {
+ result.addExecPaths("--extclasspath", extdirInputs);
+ }
+ if (!bootclasspathEntries.isEmpty()) {
+ result.addExecPaths("--bootclasspath", bootclasspathEntries);
+ }
+ if (!sourcePathEntries.isEmpty()) {
+ result.addExecPaths("--sourcepath", sourcePathEntries);
+ }
+ result.addExecPaths("--processorpath", plugins.processorClasspath());
+ result.addAll("--processors", plugins.processorClasses());
+ if (!sourceJars.isEmpty()) {
+ result.addExecPaths("--source_jars", ImmutableList.copyOf(sourceJars));
+ }
+ if (!sourceFiles.isEmpty()) {
+ result.addExecPaths("--sources", sourceFiles);
+ }
+ if (!javacOpts.isEmpty()) {
+ result.addAll("--javacopts", ImmutableList.copyOf(javacOpts));
+ // terminate --javacopts with `--` to support javac flags that start with `--`
+ result.add("--");
+ }
+ if (targetLabel != null) {
+ result.add("--target_label");
+ if (targetLabel.getPackageIdentifier().getRepository().isDefault()
+ || targetLabel.getPackageIdentifier().getRepository().isMain()) {
+ result.addLabel(targetLabel);
+ } else {
+ // @-prefixed strings will be assumed to be filenames and expanded by
+ // {@link JavaLibraryBuildRequest}, so add an extra &at; to escape it.
+ result.addPrefixedLabel("@", targetLabel);
+ }
+ }
+ if (injectingRuleKind != null) {
+ result.add("--injecting_rule_kind", injectingRuleKind);
+ }
+
+ if (!classpathEntries.isEmpty()) {
+ result.addExecPaths("--classpath", classpathEntries);
+ }
+
+ // strict_java_deps controls whether the mapping from jars to targets is
+ // written out and whether we try to minimize the compile-time classpath.
+ if (strictJavaDeps != StrictDepsMode.OFF) {
+ result.add("--strict_java_deps", strictJavaDeps.toString());
+ result.addExecPaths("--direct_dependencies", directJars);
+
+ if (configuration.getFragment(JavaConfiguration.class).getReduceJavaClasspath()
+ == JavaClasspathMode.JAVABUILDER) {
+ result.add("--reduce_classpath");
+
+ if (!compileTimeDependencyArtifacts.isEmpty()) {
+ result.addExecPaths("--deps_artifacts", compileTimeDependencyArtifacts);
+ }
+ }
+ }
+ result.add("--experimental_fix_deps_tool", fixDepsTool);
+
+ // Chose what artifact to pass to JavaBuilder, as input to jacoco instrumentation processor.
+ // metadata should be null when --experimental_java_coverage is true.
+ Artifact coverageArtifact = metadata != null ? metadata : artifactForExperimentalCoverage;
+ if (coverageArtifact != null) {
+ result.add("--post_processor");
+ result.addExecPath(JACOCO_INSTRUMENTATION_PROCESSOR, coverageArtifact);
+ result.addPath(
+ configuration
+ .getCoverageMetadataDirectory(targetLabel.getPackageIdentifier().getRepository())
+ .getExecPath());
+ result.add("-*Test");
+ result.add("-*TestCase");
+ }
+ return result.build();
+ }
+
+ private LazyString getProgressMessage() {
+ Artifact outputJar = this.outputJar;
+ int sourceFileCount = sourceFiles.size();
+ int sourceJarCount = sourceJars.size();
+ String annotationProcessorNames = getProcessorNames();
+ return new LazyString() {
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("Building ");
+ sb.append(outputJar.prettyPrint());
+ sb.append(" (");
+ boolean first = true;
+ first = appendCount(sb, first, sourceFileCount, "source file");
+ first = appendCount(sb, first, sourceJarCount, "source jar");
+ sb.append(")");
+ sb.append(annotationProcessorNames);
+ return sb.toString();
+ }
+ };
+ }
+
+ private String getProcessorNames() {
+ if (plugins.processorClasses().isEmpty()) {
+ return "";
+ }
+ StringBuilder sb = new StringBuilder();
+ List<String> shortNames = new ArrayList<>();
+ for (String name : plugins.processorClasses()) {
+ // Annotation processor names are qualified class names. Omit the package part for the
+ // progress message, e.g. `com.google.Foo` -> `Foo`.
+ int idx = name.lastIndexOf('.');
+ String shortName = idx != -1 ? name.substring(idx + 1) : name;
+ shortNames.add(shortName);
+ }
+ sb.append(" and running annotation processors (");
+ Joiner.on(", ").appendTo(sb, shortNames);
+ sb.append(")");
+ return sb.toString();
+ }
+
+ /**
+ * Append an input count to the progress message, e.g. "2 source jars". If an input count has
+ * already been appended, prefix with ", ".
+ */
+ private static boolean appendCount(StringBuilder sb, boolean first, int count, String name) {
+ if (count > 0) {
+ if (!first) {
+ sb.append(", ");
+ } else {
+ first = false;
+ }
+ sb.append(count).append(' ').append(name);
+ if (count > 1) {
+ sb.append('s');
+ }
+ }
+ return first;
+ }
+
+ public JavaCompileActionBuilder setJavaExecutable(PathFragment javaExecutable) {
+ this.javaExecutable = javaExecutable;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setJavaBaseInputs(Iterable<Artifact> javabaseInputs) {
+ this.javabaseInputs = ImmutableList.copyOf(javabaseInputs);
+ return this;
+ }
+
+ public JavaCompileActionBuilder setOutputJar(Artifact outputJar) {
+ this.outputJar = outputJar;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setNativeHeaderOutput(Artifact nativeHeaderOutput) {
+ this.nativeHeaderOutput = nativeHeaderOutput;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setGensrcOutputJar(Artifact gensrcOutputJar) {
+ this.gensrcOutputJar = gensrcOutputJar;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setManifestProtoOutput(Artifact manifestProtoOutput) {
+ this.manifestProtoOutput = manifestProtoOutput;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setOutputDepsProto(Artifact outputDepsProto) {
+ this.outputDepsProto = outputDepsProto;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setAdditionalOutputs(Collection<Artifact> outputs) {
+ this.additionalOutputs = outputs;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setMetadata(Artifact metadata) {
+ this.metadata = metadata;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setSourceFiles(ImmutableSet<Artifact> sourceFiles) {
+ this.sourceFiles = sourceFiles;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setSourceJars(ImmutableList<Artifact> sourceJars) {
+ checkState(this.sourceJars.isEmpty());
+ this.sourceJars = checkNotNull(sourceJars, "sourceJars must not be null");
+ return this;
+ }
+
+ /**
+ * Sets the strictness of Java dependency checking, see {@link
+ * com.google.devtools.build.lib.analysis.config.BuildConfiguration.StrictDepsMode}.
+ */
+ public JavaCompileActionBuilder setStrictJavaDeps(StrictDepsMode strictDeps) {
+ strictJavaDeps = strictDeps;
+ return this;
+ }
+
+ /** Sets the tool with which to fix dependency errors. */
+ public JavaCompileActionBuilder setFixDepsTool(String depsTool) {
+ fixDepsTool = depsTool;
+ return this;
+ }
+
+ /** Accumulates the given jar artifacts as being provided by direct dependencies. */
+ public JavaCompileActionBuilder setDirectJars(NestedSet<Artifact> directJars) {
+ this.directJars = checkNotNull(directJars, "directJars must not be null");
+ return this;
+ }
+
+ public JavaCompileActionBuilder setCompileTimeDependencyArtifacts(
+ NestedSet<Artifact> dependencyArtifacts) {
+ checkNotNull(compileTimeDependencyArtifacts, "dependencyArtifacts must not be null");
+ this.compileTimeDependencyArtifacts = dependencyArtifacts;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setJavacOpts(Iterable<String> copts) {
+ this.javacOpts = ImmutableList.copyOf(copts);
+ return this;
+ }
+
+ public JavaCompileActionBuilder setJavacJvmOpts(ImmutableList<String> opts) {
+ this.javacJvmOpts = opts;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setJavacExecutionInfo(
+ ImmutableMap<String, String> executionInfo) {
+ this.executionInfo = executionInfo;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setCompressJar(boolean compressJar) {
+ this.compressJar = compressJar;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setClasspathEntries(NestedSet<Artifact> classpathEntries) {
+ this.classpathEntries = classpathEntries;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setBootclasspathEntries(Iterable<Artifact> bootclasspathEntries) {
+ this.bootclasspathEntries = ImmutableList.copyOf(bootclasspathEntries);
+ return this;
+ }
+
+ public JavaCompileActionBuilder setSourcePathEntries(Iterable<Artifact> sourcePathEntries) {
+ this.sourcePathEntries = ImmutableList.copyOf(sourcePathEntries);
+ return this;
+ }
+
+ public JavaCompileActionBuilder setExtdirInputs(Iterable<Artifact> extdirEntries) {
+ this.extdirInputs = ImmutableList.copyOf(extdirEntries);
+ return this;
+ }
+
+ /** Sets the directory where source files generated by annotation processors should be stored. */
+ public JavaCompileActionBuilder setSourceGenDirectory(PathFragment sourceGenDirectory) {
+ this.sourceGenDirectory = sourceGenDirectory;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setTempDirectory(PathFragment tempDirectory) {
+ this.tempDirectory = tempDirectory;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setClassDirectory(PathFragment classDirectory) {
+ this.classDirectory = classDirectory;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setPlugins(JavaPluginInfo plugins) {
+ checkNotNull(plugins, "plugins must not be null");
+ checkState(this.plugins.isEmpty());
+ this.plugins = plugins;
+ return this;
+ }
+
+ public void setExtraData(NestedSet<Artifact> extraData) {
+ checkNotNull(extraData, "extraData must not be null");
+ checkState(this.extraData.isEmpty());
+ this.extraData = extraData;
+ }
+
+ public JavaCompileActionBuilder setLangtoolsJar(Artifact langtoolsJar) {
+ this.langtoolsJar = langtoolsJar;
+ return this;
+ }
+
+ /** Sets the tools jars. */
+ public JavaCompileActionBuilder setToolsJars(NestedSet<Artifact> toolsJars) {
+ checkNotNull(toolsJars, "toolsJars must not be null");
+ this.toolsJars = toolsJars;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setJavaBuilder(FilesToRunProvider javaBuilder) {
+ this.javaBuilder = javaBuilder;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setInstrumentationJars(Iterable<Artifact> instrumentationJars) {
+ this.instrumentationJars = ImmutableList.copyOf(instrumentationJars);
+ return this;
+ }
+
+ public JavaCompileActionBuilder setArtifactForExperimentalCoverage(
+ Artifact artifactForExperimentalCoverage) {
+ this.artifactForExperimentalCoverage = artifactForExperimentalCoverage;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setTargetLabel(Label targetLabel) {
+ this.targetLabel = targetLabel;
+ return this;
+ }
+
+ public JavaCompileActionBuilder setInjectingRuleKind(@Nullable String injectingRuleKind) {
+ this.injectingRuleKind = injectingRuleKind;
+ return this;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaHeaderCompileActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaHeaderCompileActionBuilder.java
index 56b371d..d89836b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaHeaderCompileActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaHeaderCompileActionBuilder.java
@@ -230,7 +230,7 @@
SpawnAction.Builder builder = new SpawnAction.Builder();
- builder.setEnvironment(JavaCompileAction.UTF8_ENVIRONMENT);
+ builder.setEnvironment(JavaCompileActionBuilder.UTF8_ENVIRONMENT);
builder.setProgressMessage(
new ProgressMessage(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaTargetAttributes.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaTargetAttributes.java
index e16ac33..ec8ee88 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaTargetAttributes.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaTargetAttributes.java
@@ -481,7 +481,7 @@
return compileTimeDependencyArtifacts;
}
- public List<Artifact> getSourceJars() {
+ public ImmutableList<Artifact> getSourceJars() {
return sourceJars;
}