aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java
diff options
context:
space:
mode:
authorGravatar Greg Estren <gregce@google.com>2016-11-21 17:54:46 +0000
committerGravatar Dmitry Lomov <dslomov@google.com>2016-11-21 20:04:46 +0000
commit2aada22ebb0671a3ee772888bf52fe814a519197 (patch)
treeb844a850254ad09a7f388d602a2e169e401539a0 /src/main/java
parent3b57ccfba7e67f85a0d3c31f9b813719e367fe9c (diff)
Adds internal data binding support to Bazel, although this
is not yet exposed at the user level. (https://developer.android.com/topic/libraries/data-binding/index.html). See comments in DataBinding.java for the high-level overview of how this works. This does not yet work with --experimental_use_parallel_android_resource_processing. Exposing this at the user level additionally requires: 1) making the data binding support libraries available at an expected place in the depot 2) Opting in android_binary / android_library rules through a new "enable_data_binding" attribute. -- MOS_MIGRATED_REVID=139797558
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java18
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java54
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java16
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java15
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/DataBinding.java276
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/UsesDataBindingProvider.java40
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/databinding_annotation_template.txt27
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java12
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java46
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java44
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaTargetAttributes.java37
12 files changed, 556 insertions, 36 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
index 118228a740..834b1e1049 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
@@ -102,10 +102,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
}
NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.stableOrder();
- ImmutableList<TransitiveInfoCollection> deps = ImmutableList.<TransitiveInfoCollection>copyOf(
- ruleContext.getPrerequisites("deps", Mode.TARGET));
- JavaCommon javaCommon = new JavaCommon(
- ruleContext, javaSemantics, deps, deps, deps);
+ JavaCommon javaCommon =
+ AndroidCommon.createJavaCommonWithAndroidDataBinding(ruleContext, javaSemantics, false);
javaSemantics.checkRule(ruleContext, javaCommon);
javaSemantics.checkForProtoLibraryAndJavaProtoLibraryOnSameProto(ruleContext, javaCommon);
@@ -225,7 +223,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
ProguardHelper.getProguardConfigArtifact(ruleContext, ""),
createMainDexProguardSpec(ruleContext),
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_PROCESSED_MANIFEST),
- ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_ZIP));
+ ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_ZIP),
+ DataBinding.isEnabled(ruleContext) ? DataBinding.getLayoutInfoFile(ruleContext) : null);
ruleContext.assertNoErrors();
incrementalResourceApk = applicationManifest
@@ -246,7 +245,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
ProguardHelper.getProguardConfigArtifact(ruleContext, "incremental"),
null, /* mainDexProguardCfg */
null, /* manifestOut */
- null /* mergedResourcesOut */);
+ null, /* mergedResourcesOut */
+ null /* dataBindingInfoZip */);
ruleContext.assertNoErrors();
instantRunResourceApk = applicationManifest
@@ -266,7 +266,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
ProguardHelper.getProguardConfigArtifact(ruleContext, "instant_run"),
null, /* mainDexProguardCfg */
null, /* manifestOut */
- null /* mergedResourcesOut */);
+ null /* mergedResourcesOut */,
+ null /* dataBindingInfoZip */);
ruleContext.assertNoErrors();
splitResourceApk = applicationManifest
@@ -286,7 +287,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
ProguardHelper.getProguardConfigArtifact(ruleContext, "incremental_split"),
null, /* mainDexProguardCfg */
null, /* manifestOut */
- null /* mergedResourcesOut */);
+ null /* mergedResourcesOut */,
+ null /* dataBindingInfoZip */);
ruleContext.assertNoErrors();
} else {
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 455ee0229d..2105496744 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
@@ -22,6 +22,7 @@ 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.OutputGroupProvider;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleContext;
@@ -548,6 +549,9 @@ public class AndroidCommon {
idlHelper.getIdlGeneratedJavaSources(),
androidSemantics.getJavacArguments(ruleContext))
.setBootClassPath(bootclasspath);
+ if (DataBinding.isEnabled(ruleContext)) {
+ DataBinding.addAnnotationProcessor(ruleContext, attributes);
+ }
JavaCompilationArtifacts.Builder artifactsBuilder = new JavaCompilationArtifacts.Builder();
NestedSetBuilder<Artifact> jarsProducedForRuntime = NestedSetBuilder.<Artifact>stableOrder();
@@ -607,8 +611,10 @@ public class AndroidCommon {
private JavaCompilationHelper initAttributes(
JavaTargetAttributes.Builder attributes, JavaSemantics semantics) {
- JavaCompilationHelper helper = new JavaCompilationHelper(
- ruleContext, semantics, javaCommon.getJavacOpts(), attributes);
+ JavaCompilationHelper helper = new JavaCompilationHelper(ruleContext, semantics,
+ javaCommon.getJavacOpts(), attributes,
+ DataBinding.isEnabled(ruleContext)
+ ? DataBinding.processDeps(ruleContext, attributes) : ImmutableList.<Artifact>of());
helper.addLibrariesToAttributes(javaCommon.targetsTreatedAsDeps(ClasspathType.COMPILE_ONLY));
attributes.setRuleKind(ruleContext.getRule().getRuleClass());
@@ -961,4 +967,48 @@ public class AndroidCommon {
}
return builder.build();
}
+
+ /**
+ * Returns a {@link JavaCommon} instance with Android data binding support.
+ *
+ * <p>Binaries need both compile-time and runtime support, while libraries only need compile-time
+ * support.
+ *
+ * <p>No rule needs <i>any</i> support if data binding is disabled.
+ */
+ static JavaCommon createJavaCommonWithAndroidDataBinding(RuleContext ruleContext,
+ JavaSemantics semantics, boolean isLibrary) {
+ boolean useDataBinding = DataBinding.isEnabled(ruleContext);
+
+ ImmutableList<Artifact> srcs =
+ ruleContext.getPrerequisiteArtifacts("srcs", RuleConfiguredTarget.Mode.TARGET).list();
+ if (useDataBinding) {
+ srcs = ImmutableList.<Artifact>builder().addAll(srcs)
+ .add(DataBinding.createAnnotationFile(ruleContext, isLibrary)).build();
+ }
+
+ ImmutableList<TransitiveInfoCollection> compileDeps;
+ ImmutableList<TransitiveInfoCollection> runtimeDeps;
+ ImmutableList<TransitiveInfoCollection> bothDeps;
+
+ if (isLibrary) {
+ compileDeps = JavaCommon.defaultDeps(ruleContext, semantics, ClasspathType.COMPILE_ONLY);
+ if (useDataBinding) {
+ compileDeps = DataBinding.addSupportLibs(ruleContext, compileDeps);
+ }
+ runtimeDeps = JavaCommon.defaultDeps(ruleContext, semantics, ClasspathType.RUNTIME_ONLY);
+ bothDeps = JavaCommon.defaultDeps(ruleContext, semantics, ClasspathType.BOTH);
+ } else {
+ // Binary:
+ List<? extends TransitiveInfoCollection> ruleDeps =
+ ruleContext.getPrerequisites("deps", RuleConfiguredTarget.Mode.TARGET);
+ compileDeps = useDataBinding
+ ? DataBinding.addSupportLibs(ruleContext, ruleDeps)
+ : ImmutableList.<TransitiveInfoCollection>copyOf(ruleDeps);
+ runtimeDeps = compileDeps;
+ bothDeps = compileDeps;
+ }
+
+ return new JavaCommon(ruleContext, semantics, srcs, compileDeps, runtimeDeps, bothDeps);
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
index 9eb88a1a24..90ad509ed1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
@@ -64,7 +64,8 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
AndroidCommon.collectTransitiveInfo(ruleContext, Mode.TARGET));
NestedSet<Artifact> transitiveProguardConfigs =
new ProguardLibrary(ruleContext).collectProguardSpecs();
- JavaCommon javaCommon = new JavaCommon(ruleContext, javaSemantics);
+ JavaCommon javaCommon =
+ AndroidCommon.createJavaCommonWithAndroidDataBinding(ruleContext, javaSemantics, true);
javaSemantics.checkRule(ruleContext, javaCommon);
AndroidCommon androidCommon = new AndroidCommon(javaCommon);
@@ -93,8 +94,8 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
null, /* proguardCfgOut */
null, /* mainDexProguardCfg */
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_PROCESSED_MANIFEST),
- // This is just to communicate the results from the merge step to the validator step.
- ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_ZIP));
+ ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_ZIP),
+ DataBinding.isEnabled(ruleContext) ? DataBinding.getLayoutInfoFile(ruleContext) : null);
if (ruleContext.hasErrors()) {
return null;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java
index 45ee4685f5..bbbc9b052a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java
@@ -83,6 +83,7 @@ public class AndroidResourcesProcessorBuilder {
private String applicationId;
private String versionName;
private Artifact symbolsTxt;
+ private Artifact dataBindingInfoZip;
private Artifact manifestOut;
private Artifact mergedResourcesOut;
@@ -107,6 +108,16 @@ public class AndroidResourcesProcessorBuilder {
return this;
}
+ /**
+ * The output zip for resource-processed data binding expressions (i.e. a zip of .xml files).
+ * If null, data binding processing is skipped (and data binding expressions aren't allowed in
+ * layout resources).
+ */
+ public AndroidResourcesProcessorBuilder setDataBindingInfoZip(Artifact zip) {
+ this.dataBindingInfoZip = zip;
+ return this;
+ }
+
public AndroidResourcesProcessorBuilder withDependencies(ResourceDependencies resourceDeps) {
this.dependencies = resourceDeps;
return this;
@@ -287,6 +298,11 @@ public class AndroidResourcesProcessorBuilder {
builder.add("--applicationId").add(applicationId);
}
+ if (dataBindingInfoZip != null) {
+ builder.addExecPath("--dataBindingInfoOut", dataBindingInfoZip);
+ outs.add(dataBindingInfoZip);
+ }
+
if (!Strings.isNullOrEmpty(customJavaPackage)) {
// Sets an alternative java package for the generated R.java
// this allows android rules to generate resources outside of the java{,tests} tree.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java b/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
index cd7ee9be5c..3a00d2adb8 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
@@ -313,7 +313,8 @@ public final class ApplicationManifest {
proguardCfg,
null, /* Artifact mainDexProguardCfg */
null, /* Artifact manifestOut */
- null /* Artifact mergedResources */);
+ null /* Artifact mergedResources */,
+ null /* Artifact dataBindingInfoZip */);
}
/** Packages up the manifest with resource and assets from the LocalResourceContainer. */
@@ -349,7 +350,8 @@ public final class ApplicationManifest {
null, /* Artifact proguardCfg */
null, /* Artifact mainDexProguardCfg */
manifestOut,
- mergedResources);
+ mergedResources,
+ null /* Artifact dataBindingInfoZip */);
}
/** Packages up the manifest with resource and assets from the rule and dependent resources. */
@@ -368,7 +370,8 @@ public final class ApplicationManifest {
Artifact proguardCfg,
@Nullable Artifact mainDexProguardCfg,
Artifact manifestOut,
- Artifact mergedResources) throws InterruptedException {
+ Artifact mergedResources,
+ Artifact dataBindingInfoZip) throws InterruptedException {
LocalResourceContainer data = new LocalResourceContainer.Builder(ruleContext)
.withAssets(
AndroidCommon.getAssetDir(ruleContext),
@@ -404,7 +407,7 @@ public final class ApplicationManifest {
proguardCfg,
mainDexProguardCfg,
manifestOut,
- mergedResources);
+ mergedResources, dataBindingInfoZip);
}
private ResourceApk createApk(
@@ -421,7 +424,8 @@ public final class ApplicationManifest {
Artifact proguardCfg,
@Nullable Artifact mainDexProguardCfg,
Artifact manifestOut,
- Artifact mergedResources) throws InterruptedException {
+ Artifact mergedResources,
+ Artifact dataBindingInfoZip) throws InterruptedException {
ResourceContainer resourceContainer = checkForInlinedResources(
maybeInlinedResourceContainer,
resourceDeps.getResources(), // TODO(bazel-team): Figure out if we really need to check
@@ -484,6 +488,7 @@ public final class ApplicationManifest {
.setDensities(densities)
.setProguardOut(proguardCfg)
.setMainDexProguardOut(mainDexProguardCfg)
+ .setDataBindingInfoZip(dataBindingInfoZip)
.setApplicationId(manifestValues.get("applicationId"))
.setVersionCode(manifestValues.get("versionCode"))
.setVersionName(manifestValues.get("versionName"));
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
new file mode 100644
index 0000000000..7290259437
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/DataBinding.java
@@ -0,0 +1,276 @@
+// Copyright 2016 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.android;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Artifact;
+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.cmdline.Label;
+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 java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Support logic for Bazel's
+ * <a href="https://developer.android.com/topic/libraries/data-binding/index.html">data binding</a>
+ * integration.
+ *
+ * <p>In short, data binding in Bazel works as follows:
+ * <ol>
+ * <li>If a rule enables data binding and has layout resources with data binding expressions,
+ * resource processing invokes the data binding library to preprocess these expressions, then
+ * strips them out before feeding the resources into aapt. A separate "layout info" XML file
+ * gets produced that contains the bindings.</li>
+ * <li>The data binding annotation processor gets activated on Java compilation. This processor
+ * reads a custom-generated <code>DataBindingInfo.java</code> which specifies the path to the
+ * layout info file (as an annotation). The processor reads that file and produces the
+ * corresponding Java classes that end-user code uses to access the resources.</li>
+ * <li>The data binding compile-time and runtime support libraries get linked into the binary's
+ * deploy jar.</li>
+ * </ol>
+ *
+ * <p>For data binding to work, the corresponding support libraries must be checked into the depot
+ * via the implicit dependencies specified inside this class.
+ *
+ * <p>Unless otherwise specified, all methods in this class assume the current rule applies data
+ * binding. Callers can intelligently trigger this logic by checking {@link #isEnabled}.
+ *
+ */
+public final class DataBinding {
+ /**
+ * The rule attribute supplying the data binding runtime/compile-time support libraries.
+ */
+ private static final String DATABINDING_RUNTIME_ATTR = "$databinding_runtime";
+
+ /**
+ * The rule attribute supplying the data binding annotation processor.
+ */
+ private static final String DATABINDING_ANNOTATION_PROCESSOR_ATTR =
+ "$databinding_annotation_processor";
+
+ /**
+ * 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
+ * support in its attributes.
+ *
+ * <p>Data binding incurs additional resource processing and compilation work as well as
+ * additional compile/runtime dependencies. But rules with data binding disabled will fail if
+ * any data binding expressions appear in their layout resources.
+ */
+ public static boolean isEnabled(RuleContext ruleContext) {
+ if (ruleContext.attributes().has("enable_data_binding", Type.BOOLEAN)
+ && ruleContext.attributes().get("enable_data_binding", Type.BOOLEAN)) {
+ return true;
+ } else {
+ return !Iterables.isEmpty(ruleContext.getPrerequisites("deps",
+ RuleConfiguredTarget.Mode.TARGET, UsesDataBindingProvider.class));
+ }
+ }
+
+ /**
+ * Returns the file where data binding's resource processing produces binding xml. For
+ * example, given:
+ *
+ * <pre>{@code
+ * <layout>
+ * <data>
+ * <variable name="foo" type="String" />
+ * </data>
+ * </layout>
+ * <LinearLayout>
+ * ...
+ * </LinearLayout>
+ * }
+ * </pre>
+ *
+ * <p>data binding strips out and processes this part:
+ *
+ * <pre>{@code
+ * <data>
+ * <variable name="foo" type="String" />
+ * </data>
+ * }
+ * </pre>
+ *
+ * for each layout file with data binding expressions. Since this may produce multiple
+ * files, outputs are zipped up into a single container.
+ */
+ static Artifact getLayoutInfoFile(RuleContext ruleContext) {
+ // The data binding library expects this to be called "layout-info.zip".
+ return ruleContext.getUniqueDirectoryArtifact("databinding", "layout-info.zip",
+ ruleContext.getBinOrGenfilesDirectory());
+ }
+
+ /**
+ * Adds the support libraries needed to compile/run Java code with data binding.
+ *
+ * <p>This excludes the annotation processor, which is injected separately as a Java plugin
+ * (see {@link #addAnnotationProcessor}).
+ */
+ static ImmutableList<TransitiveInfoCollection> addSupportLibs(RuleContext ruleContext,
+ List<? extends TransitiveInfoCollection> deps) {
+ RuleConfiguredTarget.Mode mode = RuleConfiguredTarget.Mode.TARGET;
+ return ImmutableList.<TransitiveInfoCollection>builder()
+ .addAll(deps)
+ .addAll(ruleContext.getPrerequisites(DATABINDING_RUNTIME_ATTR, mode))
+ .build();
+ }
+
+ /**
+ * Adds data binding's annotation processor as a plugin to the given Java compilation context.
+ *
+ * <p>This, in conjunction with {@link #createAnnotationFile} extends the Java compilation to
+ * translate data binding .xml into corresponding classes.
+ */
+ static void addAnnotationProcessor(RuleContext ruleContext,
+ JavaTargetAttributes.Builder attributes) {
+ JavaPluginInfoProvider plugin = ruleContext.getPrerequisite(
+ DATABINDING_ANNOTATION_PROCESSOR_ATTR, RuleConfiguredTarget.Mode.TARGET,
+ JavaPluginInfoProvider.class);
+ for (String name : plugin.getProcessorClasses()) {
+ // For header compilation (see JavaHeaderCompileAction):
+ attributes.addApiGeneratingProcessorName(name);
+ // For full compilation:
+ attributes.addProcessorName(name);
+ }
+ // For header compilation (see JavaHeaderCompileAction):
+ attributes.addApiGeneratingProcessorPath(plugin.getProcessorClasspath());
+ // For full compilation:
+ attributes.addProcessorPath(plugin.getProcessorClasspath());
+ attributes.addAdditionalOutputs(getMetadataOutputs(ruleContext));
+ }
+
+ /**
+ * 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.
+ */
+ 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));
+
+ return output;
+ }
+
+ /**
+ * Adds the appropriate {@link UsesDataBindingProvider} for a rule if it should expose one.
+ *
+ * <p>A rule exposes {@link UsesDataBindingProvider} if either it or its deps set
+ * {@code enable_data_binding = 1}.
+ */
+ public static void maybeAddProvider(RuleConfiguredTargetBuilder builder,
+ RuleContext ruleContext) {
+ // Expose the data binding provider if this rule either applies data binding or exports a dep
+ // that applies it.
+ List<Artifact> dataBindingMetadataOutputs = new ArrayList<>();
+ if (DataBinding.isEnabled(ruleContext)) {
+ dataBindingMetadataOutputs.addAll(getMetadataOutputs(ruleContext));
+ }
+ if (ruleContext.getAttribute("exports") != null) {
+ for (UsesDataBindingProvider provider : ruleContext.getPrerequisites("exports",
+ RuleConfiguredTarget.Mode.TARGET, UsesDataBindingProvider.class)) {
+ dataBindingMetadataOutputs.addAll(provider.getMetadataOutputs());
+ }
+ }
+ if (!dataBindingMetadataOutputs.isEmpty()) {
+ // QUESTION(gregce): does a rule need to propagate the metadata outputs of its deps, or do
+ // they get integrated automatically into its own outputs?
+ builder.addProvider(UsesDataBindingProvider.class,
+ new UsesDataBindingProvider(dataBindingMetadataOutputs));
+ }
+ }
+
+ /**
+ * 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.
+ */
+ public static List<Artifact> getMetadataOutputs(RuleContext ruleContext) {
+ 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.getPackageIdentifier().getPackageFragment().getBaseName(),
+ javaPackage.replace('.', '/'),
+ javaPackage);
+ for (String suffix : METADATA_OUTPUT_SUFFIXES) {
+ outputs.add(ruleContext.getBinArtifact(pathPrefix + suffix));
+ }
+ return outputs.build();
+ }
+
+ /**
+ * 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) {
+ ImmutableList.Builder<Artifact> dataBindingJavaInputs = ImmutableList.<Artifact>builder();
+ dataBindingJavaInputs.add(DataBinding.getLayoutInfoFile(ruleContext));
+ for (UsesDataBindingProvider p : ruleContext.getPrerequisites("deps",
+ RuleConfiguredTarget.Mode.TARGET, UsesDataBindingProvider.class)) {
+ for (Artifact dataBindingDepMetadata : p.getMetadataOutputs()) {
+ attributes.addProcessorPathDir(dataBindingDepMetadata.getExecPath().getParentDirectory());
+ dataBindingJavaInputs.add(dataBindingDepMetadata);
+ }
+ }
+ return dataBindingJavaInputs.build();
+ }
+}
+
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/UsesDataBindingProvider.java b/src/main/java/com/google/devtools/build/lib/rules/android/UsesDataBindingProvider.java
new file mode 100644
index 0000000000..7f69dac2bd
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/UsesDataBindingProvider.java
@@ -0,0 +1,40 @@
+// Copyright 2016 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.android;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
+import java.util.Collection;
+
+/**
+ * An Android rule that exposes this enables
+ * <a href="https://developer.android.com/topic/libraries/data-binding/index.html">data binding</a>
+ * on its resource processing and Java compilation.
+ */
+public final class UsesDataBindingProvider implements TransitiveInfoProvider {
+ private final ImmutableList<Artifact> metadataOutputs;
+
+ public UsesDataBindingProvider(Collection<Artifact> metadataOutputs) {
+ this.metadataOutputs = ImmutableList.copyOf(metadataOutputs);
+ }
+
+ /**
+ * Returns the metadata outputs from this rule's annotation processing that describe how it
+ * applies data binding. See {@link DataBinding#getMetadataOutputs} for details.
+ */
+ public ImmutableList<Artifact> getMetadataOutputs() {
+ return metadataOutputs;
+ }
+}
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
new file mode 100644
index 0000000000..f847a20be4
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/databinding_annotation_template.txt
@@ -0,0 +1,27 @@
+package android.databinding.layouts;
+
+import android.databinding.BindingBuildInfo;
+
+/**
+ * Template for the file that feeds data binding's annotation processor. The
+ * processor reads the values set here to generate .java files that link XML
+ * 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
+)
+public class DataBindingInfo {
+ /* This only exists for annotation processing. */
+}
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 aeb96b58e9..9f528c44de 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
@@ -608,6 +608,14 @@ public class JavaCommon {
return targetsTreatedAsDeps.get(type);
}
+ /**
+ * Returns the default dependencies for the given classpath context.
+ */
+ public static ImmutableList<TransitiveInfoCollection> defaultDeps(RuleContext ruleContext,
+ JavaSemantics semantics, ClasspathType type) {
+ return collectTargetsTreatedAsDeps(ruleContext, semantics, type);
+ }
+
private static ImmutableList<TransitiveInfoCollection> collectTargetsTreatedAsDeps(
RuleContext ruleContext, JavaSemantics semantics, ClasspathType type) {
ImmutableList.Builder<TransitiveInfoCollection> builder = new Builder<>();
@@ -798,8 +806,8 @@ public class JavaCommon {
* @return the value of the neverlink attribute.
*/
public static final boolean isNeverLink(RuleContext ruleContext) {
- return ruleContext.getRule().isAttrDefined("neverlink", Type.BOOLEAN) &&
- ruleContext.attributes().get("neverlink", Type.BOOLEAN);
+ return ruleContext.getRule().isAttrDefined("neverlink", Type.BOOLEAN)
+ && ruleContext.attributes().get("neverlink", Type.BOOLEAN);
}
private static NestedSet<Artifact> getFilesToCompile(Artifact classJar) {
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 9ae2dbee79..77e2b02a13 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
@@ -66,6 +66,7 @@ public final class JavaCompilationHelper {
private final List<Artifact> translations = new ArrayList<>();
private boolean translationsFrozen;
private final JavaSemantics semantics;
+ private final ImmutableList<Artifact> additionalJavaBaseInputs;
private static final String DEFAULT_ATTRIBUTES_SUFFIX = "";
@@ -73,7 +74,8 @@ public final class JavaCompilationHelper {
ImmutableList<String> javacOpts, JavaTargetAttributes.Builder attributes,
JavaToolchainProvider javaToolchainProvider,
NestedSet<Artifact> hostJavabase,
- Iterable<Artifact> jacocoInstrumentation) {
+ Iterable<Artifact> jacocoInstrumentation,
+ ImmutableList<Artifact> additionalJavaBaseInputs) {
this.ruleContext = ruleContext;
this.javaToolchain = javaToolchainProvider;
this.hostJavabase = hostJavabase;
@@ -82,6 +84,16 @@ public final class JavaCompilationHelper {
this.customJavacOpts = javacOpts;
this.customJavacJvmOpts = javaToolchain.getJvmOptions();
this.semantics = semantics;
+ this.additionalJavaBaseInputs = additionalJavaBaseInputs;
+ }
+
+ public JavaCompilationHelper(RuleContext ruleContext, JavaSemantics semantics,
+ ImmutableList<String> javacOpts, JavaTargetAttributes.Builder attributes,
+ JavaToolchainProvider javaToolchainProvider,
+ NestedSet<Artifact> hostJavabase,
+ Iterable<Artifact> jacocoInstrumentation) {
+ this(ruleContext, semantics, javacOpts, attributes, javaToolchainProvider, hostJavabase,
+ jacocoInstrumentation, ImmutableList.<Artifact>of());
}
public JavaCompilationHelper(RuleContext ruleContext, JavaSemantics semantics,
@@ -93,6 +105,16 @@ public final class JavaCompilationHelper {
}
public JavaCompilationHelper(RuleContext ruleContext, JavaSemantics semantics,
+ ImmutableList<String> javacOpts, JavaTargetAttributes.Builder attributes,
+ ImmutableList<Artifact> additionalJavaBaseInputs) {
+ this(ruleContext, semantics, javacOpts, attributes,
+ getJavaToolchainProvider(ruleContext),
+ getHostJavabaseInputsNonStatic(ruleContext),
+ getInstrumentationJars(ruleContext),
+ additionalJavaBaseInputs);
+ }
+
+ public JavaCompilationHelper(RuleContext ruleContext, JavaSemantics semantics,
JavaTargetAttributes.Builder attributes) {
this(ruleContext, semantics, getDefaultJavacOptsFromRule(ruleContext), attributes);
}
@@ -152,6 +174,7 @@ public final class JavaCompilationHelper {
builder.setManifestProtoOutput(manifestProtoOutput);
builder.setGensrcOutputJar(gensrcOutputJar);
builder.setOutputDepsProto(outputDepsProto);
+ builder.setAdditionalOutputs(attributes.getAdditionalOutputs());
builder.setMetadata(outputMetadata);
builder.setInstrumentationJars(jacocoInstrumentation);
builder.addSourceFiles(attributes.getSourceFiles());
@@ -164,6 +187,7 @@ public final class JavaCompilationHelper {
builder.setTempDirectory(tempDir(outputJar));
builder.setClassDirectory(classDir(outputJar));
builder.addProcessorPaths(attributes.getProcessorPath());
+ builder.addProcessorPathDirs(attributes.getProcessorPathDirs());
builder.addProcessorNames(attributes.getProcessorNames());
builder.setStrictJavaDeps(attributes.getStrictJavaDeps());
builder.setDirectJars(attributes.getDirectJars());
@@ -240,8 +264,8 @@ public final class JavaCompilationHelper {
private boolean shouldInstrumentJar() {
// TODO(bazel-team): What about source jars?
- return getConfiguration().isCodeCoverageEnabled() && attributes.hasSourceFiles() &&
- InstrumentedFilesCollector.shouldIncludeLocalSources(getRuleContext());
+ return getConfiguration().isCodeCoverageEnabled() && attributes.hasSourceFiles()
+ && InstrumentedFilesCollector.shouldIncludeLocalSources(getRuleContext());
}
private boolean shouldUseHeaderCompilation() {
@@ -302,7 +326,11 @@ public final class JavaCompilationHelper {
builder.setDirectJars(attributes.getDirectJars());
builder.setRuleKind(attributes.getRuleKind());
builder.setTargetLabel(attributes.getTargetLabel());
- builder.setJavaBaseInputs(hostJavabase);
+ builder.setJavaBaseInputs(
+ NestedSetBuilder
+ .fromNestedSet(hostJavabase)
+ .addAll(additionalJavaBaseInputs)
+ .build());
builder.setJavacJar(javaToolchain.getJavac());
builder.build(javaToolchain);
@@ -425,8 +453,8 @@ public final class JavaCompilationHelper {
* targets acting as aliases have to be filtered out.
*/
private boolean generatesOutputDeps() {
- return getJavaConfiguration().getGenerateJavaDeps() &&
- (attributes.hasSourceFiles() || attributes.hasSourceJars());
+ return getJavaConfiguration().getGenerateJavaDeps()
+ && (attributes.hasSourceFiles() || attributes.hasSourceJars());
}
/**
@@ -466,7 +494,11 @@ public final class JavaCompilationHelper {
JavaCompileAction.Builder builder = new JavaCompileAction.Builder(ruleContext, semantics);
builder.setJavaExecutable(
ruleContext.getHostConfiguration().getFragment(Jvm.class).getJavaExecutable());
- builder.setJavaBaseInputs(hostJavabase);
+ builder.setJavaBaseInputs(
+ NestedSetBuilder
+ .fromNestedSet(hostJavabase)
+ .addAll(additionalJavaBaseInputs)
+ .build());
builder.setTargetLabel(ruleContext.getLabel());
return builder;
}
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 eac7e6e80b..d1cc48ec1e 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
@@ -594,7 +594,8 @@ public final class JavaCompileAction extends AbstractAction {
* @param outputJar output jar
* @param compressJar if true compress the output jar
* @param outputDepsProto the proto file capturing dependency information
- * @param processorPath the classpath where javac should search for annotation processors
+ * @param processorPath the classpath files where javac should search for annotation processors
+ * @param processorPathDirs the classpath dirs where javac should search for annotation processors
* @param processorNames the classes that javac should use as annotation processors
* @param messages the message files for translation
* @param resources the set of resources to put into the jar
@@ -614,6 +615,7 @@ public final class JavaCompileAction extends AbstractAction {
final boolean compressJar,
final Artifact outputDepsProto,
final List<Artifact> processorPath,
+ final Set<PathFragment> processorPathDirs,
final List<String> processorNames,
final Collection<Artifact> messages,
final Map<PathFragment, Artifact> resources,
@@ -660,8 +662,13 @@ public final class JavaCompileAction extends AbstractAction {
}
result.add(Joiner.on(pathSeparator).join(extdirs));
}
- if (!processorPath.isEmpty()) {
- result.addJoinExecPaths("--processorpath", pathSeparator, processorPath);
+ if (!processorPath.isEmpty() || !processorPathDirs.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);
@@ -927,6 +934,7 @@ public final class JavaCompileAction extends AbstractAction {
private Artifact gensrcOutputJar;
private Artifact manifestProtoOutput;
private Artifact outputDepsProto;
+ private Collection<Artifact> additionalOutputs;
private Artifact paramFile;
private Artifact metadata;
private final Collection<Artifact> sourceFiles = new ArrayList<>();
@@ -953,6 +961,7 @@ public final class JavaCompileAction extends AbstractAction {
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 String ruleKind;
private Label targetLabel;
@@ -1039,12 +1048,18 @@ public final class JavaCompileAction extends AbstractAction {
Preconditions.checkState(javaExecutable.isAbsolute() ^ !javabaseInputs.isEmpty(),
javaExecutable);
- ArrayList<Artifact> outputs = new ArrayList<>(Collections2.filter(Arrays.asList(
- outputJar,
- metadata,
- gensrcOutputJar,
- manifestProtoOutput,
- outputDepsProto), Predicates.notNull()));
+ ImmutableList.Builder<Artifact> outputsBuilder = ImmutableList.<Artifact>builder()
+ .addAll(
+ new ArrayList<>(Collections2.filter(Arrays.asList(
+ outputJar,
+ metadata,
+ gensrcOutputJar,
+ manifestProtoOutput,
+ outputDepsProto), Predicates.notNull())));
+ if (additionalOutputs != null) {
+ outputsBuilder.addAll(additionalOutputs);
+ }
+ ImmutableList<Artifact> outputs = outputsBuilder.build();
CustomMultiArgv commonJavaBuilderArgs = commonJavaBuilderArgs(
semantics,
@@ -1057,6 +1072,7 @@ public final class JavaCompileAction extends AbstractAction {
compressJar,
outputDepsProto,
processorPath,
+ processorPathDirs,
processorNames,
translations,
resources,
@@ -1180,6 +1196,11 @@ public final class JavaCompileAction extends AbstractAction {
return this;
}
+ public Builder setAdditionalOutputs(Collection<Artifact> outputs) {
+ this.additionalOutputs = outputs;
+ return this;
+ }
+
public Builder setMetadata(Artifact metadata) {
this.metadata = metadata;
return this;
@@ -1293,6 +1314,11 @@ public final class JavaCompileAction extends AbstractAction {
return this;
}
+ public Builder addProcessorPathDirs(Collection<PathFragment> processorPathDirs) {
+ this.processorPathDirs.addAll(processorPathDirs);
+ return this;
+ }
+
public Builder addProcessorNames(Collection<String> processorNames) {
this.processorNames.addAll(processorNames);
return this;
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 300475520d..4f996ad095 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
@@ -70,6 +70,9 @@ public class JavaTargetAttributes {
private final List<Artifact> nativeLibraries = new ArrayList<>();
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<Artifact> apiGeneratingProcessorPath = new LinkedHashSet<>();
@@ -82,6 +85,8 @@ public class JavaTargetAttributes {
private final List<Artifact> classPathResources = new ArrayList<>();
+ private final Set<Artifact> additionalOutputs = new LinkedHashSet<>();
+
private BuildConfiguration.StrictDepsMode strictJavaDeps =
BuildConfiguration.StrictDepsMode.OFF;
private final NestedSetBuilder<Artifact> directJars = NestedSetBuilder.naiveLinkOrder();
@@ -302,6 +307,12 @@ public class JavaTargetAttributes {
return this;
}
+ public Builder addProcessorPathDir(PathFragment dir) {
+ Preconditions.checkArgument(!built);
+ processorPathDirs.add(dir);
+ return this;
+ }
+
public Builder addApiGeneratingProcessorName(String processor) {
Preconditions.checkArgument(!built);
apiGeneratingProcessorNames.add(processor);
@@ -326,6 +337,15 @@ public class JavaTargetAttributes {
return this;
}
+ /**
+ * Adds additional outputs to this target's compile action.
+ */
+ public Builder addAdditionalOutputs(Iterable<Artifact> outputs) {
+ Preconditions.checkArgument(!built);
+ Iterables.addAll(additionalOutputs, outputs);
+ return this;
+ }
+
public JavaTargetAttributes build() {
built = true;
return new JavaTargetAttributes(
@@ -336,6 +356,7 @@ public class JavaTargetAttributes {
bootClassPath,
nativeLibraries,
processorPath,
+ processorPathDirs,
processorNames,
apiGeneratingProcessorPath,
apiGeneratingProcessorNames,
@@ -343,6 +364,7 @@ public class JavaTargetAttributes {
messages,
sourceJars,
classPathResources,
+ additionalOutputs,
directJars.build(),
compileTimeDependencyArtifacts,
ruleKind,
@@ -387,6 +409,7 @@ 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<Artifact> apiGeneratingProcessorPath;
@@ -398,6 +421,8 @@ public class JavaTargetAttributes {
private final ImmutableList<Artifact> classPathResources;
+ private final ImmutableSet<Artifact> additionalOutputs;
+
private final NestedSet<Artifact> directJars;
private final ImmutableList<Artifact> compileTimeDependencyArtifacts;
private final String ruleKind;
@@ -415,6 +440,7 @@ public class JavaTargetAttributes {
List<Artifact> bootClassPath,
List<Artifact> nativeLibraries,
Set<Artifact> processorPath,
+ Set<PathFragment> processorPathDirs,
Set<String> processorNames,
Set<Artifact> apiGeneratingProcessorPath,
Set<String> apiGeneratingProcessorNames,
@@ -422,6 +448,7 @@ public class JavaTargetAttributes {
List<Artifact> messages,
List<Artifact> sourceJars,
List<Artifact> classPathResources,
+ Set<Artifact> additionalOutputs,
NestedSet<Artifact> directJars,
List<Artifact> compileTimeDependencyArtifacts,
String ruleKind,
@@ -440,6 +467,7 @@ public class JavaTargetAttributes {
this.bootClassPath = ImmutableList.copyOf(bootClassPath);
this.nativeLibraries = ImmutableList.copyOf(nativeLibraries);
this.processorPath = ImmutableSet.copyOf(processorPath);
+ this.processorPathDirs = ImmutableSet.copyOf(processorPathDirs);
this.processorNames = ImmutableSet.copyOf(processorNames);
this.apiGeneratingProcessorPath = ImmutableSet.copyOf(apiGeneratingProcessorPath);
this.apiGeneratingProcessorNames = ImmutableSet.copyOf(apiGeneratingProcessorNames);
@@ -447,6 +475,7 @@ public class JavaTargetAttributes {
this.messages = ImmutableList.copyOf(messages);
this.sourceJars = ImmutableList.copyOf(sourceJars);
this.classPathResources = ImmutableList.copyOf(classPathResources);
+ this.additionalOutputs = ImmutableSet.copyOf(additionalOutputs);
this.compileTimeDependencyArtifacts = ImmutableList.copyOf(compileTimeDependencyArtifacts);
this.ruleKind = ruleKind;
this.targetLabel = targetLabel;
@@ -478,6 +507,10 @@ public class JavaTargetAttributes {
return classPathResources;
}
+ public ImmutableSet<Artifact> getAdditionalOutputs() {
+ return additionalOutputs;
+ }
+
private NestedSet<Artifact> getExcludedArtifacts() {
return excludedArtifacts;
}
@@ -520,6 +553,10 @@ public class JavaTargetAttributes {
return processorPath;
}
+ public ImmutableSet<PathFragment> getProcessorPathDirs() {
+ return processorPathDirs;
+ }
+
public Collection<Artifact> getApiGeneratingProcessorPath() {
return apiGeneratingProcessorPath;
}