aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java11
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/DataBinding.java189
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/databinding_annotation_template.txt14
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java32
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaHeaderCompileAction.java12
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaTargetAttributes.java26
7 files changed, 196 insertions, 92 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
index 91a43c0171..3f1b60998c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
@@ -529,7 +529,7 @@ public class AndroidCommon {
androidSemantics.getJavacArguments(ruleContext))
.setBootClassPath(bootclasspath);
if (DataBinding.isEnabled(ruleContext)) {
- DataBinding.addAnnotationProcessor(ruleContext, attributes);
+ DataBinding.addAnnotationProcessor(ruleContext, attributes, isBinary);
}
JavaCompilationArtifacts.Builder artifactsBuilder = new JavaCompilationArtifacts.Builder();
@@ -589,7 +589,7 @@ public class AndroidCommon {
JavaCompilationHelper helper = new JavaCompilationHelper(ruleContext, semantics,
javaCommon.getJavacOpts(), attributes,
DataBinding.isEnabled(ruleContext)
- ? DataBinding.processDeps(ruleContext, attributes) : ImmutableList.<Artifact>of());
+ ? DataBinding.processDeps(ruleContext) : ImmutableList.<Artifact>of());
helper.addLibrariesToAttributes(javaCommon.targetsTreatedAsDeps(ClasspathType.COMPILE_ONLY));
attributes.setRuleKind(ruleContext.getRule().getRuleClass());
@@ -905,8 +905,11 @@ public class AndroidCommon {
// Add this rule's annotation processor input if this rule has direct resources. If it
// doesn't have direct resources, it doesn't produce data binding output so there's no
// input for the annotation processor.
- srcs = ImmutableList.<Artifact>builder().addAll(srcs)
- .add(DataBinding.createAnnotationFile(ruleContext, isLibrary)).build();
+ Artifact annotationFile = DataBinding.createAnnotationFile(ruleContext, isLibrary);
+ if (annotationFile != null) {
+ srcs = ImmutableList.<Artifact>builder().addAll(srcs)
+ .add(DataBinding.createAnnotationFile(ruleContext, isLibrary)).build();
+ }
}
ImmutableList<TransitiveInfoCollection> compileDeps;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/DataBinding.java b/src/main/java/com/google/devtools/build/lib/rules/android/DataBinding.java
index 9c9c3882ac..a66d4b186c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/DataBinding.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/DataBinding.java
@@ -20,14 +20,17 @@ import com.google.devtools.build.lib.analysis.RuleConfiguredTarget;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
-import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction;
-import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Substitution;
-import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Template;
+import com.google.devtools.build.lib.analysis.actions.FileWriteAction;
+import com.google.devtools.build.lib.analysis.actions.SymlinkAction;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.rules.java.JavaPluginInfoProvider;
import com.google.devtools.build.lib.rules.java.JavaTargetAttributes;
import com.google.devtools.build.lib.syntax.Type;
+import com.google.devtools.build.lib.util.ResourceFileLoader;
+import com.google.devtools.build.lib.vfs.PathFragment;
+
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -70,6 +73,23 @@ public final class DataBinding {
"$databinding_annotation_processor";
/**
+ * Annotation processing creates the following metadata files that describe how data binding is
+ * applied. The full file paths include prefixes as implemented in {@link #getMetadataOutputs}.
+ */
+ private static final ImmutableList<String> METADATA_OUTPUT_SUFFIXES = ImmutableList.<String>of(
+ "setter_store.bin", "layoutinfo.bin", "br.bin");
+
+ /**
+ * The directory where the annotation processor looks for dep metadata.
+ */
+ private static final String DEP_METADATA_INPUT_DIR = "dependent-lib-artifacts";
+
+ /**
+ * The directory where the annotation processor write metadata output for the current rule.
+ */
+ private static final String METADATA_OUTPUT_DIR = "bin-files";
+
+ /**
* Should data binding support be enabled for this rule?
*
* <p>This is true if either the rule or any of its transitive dependencies declares data binding
@@ -90,6 +110,24 @@ public final class DataBinding {
}
/**
+ * Returns this rule's data binding base output dir (as an execroot-relative path).
+ */
+ private static PathFragment getDataBindingExecPath(RuleContext ruleContext) {
+ return ruleContext.getBinOrGenfilesDirectory().getExecPath().getRelative(
+ ruleContext.getUniqueDirectory("databinding"));
+ }
+
+ /**
+ * Returns an artifact for the specified output under a standardized data binding base dir.
+ */
+ private static Artifact getDataBindingArtifact(RuleContext ruleContext, String relativePath) {
+ PathFragment binRelativeBasePath = getDataBindingExecPath(ruleContext)
+ .relativeTo(ruleContext.getBinOrGenfilesDirectory().getExecPath());
+ return ruleContext.getDerivedArtifact(binRelativeBasePath.getRelative(relativePath),
+ ruleContext.getBinOrGenfilesDirectory());
+ }
+
+ /**
* Returns the file where data binding's resource processing produces binding xml. For
* example, given:
*
@@ -145,7 +183,7 @@ public final class DataBinding {
* translate data binding .xml into corresponding classes.
*/
static void addAnnotationProcessor(RuleContext ruleContext,
- JavaTargetAttributes.Builder attributes) {
+ JavaTargetAttributes.Builder attributes, boolean isBinary) {
JavaPluginInfoProvider plugin = ruleContext.getPrerequisite(
DATABINDING_ANNOTATION_PROCESSOR_ATTR, RuleConfiguredTarget.Mode.TARGET,
JavaPluginInfoProvider.class);
@@ -160,34 +198,75 @@ public final class DataBinding {
// For full compilation:
attributes.addProcessorPath(plugin.getProcessorClasspath());
attributes.addAdditionalOutputs(getMetadataOutputs(ruleContext));
+
+ addProcessorFlags(ruleContext, attributes, isBinary);
+ }
+
+ /**
+ * Adds javac flags to configure data binding's annotation processor.
+ */
+ private static void addProcessorFlags(RuleContext ruleContext,
+ JavaTargetAttributes.Builder attributes, boolean isBinary) {
+ String metadataOutputDir = getDataBindingExecPath(ruleContext).getPathString();
+
+ // Directory where the annotation processor looks for deps metadata output. The annotation
+ // processor automatically appends {@link DEP_METADATA_INPUT_DIR} to this path. Individual
+ // files can be anywhere under this directory, recursively.
+ addProcessorFlag(attributes, "bindingBuildFolder", metadataOutputDir);
+ // Directory where the annotation processor should write this rule's metadata output. The
+ // annotation processor automatically appends {@link METADATA_OUTPUT_DIR} to this path.
+ addProcessorFlag(attributes, "generationalFileOutDir", metadataOutputDir);
+ // Path to the Android SDK installation (if available).
+ addProcessorFlag(attributes, "sdkDir", "/not/used");
+ // Whether the current rule is a library or binary.
+ addProcessorFlag(attributes, "artifactType", isBinary ? "APPLICATION" : "LIBRARY");
+ // The path where data binding's resource processor wrote its output (the data binding XML
+ // expressions). The annotation processor reads this file to translate that XML into Java.
+ addProcessorFlag(attributes, "xmlOutDir", getDataBindingExecPath(ruleContext).toString());
+ // Unused.
+ addProcessorFlag(attributes, "exportClassListTo", "/tmp/exported_classes");
+ // The Java package for the current rule.
+ addProcessorFlag(attributes, "modulePackage",
+ AndroidCommon.getJavaPackage(ruleContext));
+ // The minimum Android SDK compatible with this rule.
+ addProcessorFlag(attributes, "minApi", "14"); // TODO(gregce): update this
+ // If enabled, the annotation processor reports detailed output about its activities.
+ // addProcessorFlag(attributes, "enableDebugLogs", "1");
+ // If enabled, produces cleaner output for Android Studio.
+ addProcessorFlag(attributes, "printEncodedErrors", "0");
+ // Specifies whether the current rule is a test. Currently unused.
+ // addDataBindingProcessorFlag(attributes, "isTestVariant", "false");
+ // Specifies that data binding is only used for test instrumentation. Currently unused.
+ // addDataBindingProcessorFlag(attributes, "enableForTests", null);
+ }
+
+ /**
+ * Turns a key/value pair into a javac annotation processor flag received by data binding.
+ */
+ private static void addProcessorFlag(JavaTargetAttributes.Builder attributes,
+ String flag, String value) {
+ attributes.addProcessorFlag(String.format("-Aandroid.databinding.%s=%s", flag, value));
}
/**
* Creates and returns the generated Java source that data binding's annotation processor
* reads to translate layout info xml (from {@link #getLayoutInfoFile} into the classes that
* end user code consumes.
+ *
+ * <p>This mostly just triggers the annotation processor. Annotation processor settings
+ * are configured in {@link #addProcessorFlags}.
*/
static Artifact createAnnotationFile(RuleContext ruleContext, boolean isLibrary) {
- Template template =
- Template.forResource(DataBinding.class, "databinding_annotation_template.txt");
-
- List<Substitution> subs = new ArrayList<>();
- subs.add(Substitution.of("%module_package%", AndroidCommon.getJavaPackage(ruleContext)));
- // TODO(gregce): clarify or remove the sdk root
- subs.add(Substitution.of("%sdk_root%", "/not/used"));
- subs.add(Substitution.of("%layout_info_dir%",
- getLayoutInfoFile(ruleContext).getExecPath().getParentDirectory().toString()));
- subs.add(Substitution.of("%export_class_list_to%", "/tmp/exported_classes")); // Unused.
- subs.add(Substitution.of("%is_library%", Boolean.toString(isLibrary)));
- subs.add(Substitution.of("%min_sdk%", "14")); // TODO(gregce): update this
-
- Artifact output = ruleContext.getPackageRelativeArtifact(
- String.format("databinding/%s/DataBindingInfo.java", ruleContext.getLabel().getName()),
- ruleContext.getConfiguration().getGenfilesDirectory());
-
- ruleContext.registerAction
- (new TemplateExpansionAction(ruleContext.getActionOwner(), output, template, subs, false));
-
+ String contents;
+ try {
+ contents = ResourceFileLoader.loadResource(DataBinding.class,
+ "databinding_annotation_template.txt");
+ } catch (IOException e) {
+ ruleContext.ruleError("Cannot load annotation processor template: " + e.getMessage());
+ return null;
+ }
+ Artifact output = getDataBindingArtifact(ruleContext, "DataBindingInfo.java");
+ ruleContext.registerAction(FileWriteAction.create(ruleContext, output, contents, false));
return output;
}
@@ -233,21 +312,18 @@ public final class DataBinding {
}
/**
- * Annotation processing creates the following metadata files that describe how data binding is
- * applied. The full file paths include prefixes as implemented in {@link #getMetadataOutputs}.
- */
- private static final ImmutableList<String> METADATA_OUTPUT_SUFFIXES = ImmutableList.<String>of(
- "setter_store.bin", "layoutinfo.bin", "br.bin");
-
- /**
* Returns metadata outputs from this rule's annotation processing that describe what it did with
* data binding. This is used by parent rules to ensure consistent binding patterns.
*
- * <p>>For example, if an {@code android_binary} depends on an {@code android_library} in a
- * different package, the {@code android_library}'s version gets packaged with the application
- * jar, even though (due to resource merging) both modules compile against their own instances.
+ * <p>>For example, if {@code foo.AndroidBinary} depends on {@code foo.lib.AndroidLibrary} and
+ * the library defines data binding expression {@code Bar}, compiling the library produces Java
+ * class {@code foo.lib.Bar}. But since the binary applies data binding over the merged resources
+ * of its deps, that means the binary also sees {@code Bar}, so it compiles it into
+ * {@code foo.Bar}. This would be a class redefinition conflict. But by feeding the library's
+ * metadata outputs into the binary's compilation, enough information is available to only use the
+ * first version.
*/
- public static List<Artifact> getMetadataOutputs(RuleContext ruleContext) {
+ private static List<Artifact> getMetadataOutputs(RuleContext ruleContext) {
if (!LocalResourceContainer.definesAndroidResources(ruleContext.attributes())) {
// If this rule doesn't define local resources, no resource processing was done, so it
// doesn't produce data binding output.
@@ -255,16 +331,11 @@ public final class DataBinding {
}
ImmutableList.Builder<Artifact> outputs = ImmutableList.<Artifact>builder();
String javaPackage = AndroidCommon.getJavaPackage(ruleContext);
- Label ruleLabel = ruleContext.getRule().getLabel();
- String pathPrefix =
- String.format(
- "_javac/%s/lib%s_classes/%s/%s-",
- ruleLabel.getName(),
- ruleLabel.getName(),
- javaPackage.replace('.', '/'),
- javaPackage);
for (String suffix : METADATA_OUTPUT_SUFFIXES) {
- outputs.add(ruleContext.getBinArtifact(pathPrefix + suffix));
+ // The annotation processor automatically creates files with this naming pattern under the
+ // {@code -Aandroid.databinding.generationalFileOutDir} base directory.
+ outputs.add(getDataBindingArtifact(ruleContext, String.format("%s/%s-%s-%s",
+ METADATA_OUTPUT_DIR, javaPackage, javaPackage, suffix)));
}
return outputs.build();
}
@@ -273,22 +344,40 @@ public final class DataBinding {
* Processes deps that also apply data binding.
*
* @param ruleContext the current rule
- * @param attributes java compilation attributes. The directories of the deps' metadata outputs
- * (see {@link #getMetadataOutputs}) are added to this rule's annotation processor classpath.
* @return the deps' metadata outputs. These need to be staged as compilation inputs to the
* current rule.
*/
- static ImmutableList<Artifact> processDeps(RuleContext ruleContext,
- JavaTargetAttributes.Builder attributes) {
+ static ImmutableList<Artifact> processDeps(RuleContext ruleContext) {
ImmutableList.Builder<Artifact> dataBindingJavaInputs = ImmutableList.<Artifact>builder();
if (LocalResourceContainer.definesAndroidResources(ruleContext.attributes())) {
dataBindingJavaInputs.add(DataBinding.getLayoutInfoFile(ruleContext));
}
for (Artifact dataBindingDepMetadata : getTransitiveMetadata(ruleContext, "deps")) {
- attributes.addProcessorPathDir(dataBindingDepMetadata.getExecPath().getParentDirectory());
- dataBindingJavaInputs.add(dataBindingDepMetadata);
+ dataBindingJavaInputs.add(
+ symlinkDepsMetadataIntoOutputTree(ruleContext, dataBindingDepMetadata));
}
return dataBindingJavaInputs.build();
}
+
+ /**
+ *
+ * Data binding's annotation processor reads the transitive metadata outputs of the target's deps
+ * (see {@link #getMetadataOutputs(RuleContext)}) in the directory specified by the processor
+ * flag {@code -Aandroid.databinding.bindingBuildFolder}. Since dependencies don't generate
+ * their outputs under a common directory, we symlink them into a common place here.
+ *
+ * @return the symlink paths of the transitive dep metadata outputs for this rule
+ */
+ private static Artifact symlinkDepsMetadataIntoOutputTree(RuleContext ruleContext,
+ Artifact depMetadata) {
+ Label ruleLabel = ruleContext.getRule().getLabel();
+ Artifact symlink = getDataBindingArtifact(ruleContext,
+ String.format("%s/%s", DEP_METADATA_INPUT_DIR, depMetadata.getRootRelativePathString()));
+ ruleContext.registerAction(
+ new SymlinkAction(ruleContext.getActionOwner(), depMetadata, symlink,
+ String.format("Symlinking dep metadata output %s for %s",
+ depMetadata.getFilename(), ruleLabel)));
+ return symlink;
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/databinding_annotation_template.txt b/src/main/java/com/google/devtools/build/lib/rules/android/databinding_annotation_template.txt
index f847a20be4..295397e4bb 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/databinding_annotation_template.txt
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/databinding_annotation_template.txt
@@ -8,19 +8,7 @@ import android.databinding.BindingBuildInfo;
* data binding declarations (from layoutInfoDir) to app code.
*/
@BindingBuildInfo(
- // Setting a random build ID triggers incremental recompiling for the
- // annotation processor. But Bazel is already incrementally correct, so
- // this is unnecessary.
- buildId="not_used_here",
- modulePackage="%module_package%",
- sdkRoot="%sdk_root%",
- // The layout info file's *directory* (not the file itself):
- layoutInfoDir="%layout_info_dir%",
- exportClassListTo="%export_class_list_to%",
- isLibrary=%is_library%,
- minSdk=%min_sdk%,
- enableDebugLogs=false,
- printEncodedError=true
+ buildId="not_used_here" // Adds incrementality, which Bazel already supports
)
public class DataBindingInfo {
/* This only exists for annotation processing. */
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 7d3742feb6..0c19e64ed8 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
@@ -212,8 +212,8 @@ public final class JavaCompilationHelper {
builder.setTempDirectory(tempDir(classJar));
builder.setClassDirectory(classDir(classJar));
builder.addProcessorPaths(attributes.getProcessorPath());
- builder.addProcessorPathDirs(attributes.getProcessorPathDirs());
builder.addProcessorNames(attributes.getProcessorNames());
+ builder.addProcessorFlags(attributes.getProcessorFlags());
builder.setStrictJavaDeps(attributes.getStrictJavaDeps());
builder.setDirectJars(attributes.getDirectJars());
builder.addCompileTimeDependencyArtifacts(attributes.getCompileTimeDependencyArtifacts());
@@ -362,7 +362,7 @@ public final class JavaCompilationHelper {
// only run API-generating annotation processors during header compilation
builder.addProcessorPaths(attributes.getApiGeneratingProcessorPath());
builder.addProcessorNames(attributes.getApiGeneratingProcessorNames());
-
+ builder.addProcessorFlags(attributes.getProcessorFlags());
builder.setJavacOpts(getJavacOpts());
builder.setTempDirectory(tempDir(headerJar));
builder.setOutputJar(headerJar);
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
index fb716cae47..320acd99f9 100644
--- 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
@@ -61,7 +61,6 @@ import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -116,6 +115,11 @@ public final class JavaCompileAction extends SpawnAction {
*/
private final ImmutableList<String> processorNames;
+ /**
+ * The list of custom javac flags to pass to annotation processors.
+ */
+ private final ImmutableList<String> processorFlags;
+
/** Set of additional Java source files to compile. */
private final ImmutableList<Artifact> sourceJars;
@@ -160,6 +164,7 @@ public final class JavaCompileAction extends SpawnAction {
* @param extdirInputs the compile-time extclasspath entries
* @param processorPath the classpath to search for annotation processors
* @param processorNames the annotation processors to run
+ * @param processorFlags custom annotation processor flags to pass to javac
* @param sourceJars jars of sources to compile
* @param sourceFiles source files to compile
* @param javacOpts the javac options for the compilation
@@ -184,6 +189,7 @@ public final class JavaCompileAction extends SpawnAction {
ImmutableList<Artifact> extdirInputs,
List<Artifact> processorPath,
List<String> processorNames,
+ List<String> processorFlags,
Collection<Artifact> sourceJars,
Collection<Artifact> sourceFiles,
List<String> javacOpts,
@@ -218,6 +224,7 @@ public final class JavaCompileAction extends SpawnAction {
this.extdirInputs = extdirInputs;
this.processorPath = ImmutableList.copyOf(processorPath);
this.processorNames = ImmutableList.copyOf(processorNames);
+ this.processorFlags = ImmutableList.copyOf(processorFlags);
this.sourceJars = ImmutableList.copyOf(sourceJars);
this.sourceFiles = ImmutableList.copyOf(sourceFiles);
this.javacOpts = ImmutableList.copyOf(javacOpts);
@@ -311,6 +318,10 @@ public final class JavaCompileAction extends SpawnAction {
return processorNames;
}
+ private List<String> getProcessorFlags() {
+ return processorFlags;
+ }
+
/**
* Returns the output jar artifact that gets generated by archiving the results of the Java
* compilation.
@@ -517,8 +528,8 @@ public final class JavaCompileAction extends SpawnAction {
private PathFragment tempDirectory;
private PathFragment classDirectory;
private final List<Artifact> processorPath = new ArrayList<>();
- private final Set<PathFragment> processorPathDirs = new LinkedHashSet<>();
private final List<String> processorNames = new ArrayList<>();
+ private final List<String> processorFlags = new ArrayList<>();
private String ruleKind;
private Label targetLabel;
@@ -652,6 +663,7 @@ public final class JavaCompileAction extends SpawnAction {
extdirInputs,
processorPath,
processorNames,
+ processorFlags,
sourceJars,
sourceFiles,
internedJcopts,
@@ -700,18 +712,18 @@ public final class JavaCompileAction extends SpawnAction {
if (!sourcePathEntries.isEmpty()) {
result.addJoinExecPaths("--sourcepath", pathSeparator, sourcePathEntries);
}
- if (!processorPath.isEmpty() || !processorPathDirs.isEmpty()) {
+ if (!processorPath.isEmpty()) {
ImmutableList.Builder<String> execPathStrings = ImmutableList.<String>builder();
execPathStrings.addAll(Artifact.toExecPaths(processorPath));
- for (PathFragment processorPathDir : processorPathDirs) {
- execPathStrings.add(processorPathDir.toString());
- }
result.addJoinStrings(
"--processorpath", pathSeparator, execPathStrings.build());
}
if (!processorNames.isEmpty()) {
result.add("--processors", processorNames);
}
+ if (!processorFlags.isEmpty()) {
+ result.add("--javacopts", processorFlags);
+ }
if (!sourceJars.isEmpty()) {
result.addExecPaths("--source_jars", sourceJars);
}
@@ -944,13 +956,13 @@ public final class JavaCompileAction extends SpawnAction {
return this;
}
- public Builder addProcessorPathDirs(Collection<PathFragment> processorPathDirs) {
- this.processorPathDirs.addAll(processorPathDirs);
+ public Builder addProcessorNames(Collection<String> processorNames) {
+ this.processorNames.addAll(processorNames);
return this;
}
- public Builder addProcessorNames(Collection<String> processorNames) {
- this.processorNames.addAll(processorNames);
+ public Builder addProcessorFlags(Collection<String> processorFlags) {
+ this.processorFlags.addAll(processorFlags);
return this;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaHeaderCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaHeaderCompileAction.java
index 7ffaee271a..3939d0e680 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaHeaderCompileAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaHeaderCompileAction.java
@@ -203,6 +203,8 @@ public class JavaHeaderCompileAction extends SpawnAction {
private ImmutableList<String> javacOpts;
private final List<Artifact> processorPath = new ArrayList<>();
private final List<String> processorNames = new ArrayList<>();
+ private final List<String> processorFlags = new ArrayList<>();
+
private NestedSet<Artifact> javabaseInputs;
private Artifact javacJar;
@@ -304,6 +306,13 @@ public class JavaHeaderCompileAction extends SpawnAction {
return this;
}
+ /** Sets annotation processor flags to pass to javac. */
+ public Builder addProcessorFlags(Collection<String> processorFlags) {
+ checkNotNull(processorFlags, "processorFlags must not be null");
+ this.processorFlags.addAll(processorFlags);
+ return this;
+ }
+
/** Sets the kind of the build rule being compiled (e.g. {@code java_library}). */
public Builder setRuleKind(@Nullable String ruleKind) {
this.ruleKind = ruleKind;
@@ -487,6 +496,9 @@ public class JavaHeaderCompileAction extends SpawnAction {
if (!processorNames.isEmpty()) {
result.add("--processors", processorNames);
}
+ if (!processorFlags.isEmpty()) {
+ result.add("--javacopts", processorFlags);
+ }
if (!processorPath.isEmpty()) {
result.addExecPaths("--processorpath", processorPath);
}
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 d09bdbc893..dc6187d2d4 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
@@ -73,8 +73,8 @@ public class JavaTargetAttributes {
private final Set<Artifact> processorPath = new LinkedHashSet<>();
// Classpath directories can't be represented as artifacts (TreeArtifact isn't appropriate
// here since all we need is a path string to apply to the command line).
- private final Set<PathFragment> processorPathDirs = new LinkedHashSet<>();
private final Set<String> processorNames = new LinkedHashSet<>();
+ private final Set<String> processorFlags = new LinkedHashSet<>();
private final Set<Artifact> apiGeneratingProcessorPath = new LinkedHashSet<>();
private final Set<String> apiGeneratingProcessorNames = new LinkedHashSet<>();
@@ -319,15 +319,15 @@ public class JavaTargetAttributes {
return this;
}
- public Builder addProcessorPath(Iterable<Artifact> jars) {
+ public Builder addProcessorFlag(String processorFlag) {
Preconditions.checkArgument(!built);
- Iterables.addAll(processorPath, jars);
+ processorFlags.add(processorFlag);
return this;
}
- public Builder addProcessorPathDir(PathFragment dir) {
+ public Builder addProcessorPath(Iterable<Artifact> jars) {
Preconditions.checkArgument(!built);
- processorPathDirs.add(dir);
+ Iterables.addAll(processorPath, jars);
return this;
}
@@ -375,8 +375,8 @@ public class JavaTargetAttributes {
sourcePath,
nativeLibraries,
processorPath,
- processorPathDirs,
processorNames,
+ processorFlags,
apiGeneratingProcessorPath,
apiGeneratingProcessorNames,
resources,
@@ -442,8 +442,8 @@ public class JavaTargetAttributes {
private final ImmutableList<Artifact> nativeLibraries;
private final ImmutableSet<Artifact> processorPath;
- private final ImmutableSet<PathFragment> processorPathDirs;
private final ImmutableSet<String> processorNames;
+ private final ImmutableSet<String> processorFlags;
private final ImmutableSet<Artifact> apiGeneratingProcessorPath;
private final ImmutableSet<String> apiGeneratingProcessorNames;
@@ -476,8 +476,8 @@ public class JavaTargetAttributes {
List<Artifact> sourcePath,
List<Artifact> nativeLibraries,
Set<Artifact> processorPath,
- Set<PathFragment> processorPathDirs,
Set<String> processorNames,
+ Set<String> processorFlags,
Set<Artifact> apiGeneratingProcessorPath,
Set<String> apiGeneratingProcessorNames,
Map<PathFragment, Artifact> resources,
@@ -505,8 +505,8 @@ public class JavaTargetAttributes {
this.sourcePath = ImmutableList.copyOf(sourcePath);
this.nativeLibraries = ImmutableList.copyOf(nativeLibraries);
this.processorPath = ImmutableSet.copyOf(processorPath);
- this.processorPathDirs = ImmutableSet.copyOf(processorPathDirs);
this.processorNames = ImmutableSet.copyOf(processorNames);
+ this.processorFlags = ImmutableSet.copyOf(processorFlags);
this.apiGeneratingProcessorPath = ImmutableSet.copyOf(apiGeneratingProcessorPath);
this.apiGeneratingProcessorNames = ImmutableSet.copyOf(apiGeneratingProcessorNames);
this.resources = ImmutableMap.copyOf(resources);
@@ -600,10 +600,6 @@ public class JavaTargetAttributes {
return processorPath;
}
- public ImmutableSet<PathFragment> getProcessorPathDirs() {
- return processorPathDirs;
- }
-
public Collection<Artifact> getApiGeneratingProcessorPath() {
return apiGeneratingProcessorPath;
}
@@ -628,6 +624,10 @@ public class JavaTargetAttributes {
return processorNames;
}
+ public Collection<String> getProcessorFlags() {
+ return processorFlags;
+ }
+
public boolean hasSources() {
return !sourceFiles.isEmpty() || !sourceJars.isEmpty();
}