diff options
author | corysmith <corysmith@google.com> | 2018-08-03 15:38:35 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-08-03 15:40:24 -0700 |
commit | 68cbbe96e8b28e8de50228275f7d2d83c2bb137b (patch) | |
tree | 8764c35ced54abaf6ca5f67c417ebea064a9a51d | |
parent | 0cb8590de83b9250eee198a3f82078aad74f42b5 (diff) |
Moved all external calls to isDataEnabled to DataBindingContext and made it private.
RELNOTES: None
PiperOrigin-RevId: 207335684
12 files changed, 222 insertions, 117 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 959ffe83dd..dc4b78d317 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 @@ -114,23 +114,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { AndroidSdkProvider.verifyPresence(ruleContext); NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.stableOrder(); - JavaCommon javaCommon = - AndroidCommon.createJavaCommonWithAndroidDataBinding(ruleContext, javaSemantics, false); - javaSemantics.checkRule(ruleContext, javaCommon); - javaSemantics.checkForProtoLibraryAndJavaProtoLibraryOnSameProto(ruleContext, javaCommon); - - AndroidCommon androidCommon = new AndroidCommon(javaCommon, /* asNeverLink= */ true); - ResourceDependencies resourceDeps = - ResourceDependencies.fromRuleDeps(ruleContext, /* neverlink= */ false); RuleConfiguredTargetBuilder builder = - init( - ruleContext, - filesBuilder, - resourceDeps, - androidCommon, - cppSemantics, - javaSemantics, - androidSemantics); + init(ruleContext, filesBuilder, cppSemantics, javaSemantics, androidSemantics); return builder.build(); } @@ -175,13 +160,14 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { private static RuleConfiguredTargetBuilder init( RuleContext ruleContext, NestedSetBuilder<Artifact> filesBuilder, - ResourceDependencies resourceDeps, - AndroidCommon androidCommon, CppSemantics cppSemantics, JavaSemantics javaSemantics, AndroidSemantics androidSemantics) throws InterruptedException, RuleErrorException { + ResourceDependencies resourceDeps = + ResourceDependencies.fromRuleDeps(ruleContext, /* neverlink= */ false); + validateRuleContext(ruleContext); NativeLibs nativeLibs = @@ -229,7 +215,6 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { ResourceFilterFactory.fromRuleContextAndAttrs(ruleContext), ruleContext.getExpander().withDataLocations().tokenized("nocompress_extensions"), ruleContext.attributes().get("crunch_png", Type.BOOLEAN), - DataBinding.isEnabled(ruleContext), ruleContext.attributes().isAttributeValueExplicitlySpecified("feature_of") ? ruleContext .getPrerequisite("feature_of", Mode.TARGET, ApkInfo.PROVIDER) @@ -261,6 +246,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { applicationManifest.packBinaryWithDataAndResources( ruleContext, dataContext, + DataBinding.contextFrom(ruleContext), ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_APK), resourceDeps, ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT), @@ -273,15 +259,20 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { dataContext.getAndroidConfig(), ruleContext, shrinkResources), ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_PROCESSED_MANIFEST), ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_ZIP), - DataBinding.isEnabled(ruleContext) - ? DataBinding.getLayoutInfoFile(ruleContext) - : null, featureOfArtifact, featureAfterArtifact); } ruleContext.assertNoErrors(); + JavaCommon javaCommon = + AndroidCommon.createJavaCommonWithAndroidDataBinding( + ruleContext, javaSemantics, resourceApk.asDataBindingContext(), /* isLibrary */ false); + javaSemantics.checkRule(ruleContext, javaCommon); + javaSemantics.checkForProtoLibraryAndJavaProtoLibraryOnSameProto(ruleContext, javaCommon); + + AndroidCommon androidCommon = new AndroidCommon(javaCommon, /* asNeverLink= */ true); + // Remove the library resource JARs from the binary's runtime classpath. // Resource classes from android_library dependencies are replaced by the binary's resource // class. We remove them only at the top level so that resources included by a library that is 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 edeee584dd..cc5c0d3fb8 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 @@ -44,6 +44,7 @@ import com.google.devtools.build.lib.packages.NativeProvider; import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; import com.google.devtools.build.lib.packages.TriState; +import com.google.devtools.build.lib.rules.android.DataBinding.DataBindingContext; import com.google.devtools.build.lib.rules.android.ZipFilterBuilder.CheckHashMismatchMode; import com.google.devtools.build.lib.rules.cpp.AbstractCcLinkParamsStore; import com.google.devtools.build.lib.rules.cpp.CcLinkParams; @@ -483,16 +484,23 @@ public class AndroidCommon { } ImmutableList.Builder<String> javacopts = ImmutableList.builder(); javacopts.addAll(androidSemantics.getCompatibleJavacOptions(ruleContext)); - if (DataBinding.isEnabled(ruleContext)) { - javacopts.addAll(DataBinding.getJavacOpts(ruleContext, isBinary)); - } + + resourceApk + .asDataBindingContext() + .supplyJavaCoptsUsing(ruleContext, isBinary, javacopts::addAll); JavaTargetAttributes.Builder attributes = javaCommon .initCommon(idlHelper.getIdlGeneratedJavaSources(), javacopts.build()) .setBootClassPath(bootclasspath); - if (DataBinding.isEnabled(ruleContext)) { - DataBinding.addAnnotationProcessor(ruleContext, attributes); - } + + resourceApk + .asDataBindingContext() + .supplyAnnotationProcessor( + ruleContext, + (plugin, additionalOutputs) -> { + attributes.addPlugin(plugin); + attributes.addAdditionalOutputs(additionalOutputs); + }); if (excludedRuntimeArtifacts != null) { attributes.addExcludedArtifacts(excludedRuntimeArtifacts); @@ -514,7 +522,9 @@ public class AndroidCommon { jarsProducedForRuntime.add(resourceApk.getResourceJavaClassJar()); } - JavaCompilationHelper helper = initAttributes(attributes, javaSemantics); + JavaCompilationHelper helper = + initAttributes( + attributes, javaSemantics, resourceApk.asDataBindingContext().processDeps(ruleContext)); if (ruleContext.hasErrors()) { return null; } @@ -545,15 +555,16 @@ public class AndroidCommon { } private JavaCompilationHelper initAttributes( - JavaTargetAttributes.Builder attributes, JavaSemantics semantics) { - boolean useDataBinding = DataBinding.isEnabled(ruleContext); + JavaTargetAttributes.Builder attributes, + JavaSemantics semantics, + ImmutableList<Artifact> additionalArtifacts) { JavaCompilationHelper helper = new JavaCompilationHelper( ruleContext, semantics, javaCommon.getJavacOpts(), attributes, - useDataBinding ? DataBinding.processDeps(ruleContext) : ImmutableList.<Artifact>of(), + additionalArtifacts, /*disableStrictDeps=*/ false); helper.addLibrariesToAttributes(javaCommon.targetsTreatedAsDeps(ClasspathType.COMPILE_ONLY)); @@ -845,25 +856,14 @@ public class AndroidCommon { * <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); - + RuleContext ruleContext, + JavaSemantics semantics, + DataBindingContext dataBindingContext, + boolean isLibrary) { ImmutableList<Artifact> srcs = - ruleContext.getPrerequisiteArtifacts("srcs", RuleConfiguredTarget.Mode.TARGET).list(); - if (useDataBinding) { - // Add this rule's annotation processor input. If the rule doesn't have direct resources, - // there's no direct data binding info, so there's strictly no need for annotation processing. - // But it's still important to process the deps' .bin files so any Java class references get - // re-referenced so they don't get filtered out of the compilation classpath by JavaBuilder - // (which filters out classpath .jars that "aren't used": see --reduce_classpath). If data - // binding didn't reprocess a library's data binding expressions redundantly up the dependency - // chain (meaning each depender processes them again as if they were its own), this problem - // wouldn't happen. - Artifact annotationFile = DataBinding.createAnnotationFile(ruleContext); - if (annotationFile != null) { - srcs = ImmutableList.<Artifact>builder().addAll(srcs).add(annotationFile).build(); - } - } + dataBindingContext.addAnnotationFileToSrcs( + ruleContext.getPrerequisiteArtifacts("srcs", RuleConfiguredTarget.Mode.TARGET).list(), + ruleContext); ImmutableList<TransitiveInfoCollection> compileDeps; ImmutableList<TransitiveInfoCollection> runtimeDeps; 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 58ef404322..54e7683d07 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 @@ -135,13 +135,6 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory { AndroidIdlHelper.maybeAddSupportLibProguardConfigs(ruleContext, proguardConfigsbuilder); NestedSet<Artifact> transitiveProguardConfigs = proguardConfigsbuilder.build(); - // JavaCommon and AndroidCommon contain shared helper classes between java_* and android_* - // rules respectively. - JavaCommon javaCommon = - AndroidCommon.createJavaCommonWithAndroidDataBinding(ruleContext, javaSemantics, true); - javaSemantics.checkRule(ruleContext, javaCommon); - AndroidCommon androidCommon = new AndroidCommon(javaCommon); - AndroidConfiguration androidConfig = AndroidCommon.getAndroidConfig(ruleContext); // "Resources" here include actual resources (xmls, drawables, etc), assets, and the manifest. @@ -205,9 +198,7 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory { ruleContext.getImplicitOutputArtifact( AndroidRuleClasses.ANDROID_PROCESSED_MANIFEST), ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_ZIP), - DataBinding.isEnabled(ruleContext) - ? DataBinding.getLayoutInfoFile(ruleContext) - : null); + DataBinding.contextFrom(ruleContext)); } if (ruleContext.hasErrors()) { return null; @@ -223,6 +214,14 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory { StampedAndroidManifest.createEmpty(ruleContext, /* exported = */ false)); } + // JavaCommon and AndroidCommon contain shared helper classes between java_* and android_* + // rules respectively. + JavaCommon javaCommon = + AndroidCommon.createJavaCommonWithAndroidDataBinding( + ruleContext, javaSemantics, resourceApk.asDataBindingContext(), /* isLibrary */ true); + javaSemantics.checkRule(ruleContext, javaCommon); + AndroidCommon androidCommon = new AndroidCommon(javaCommon); + // As android_library makes use of the Java rule compilation pipeline, we collect all // Java-related information here to be passed into the JavaSourceInfoProvider later. JavaTargetAttributes javaTargetAttributes = diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java index 6d02827921..55fe52f37a 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java @@ -122,6 +122,7 @@ public abstract class AndroidLocalTestBase implements RuleConfiguredTargetFactor applicationManifest.packBinaryWithDataAndResources( ruleContext, dataContext, + DataBinding.contextFrom(ruleContext), ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_APK), resourceDependencies, ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT), @@ -133,9 +134,6 @@ public abstract class AndroidLocalTestBase implements RuleConfiguredTargetFactor /* conditionalKeepRules= */ false, ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_PROCESSED_MANIFEST), ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_ZIP), - DataBinding.isEnabled(ruleContext) - ? DataBinding.getLayoutInfoFile(ruleContext) - : null, null, /* featureOfArtifact */ null /* featureAfterArtifact */); } 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 e1567f0209..d1a5e9f257 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 @@ -233,16 +233,17 @@ public class AndroidResourcesProcessorBuilder { public ResourceApk buildWithoutLocalResources( AndroidDataContext dataContext, StampedAndroidManifest manifest, - DataBindingContext androidDataContext) { + DataBindingContext dataBindingContext) { build( - dataContext, AndroidResources.empty(), AndroidAssets.empty(), manifest, androidDataContext); + dataContext, AndroidResources.empty(), AndroidAssets.empty(), manifest, dataBindingContext); return ResourceApk.fromTransitiveResources( resourceDependencies, assetDependencies, manifest.withProcessedManifest(manifestOut == null ? manifest.getManifest() : manifestOut), - rTxtOut); + rTxtOut, + dataBindingContext); } public ResourceContainer build( diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java index 565fd50a89..8d48497115 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java @@ -579,7 +579,6 @@ public abstract class AndroidSkylarkData settings.resourceFilterFactory, settings.noCompressExtensions, crunchPng, - dataBindingEnabled, /* featureOf = */ null, /* featureAfter = */ null, DataBinding.contextFrom(dataBindingEnabled, ctx.getActionConstructionContext())) 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 c9e3daea8c..94e99ac53d 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 @@ -34,9 +34,9 @@ import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory. import com.google.devtools.build.lib.packages.RuleErrorConsumer; import com.google.devtools.build.lib.rules.android.AndroidConfiguration.AndroidAaptVersion; import com.google.devtools.build.lib.rules.android.AndroidConfiguration.AndroidManifestMerger; +import com.google.devtools.build.lib.rules.android.DataBinding.DataBindingContext; import com.google.devtools.build.lib.rules.android.ResourceContainer.Builder.JavaPackageSource; import com.google.devtools.build.lib.syntax.Type; -import com.google.devtools.build.lib.vfs.PathFragment; import java.util.List; import java.util.Map; import java.util.Optional; @@ -371,6 +371,7 @@ public final class ApplicationManifest { public ResourceApk packTestWithDataAndResources( RuleContext ruleContext, AndroidDataContext dataContext, + DataBindingContext dataBindingContext, Artifact resourceApk, ResourceDependencies resourceDeps, @Nullable Artifact rTxt, @@ -430,7 +431,8 @@ public final class ApplicationManifest { AndroidRuleClasses.ANDROID_RESOURCES_CLASS_JAR)) .build(dataContext, processed); - return ResourceApk.of(finalContainer, resourceDeps, proguardCfg, mainDexProguardCfg); + return ResourceApk.of( + finalContainer, resourceDeps, proguardCfg, mainDexProguardCfg, dataBindingContext); } /** Packages up the manifest with resource and assets from the LocalResourceContainer. */ @@ -494,7 +496,7 @@ public final class ApplicationManifest { .setStaticLibraryOut(merged.getStaticLibrary()) .build(dataContext, merged); - return ResourceApk.of(processed, resourceDeps); + return ResourceApk.of(processed, resourceDeps, DataBinding.contextFrom(ruleContext)); } /* Creates an incremental apk from assets and data. */ @@ -552,7 +554,8 @@ public final class ApplicationManifest { // Intentionally skip building an R class JAR - incremental binaries handle this separately. - return ResourceApk.of(processed, resourceDeps, proguardCfg, null); + return ResourceApk.of( + processed, resourceDeps, proguardCfg, null, DataBinding.contextFrom(ruleContext)); } /** Packages up the manifest with resource and assets from the rule and dependent resources. */ @@ -560,6 +563,7 @@ public final class ApplicationManifest { public ResourceApk packBinaryWithDataAndResources( RuleContext ruleContext, AndroidDataContext dataContext, + DataBindingContext dataBindingContext, Artifact resourceApk, ResourceDependencies resourceDeps, @Nullable Artifact rTxt, @@ -571,7 +575,6 @@ public final class ApplicationManifest { boolean conditionalKeepRules, Artifact manifestOut, Artifact mergedResources, - @Nullable Artifact dataBindingInfoZip, @Nullable Artifact featureOf, @Nullable Artifact featureAfter) throws InterruptedException, RuleErrorException { @@ -604,7 +607,7 @@ public final class ApplicationManifest { "resource cycle shrinking can only be enabled for builds with aapt2"); } - ResourceContainer processed = + final AndroidResourcesProcessorBuilder androidResourcesProcessorBuilder = new AndroidResourcesProcessorBuilder() .setLibrary(false) .setApkOut(resourceContainer.getApk()) @@ -618,8 +621,10 @@ public final class ApplicationManifest { .withResourceDependencies(resourceDeps) .setProguardOut(proguardCfg) .setMainDexProguardOut(mainDexProguardCfg) - .conditionalKeepRules(conditionalKeepRules) - .setDataBindingInfoZip(dataBindingInfoZip) + .conditionalKeepRules(conditionalKeepRules); + dataBindingContext.supplyLayoutInfo(androidResourcesProcessorBuilder::setDataBindingInfoZip); + ResourceContainer processed = + androidResourcesProcessorBuilder .setApplicationId(manifestValues.get("applicationId")) .setVersionCode(manifestValues.get("versionCode")) .setVersionName(manifestValues.get("versionName")) @@ -642,7 +647,8 @@ public final class ApplicationManifest { AndroidRuleClasses.ANDROID_RESOURCES_CLASS_JAR)) .build(dataContext, processed); - return ResourceApk.of(finalContainer, resourceDeps, proguardCfg, mainDexProguardCfg); + return ResourceApk.of( + finalContainer, resourceDeps, proguardCfg, mainDexProguardCfg, dataBindingContext); } public ResourceApk packLibraryWithDataAndResources( @@ -653,7 +659,7 @@ public final class ApplicationManifest { Artifact symbols, Artifact manifestOut, Artifact mergedResources, - @Nullable Artifact dataBindingInfoZip) + DataBindingContext dataBindingContext) throws InterruptedException, RuleErrorException { AndroidResources resources = AndroidResources.from(ruleContext, "resource_files"); AndroidAssets assets = AndroidAssets.from(ruleContext); @@ -683,7 +689,7 @@ public final class ApplicationManifest { AndroidRuleClasses.ANDROID_RESOURCES_AAPT2_LIBRARY_APK)); } - ResourceContainer resourceContainer = builder.build(); + final ResourceContainer resourceContainer = builder.build(); Artifact rJavaClassJar = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_CLASS_JAR); @@ -701,33 +707,31 @@ public final class ApplicationManifest { .setOutput(resourceContainer.getSymbols()) .setCompiledSymbolsOutput(resourceContainer.getCompiledSymbols()); - if (dataBindingInfoZip != null && resourceContainer.getCompiledSymbols() != null) { - PathFragment unusedInfo = dataBindingInfoZip.getRootRelativePath(); + if (resourceContainer.getCompiledSymbols() != null) { // TODO(corysmith): Centralize the data binding processing and zipping into a single // action. Data binding processing needs to be triggered here as well as the merger to // avoid aapt2 from throwing an error during compilation. - parsingBuilder - .setDataBindingInfoZip( - ruleContext.getDerivedArtifact( - unusedInfo.replaceName(unusedInfo.getBaseName() + "_unused.zip"), - dataBindingInfoZip.getRoot())) - .setManifest(resourceContainer.getManifest()) - .setJavaPackage(resourceContainer.getJavaPackage()); + dataBindingContext.supplyLayoutInfo( + layoutInfo -> + parsingBuilder + .setDataBindingInfoZip( + ruleContext.getUniqueDirectoryArtifact("dummydatabinding", "unused.zip")) + .setManifest(resourceContainer.getManifest()) + .setJavaPackage(resourceContainer.getJavaPackage())); } - resourceContainer = parsingBuilder.buildAndUpdate(dataContext, resourceContainer); + ResourceContainer parsedResourceContainer = + parsingBuilder.buildAndUpdate(dataContext, resourceContainer); ResourceContainer merged = new AndroidResourceMergingActionBuilder() - .setJavaPackage(resourceContainer.getJavaPackage()) + .setJavaPackage(parsedResourceContainer.getJavaPackage()) .withDependencies(resourceDeps) .setThrowOnResourceConflict(androidConfiguration.throwOnResourceConflict()) .setUseCompiledMerge(skipParsingAction) - .setDataBindingInfoZip(dataBindingInfoZip) .setMergedResourcesOut(mergedResources) .setManifestOut(manifestOut) .setClassJarOut(rJavaClassJar) - .setDataBindingInfoZip(dataBindingInfoZip) - .build(dataContext, resourceContainer); + .build(dataContext, parsedResourceContainer); ResourceContainer processed = new AndroidResourceValidatorActionBuilder() @@ -736,16 +740,16 @@ public final class ApplicationManifest { .setMergedResources(mergedResources) .setRTxtOut(merged.getRTxt()) .setSourceJarOut(merged.getJavaSourceJar()) - .setApkOut(resourceContainer.getApk()) - // aapt2 related artifacts. Will be generated if the targetAaptVersion is AAPT2. + .setApkOut(parsedResourceContainer.getApk()) .withDependencies(resourceDeps) + // aapt2 related artifacts. Will be generated if the targetAaptVersion is AAPT2. .setCompiledSymbols(merged.getCompiledSymbols()) .setAapt2RTxtOut(merged.getAapt2RTxt()) .setAapt2SourceJarOut(merged.getAapt2JavaSourceJar()) .setStaticLibraryOut(merged.getStaticLibrary()) .build(dataContext, merged); - return ResourceApk.of(processed, resourceDeps); + return ResourceApk.of(processed, resourceDeps, dataBindingContext); } public Artifact getManifest() { 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 9f295ba832..cb99971ea5 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 @@ -33,6 +33,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.function.BiConsumer; import java.util.function.Consumer; /** @@ -67,7 +68,52 @@ public final class DataBinding { /** Contains Android Databinding configuration and resource generation information. */ public interface DataBindingContext { + + /** + * 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. + */ void supplyLayoutInfo(Consumer<Artifact> consumer); + + /** The javac flags that are needed to configure data binding's annotation processor. */ + void supplyJavaCoptsUsing( + RuleContext ruleContext, boolean isBinary, Consumer<Iterable<String>> consumer); + + /** + * 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. + */ + void supplyAnnotationProcessor( + RuleContext ruleContext, BiConsumer<JavaPluginInfoProvider, Iterable<Artifact>> consumer); + + ImmutableList<Artifact> processDeps(RuleContext ruleContext); + + ImmutableList<Artifact> addAnnotationFileToSrcs( + ImmutableList<Artifact> srcs, RuleContext ruleContext); } private static final class EnabledDataBindingContext implements DataBindingContext { @@ -84,6 +130,38 @@ public final class DataBinding { } @Override + public void supplyJavaCoptsUsing( + RuleContext ruleContext, boolean isBinary, Consumer<Iterable<String>> consumer) { + consumer.accept(getJavacOpts(ruleContext, isBinary)); + } + + @Override + public void supplyAnnotationProcessor( + RuleContext ruleContext, BiConsumer<JavaPluginInfoProvider, Iterable<Artifact>> consumer) { + consumer.accept( + JavaInfo.getProvider( + JavaPluginInfoProvider.class, + ruleContext.getPrerequisite( + DATABINDING_ANNOTATION_PROCESSOR_ATTR, RuleConfiguredTarget.Mode.HOST)), + getMetadataOutputs(ruleContext)); + } + + @Override + public ImmutableList<Artifact> processDeps(RuleContext ruleContext) { + return DataBinding.processDeps(ruleContext); + } + + @Override + public ImmutableList<Artifact> addAnnotationFileToSrcs( + ImmutableList<Artifact> srcs, RuleContext ruleContext) { + final Artifact annotationFile = createAnnotationFile(ruleContext); + if (annotationFile != null) { + return ImmutableList.<Artifact>builder().addAll(srcs).add(annotationFile).build(); + } + return ImmutableList.of(); + } + + @Override public boolean equals(Object o) { if (this == o) { return true; @@ -102,11 +180,29 @@ public final class DataBinding { } private static final class DisabledDataBindingContext implements DataBindingContext { - @Override public void supplyLayoutInfo(Consumer<Artifact> consumer) { // pass } + + @Override + public void supplyJavaCoptsUsing( + RuleContext ruleContext, boolean isBinary, Consumer<Iterable<String>> consumer) {} + + @Override + public void supplyAnnotationProcessor( + RuleContext ruleContext, BiConsumer<JavaPluginInfoProvider, Iterable<Artifact>> consumer) {} + + @Override + public ImmutableList<Artifact> processDeps(RuleContext ruleContext) { + return ImmutableList.of(); + } + + @Override + public ImmutableList<Artifact> addAnnotationFileToSrcs( + ImmutableList<Artifact> srcs, RuleContext ruleContext) { + return srcs; + } } /** Supplies a databinding context from a rulecontext. */ @@ -117,7 +213,7 @@ public final class DataBinding { return asDisabledDataBindingContext(); } - /** Supplies a databinding context from a rulecontext. */ + /** Supplies a databinding context from an action context. */ public static DataBindingContext contextFrom(boolean enabled, ActionConstructionContext context) { if (enabled) { return asEnabledDataBindingContextFrom(context); @@ -131,7 +227,7 @@ public final class DataBinding { return new EnabledDataBindingContext(actionContext); } - /** Supplies a disabled (no-op) DataBindingContext from the action context. */ + /** Supplies a disabled (no-op) DataBindingContext. */ public static DataBindingContext asDisabledDataBindingContext() { return new DisabledDataBindingContext(); } @@ -370,7 +466,7 @@ public final class DataBinding { * @return the deps' metadata outputs. These need to be staged as compilation inputs to the * current rule. */ - static ImmutableList<Artifact> processDeps(RuleContext ruleContext) { + private static ImmutableList<Artifact> processDeps(RuleContext ruleContext) { ImmutableList.Builder<Artifact> dataBindingJavaInputs = ImmutableList.<Artifact>builder(); if (AndroidResources.definesAndroidResources(ruleContext.attributes())) { dataBindingJavaInputs.add(DataBinding.getLayoutInfoFile(ruleContext)); diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ProcessedAndroidData.java b/src/main/java/com/google/devtools/build/lib/rules/android/ProcessedAndroidData.java index f69128afd1..d0bd385c0f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/ProcessedAndroidData.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/ProcessedAndroidData.java @@ -67,7 +67,6 @@ public class ProcessedAndroidData { ResourceFilterFactory resourceFilterFactory, List<String> noCompressExtensions, boolean crunchPng, - boolean dataBindingEnabled, @Nullable Artifact featureOf, @Nullable Artifact featureAfter, DataBindingContext dataBindingContext) @@ -90,12 +89,9 @@ public class ProcessedAndroidData { AndroidBinary.createMainDexProguardSpec( dataContext.getLabel(), dataContext.getActionConstructionContext())) .conditionalKeepRules(conditionalKeepRules) - .setDataBindingInfoZip( - dataBindingEnabled - ? DataBinding.getLayoutInfoFile(dataContext.getActionConstructionContext()) - : null) .setFeatureOf(featureOf) .setFeatureAfter(featureAfter); + dataBindingContext.supplyLayoutInfo(builder::setDataBindingInfoZip); return buildActionForBinary( dataContext, dataBindingContext, diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java index 2ab400cf93..acb9d1d40a 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java @@ -50,16 +50,21 @@ public final class ResourceApk { private final Artifact rTxt; @Nullable private final Artifact resourceProguardConfig; @Nullable private final Artifact mainDexProguardConfig; + private final DataBindingContext dataBindingContext; - static ResourceApk of(ResourceContainer resourceContainer, ResourceDependencies resourceDeps) { - return of(resourceContainer, resourceDeps, null, null); + static ResourceApk of( + ResourceContainer resourceContainer, + ResourceDependencies resourceDeps, + DataBindingContext dataBindingContext) { + return of(resourceContainer, resourceDeps, null, null, dataBindingContext); } static ResourceApk of( ResourceContainer resourceContainer, ResourceDependencies resourceDeps, @Nullable Artifact resourceProguardConfig, - @Nullable Artifact mainDexProguardConfig) { + @Nullable Artifact mainDexProguardConfig, + DataBindingContext dataBindingContext) { return new ResourceApk( resourceContainer.getApk(), resourceContainer.getJavaSourceJar(), @@ -72,7 +77,8 @@ public final class ResourceApk { resourceContainer.getProcessedManifest(), resourceContainer.getRTxt(), resourceProguardConfig, - mainDexProguardConfig); + mainDexProguardConfig, + dataBindingContext); } public static ResourceApk of( @@ -92,7 +98,8 @@ public final class ResourceApk { resources.getProcessedManifest(), resources.getRTxt(), resourceProguardConfig, - mainDexProguardConfig); + mainDexProguardConfig, + resources.asDataBindingContext()); } private ResourceApk( @@ -107,7 +114,8 @@ public final class ResourceApk { ProcessedAndroidManifest manifest, Artifact rTxt, @Nullable Artifact resourceProguardConfig, - @Nullable Artifact mainDexProguardConfig) { + @Nullable Artifact mainDexProguardConfig, + DataBindingContext dataBindingContext) { this.resourceApk = resourceApk; this.resourceJavaSrcJar = resourceJavaSrcJar; this.resourceJavaClassJar = resourceJavaClassJar; @@ -120,6 +128,7 @@ public final class ResourceApk { this.rTxt = rTxt; this.resourceProguardConfig = resourceProguardConfig; this.mainDexProguardConfig = mainDexProguardConfig; + this.dataBindingContext = dataBindingContext; } ResourceApk withApk(Artifact apk) { @@ -135,7 +144,8 @@ public final class ResourceApk { manifest, rTxt, resourceProguardConfig, - mainDexProguardConfig); + mainDexProguardConfig, + asDataBindingContext()); } public Artifact getArtifact() { @@ -179,7 +189,8 @@ public final class ResourceApk { ResourceDependencies resourceDeps, AssetDependencies assetDeps, ProcessedAndroidManifest manifest, - Artifact rTxt) { + Artifact rTxt, + DataBindingContext dataBindingContext) { return new ResourceApk( null, null, @@ -192,7 +203,8 @@ public final class ResourceApk { manifest, rTxt, null, - null); + null, + dataBindingContext); } public Artifact getResourceProguardConfig() { @@ -211,6 +223,10 @@ public final class ResourceApk { return assetDeps; } + public DataBindingContext asDataBindingContext() { + return dataBindingContext; + } + /** * Creates an provider from the resources in the ResourceApk. * @@ -266,7 +282,7 @@ public final class ResourceApk { // targets // so we can validate there are no asset merging conflicts. builder.addOutputGroup(OutputGroupInfo.HIDDEN_TOP_LEVEL, assetsInfo.getValidationResult()); - } + } if (manifestInfo.isPresent() && !isLibrary) { builder.addNativeDeclaredProvider( diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ValidatedAndroidResources.java b/src/main/java/com/google/devtools/build/lib/rules/android/ValidatedAndroidResources.java index c70239b8b3..172dcee898 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/ValidatedAndroidResources.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/ValidatedAndroidResources.java @@ -194,12 +194,12 @@ public class ValidatedAndroidResources extends MergedAndroidResources return new ValidatedAndroidResources( new MergedAndroidResources( new ParsedAndroidResources( - // Null out databinding to avoid accidentally propagating ActionCreationContext new AndroidResources(getResources(), getResourceRoots()), getSymbols(), getCompiledSymbols(), getLabel(), getStampedManifest(), + // Null out databinding to avoid accidentally propagating ActionCreationContext null), getMergedResources(), getClassJar(), diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidResourcesTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidResourcesTest.java index f2169b5f4d..d1f9db8166 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidResourcesTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidResourcesTest.java @@ -496,7 +496,6 @@ public class AndroidResourcesTest extends ResourceTestBase { ResourceFilterFactory.empty(), ImmutableList.of(), false, - false, null, null, DataBinding.contextFrom(ruleContext)) @@ -549,6 +548,12 @@ public class AndroidResourcesTest extends ResourceTestBase { private ParsedAndroidResources makeParsedResources(RuleContext ruleContext) throws RuleErrorException, InterruptedException { + return makeParsedResources(ruleContext, DataBinding.asDisabledDataBindingContext()); + } + + private ParsedAndroidResources makeParsedResources( + RuleContext ruleContext, DataBindingContext dataBindingContext) + throws RuleErrorException, InterruptedException { ImmutableList<Artifact> resources = getResources("values-en/foo.xml", "drawable-hdpi/bar.png"); return new AndroidResources( resources, AndroidResources.getResourceRoots(ruleContext, resources, "resource_files")) @@ -556,7 +561,7 @@ public class AndroidResourcesTest extends ResourceTestBase { AndroidDataContext.forNative(ruleContext), getManifest(), AndroidAaptVersion.chooseTargetAaptVersion(ruleContext), - DataBinding.contextFrom(ruleContext)); + dataBindingContext); } private ProcessedAndroidManifest getManifest() { |