aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib
diff options
context:
space:
mode:
authorGravatar gregce <gregce@google.com>2017-04-05 18:25:34 +0000
committerGravatar Marcel Hlopko <hlopko@google.com>2017-04-06 11:00:13 +0200
commit418fcc73c0b5c553b1b945501bd10a394fa65f0d (patch)
treea49583e19efcfb92f632e4df4a6af0cc7fedfbd8 /src/main/java/com/google/devtools/build/lib
parent697a328dd6994bcf8f76d9abf09ac0e8734e3a07 (diff)
Upgrade Android data binding integration to work with newest libraries.
This change makes Bazel work with data binding runtime libraries 1.3.1 and buildtime libraries 2.3.1. The biggest change is to configure the annotation processor with javac annotation processor flags ("-Aflag=value") instead of directly through annotations in a template Java file. PiperOrigin-RevId: 152282448
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib')
-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();
}