diff options
Diffstat (limited to 'src/main')
11 files changed, 219 insertions, 118 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java index 32c5989cf1..11ddc1bd61 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java @@ -61,12 +61,13 @@ public class AndroidAssets { } } - /** Collects this rule's android assets. */ + /** Collects this rule's android assets, based on rule attributes. */ public static AndroidAssets from(RuleContext ruleContext) throws RuleErrorException { return from(ruleContext, getAssetTargets(ruleContext), getAssetDir(ruleContext)); } - static AndroidAssets from( + /** Collects Android assets from the specified values */ + public static AndroidAssets from( RuleErrorConsumer errorConsumer, @Nullable Iterable<? extends TransitiveInfoCollection> assetTargets, @Nullable PathFragment assetsDir) 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 eed11af544..46198628f7 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 @@ -202,13 +202,16 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { applicationManifest = ApplicationManifest.fromExplicitManifest(ruleContext, manifest.getManifest()); + AndroidAaptVersion aaptVersion = AndroidAaptVersion.chooseTargetAaptVersion(ruleContext); resourceApk = ProcessedAndroidData.processBinaryDataFrom( ruleContext, manifest, /* conditionalKeepRules = */ shouldShrinkResourceCycles( - ruleContext, shrinkResources)) - .generateRClass(ruleContext); + ruleContext, shrinkResources), + applicationManifest.getManifestValues(), + aaptVersion) + .generateRClass(ruleContext, aaptVersion); } else { applicationManifest = androidSemantics.getManifestForRule(ruleContext).mergeWith(ruleContext, resourceDeps); diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinaryMobileInstall.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinaryMobileInstall.java index 64d0cd7bf2..1042e2c161 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinaryMobileInstall.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinaryMobileInstall.java @@ -76,7 +76,8 @@ public final class AndroidBinaryMobileInstall { manifest.addMobileInstallStubApplication(ruleContext), ruleContext.getImplicitOutputArtifact( AndroidRuleClasses.ANDROID_INCREMENTAL_RESOURCES_APK), - "incremental") + "incremental", + applicationManifest.getManifestValues()) // Intentionally skip building an R class JAR - incremental binaries handle this // separately. .withValidatedResources(null); @@ -86,7 +87,8 @@ public final class AndroidBinaryMobileInstall { ruleContext, manifest.createSplitManifest(ruleContext, "android_resources", false), getMobileInstallArtifact(ruleContext, "android_resources.ap_"), - "incremental_split") + "incremental_split", + applicationManifest.getManifestValues()) // Intentionally skip building an R class JAR - incremental binaries handle this // separately. .withValidatedResources(null); 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 d9f1feeaeb..c88e36990b 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 @@ -36,6 +36,7 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.packages.BuildType; +import com.google.devtools.build.lib.rules.android.AndroidConfiguration.AndroidAaptVersion; import com.google.devtools.build.lib.rules.java.ClasspathConfiguredFragment; import com.google.devtools.build.lib.rules.java.DeployArchiveBuilder; import com.google.devtools.build.lib.rules.java.JavaCommon; @@ -93,9 +94,14 @@ public abstract class AndroidLocalTestBase implements RuleConfiguredTargetFactor StampedAndroidManifest manifest = AndroidManifest.from(ruleContext).mergeWithDeps(ruleContext); + AndroidAaptVersion aaptVersion = AndroidAaptVersion.chooseTargetAaptVersion(ruleContext); resourceApk = - ProcessedAndroidData.processLocalTestDataFrom(ruleContext, manifest) - .generateRClass(ruleContext); + ProcessedAndroidData.processLocalTestDataFrom( + ruleContext, + manifest, + ApplicationManifest.getManifestValues(ruleContext), + aaptVersion) + .generateRClass(ruleContext, aaptVersion); } else { // Create the final merged manifest ResourceDependencies resourceDependencies = diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifest.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifest.java index dfe7a014d0..b90d28b03d 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifest.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifest.java @@ -13,7 +13,6 @@ // limitations under the License. package com.google.devtools.build.lib.rules.android; -import com.google.common.annotations.VisibleForTesting; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; @@ -21,6 +20,7 @@ import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory. import com.google.devtools.build.lib.rules.java.JavaUtil; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.vfs.PathFragment; +import java.util.Map; import java.util.Objects; import javax.annotation.Nullable; @@ -91,8 +91,11 @@ public class AndroidManifest { this(manifest, other.pkg, other.exported); } - @VisibleForTesting - AndroidManifest(Artifact manifest, @Nullable String pkg, boolean exported) { + /** + * Creates a manifest wrapper without doing any processing. From within a rule, use {@link + * #from(RuleContext, AndroidSemantics)} instead. + */ + public AndroidManifest(Artifact manifest, @Nullable String pkg, boolean exported) { this.manifest = manifest; this.pkg = pkg; this.exported = exported; @@ -112,11 +115,15 @@ public class AndroidManifest { * <p>If no manifest values are specified, the manifest will remain unstamped. */ public StampedAndroidManifest stampWithManifestValues(RuleContext ruleContext) { - return mergeWithDeps(ruleContext, ResourceDependencies.empty()); + return mergeWithDeps( + ruleContext, + ResourceDependencies.empty(), + ApplicationManifest.getManifestValues(ruleContext), + ApplicationManifest.useLegacyMerging(ruleContext)); } /** - * Merges the manifest with any dependent manifests. + * Merges the manifest with any dependent manifests, extracted from rule attributes. * * <p>The manifest will also be stamped with any manifest values specified in the target's * attributes @@ -126,17 +133,20 @@ public class AndroidManifest { */ public StampedAndroidManifest mergeWithDeps(RuleContext ruleContext) { return mergeWithDeps( - ruleContext, ResourceDependencies.fromRuleDeps(ruleContext, /* neverlink = */ false)); + ruleContext, + ResourceDependencies.fromRuleDeps(ruleContext, /* neverlink = */ false), + ApplicationManifest.getManifestValues(ruleContext), + ApplicationManifest.useLegacyMerging(ruleContext)); } - private StampedAndroidManifest mergeWithDeps( - RuleContext ruleContext, ResourceDependencies resourceDeps) { + public StampedAndroidManifest mergeWithDeps( + RuleContext ruleContext, + ResourceDependencies resourceDeps, + Map<String, String> manifestValues, + boolean useLegacyMerger) { Artifact newManifest = ApplicationManifest.maybeMergeWith( - ruleContext, - manifest, - resourceDeps, - ApplicationManifest.getManifestValues(ruleContext)) + ruleContext, manifest, resourceDeps, manifestValues, useLegacyMerger, pkg) .orElse(manifest); return new StampedAndroidManifest(newManifest, pkg, exported); @@ -165,7 +175,7 @@ public class AndroidManifest { } /** Gets the default Java package */ - static String getDefaultPackage(RuleContext ruleContext) { + public static String getDefaultPackage(RuleContext ruleContext) { PathFragment dummyJar = ruleContext.getPackageDirectory().getChild("Dummy.jar"); return getJavaPackageFromPath(ruleContext, dummyJar); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResources.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResources.java index 7858091b3d..842b4ed5ab 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResources.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResources.java @@ -138,7 +138,7 @@ public class AndroidResources { resourcesAttr); } - static AndroidResources from( + public static AndroidResources from( RuleErrorConsumer errorConsumer, Iterable<FileProvider> resourcesTargets, String resourcesAttr) 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 cb13f6a559..389115afd1 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 @@ -19,6 +19,7 @@ import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.FileProvider; import com.google.devtools.build.lib.analysis.skylark.SkylarkRuleContext; +import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.events.Location; @@ -396,16 +397,7 @@ public abstract class AndroidSkylarkData { aaptVersion) .validate(ctx.getRuleContext(), aaptVersion); - JavaInfo javaInfo = - JavaInfo.Builder.create() - .setNeverlink(true) - .addProvider( - JavaCompilationInfoProvider.class, - new JavaCompilationInfoProvider.Builder() - .setCompilationClasspath( - NestedSetBuilder.create(Order.NAIVE_LINK_ORDER, validated.getClassJar())) - .build()) - .build(); + JavaInfo javaInfo = getJavaInfoForRClassJar(validated.getClassJar()); return SkylarkDict.of( /* env = */ null, @@ -742,8 +734,35 @@ public abstract class AndroidSkylarkData { .build()); } + public static SkylarkDict<NativeProvider<?>, NativeInfo> getNativeInfosFrom( + ResourceApk resourceApk, Label label) { + ImmutableMap.Builder<NativeProvider<?>, NativeInfo> builder = ImmutableMap.builder(); + + builder.put(AndroidResourcesInfo.PROVIDER, resourceApk.toResourceInfo(label)); + + resourceApk + .toAssetsInfo(label) + .ifPresent(info -> builder.put(AndroidAssetsInfo.PROVIDER, info)); + resourceApk.toManifestInfo().ifPresent(info -> builder.put(AndroidManifestInfo.PROVIDER, info)); + + builder.put(JavaInfo.PROVIDER, getJavaInfoForRClassJar(resourceApk.getResourceJavaClassJar())); + + return SkylarkDict.copyOf(/* env = */ null, builder.build()); + } + + private static JavaInfo getJavaInfoForRClassJar(Artifact rClassJar) { + return JavaInfo.Builder.create() + .setNeverlink(true) + .addProvider( + JavaCompilationInfoProvider.class, + new JavaCompilationInfoProvider.Builder() + .setCompilationClasspath(NestedSetBuilder.create(Order.NAIVE_LINK_ORDER, rClassJar)) + .build()) + .build(); + } + /** Checks if a "Noneable" object passed by Skylark is "None", which Java should treat as null. */ - private static boolean isNone(Object object) { + public static boolean isNone(Object object) { return object == Runtime.NONE; } @@ -760,7 +779,7 @@ public abstract class AndroidSkylarkData { * @return {@code null}, if the noneable argument was None, or the cast object, otherwise. */ @Nullable - private static <T> T fromNoneable(Object object, Class<T> clazz) { + public static <T> T fromNoneable(Object object, Class<T> clazz) { if (isNone(object)) { return null; } @@ -768,7 +787,7 @@ public abstract class AndroidSkylarkData { return clazz.cast(object); } - private static <T> T fromNoneableOrDefault(Object object, Class<T> clazz, T defaultValue) { + public static <T> T fromNoneableOrDefault(Object object, Class<T> clazz, T defaultValue) { T value = fromNoneable(object, clazz); if (value == null) { return defaultValue; @@ -784,7 +803,7 @@ public abstract class AndroidSkylarkData { * casts it to a list with the appropriate generic. */ @Nullable - private static <T> List<T> listFromNoneable(Object object, Class<T> clazz) throws EvalException { + public static <T> List<T> listFromNoneable(Object object, Class<T> clazz) throws EvalException { SkylarkList<?> asList = fromNoneable(object, SkylarkList.class); if (asList == null) { return null; @@ -803,7 +822,7 @@ public abstract class AndroidSkylarkData { return SkylarkList.createImmutable(value); } - private static <T extends NativeInfo> SkylarkList<T> getProviders( + public static <T extends NativeInfo> SkylarkList<T> getProviders( SkylarkList<ConfiguredTarget> targets, NativeProvider<T> provider) { return SkylarkList.createImmutable( targets 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 783f0f284c..deb2cb530e 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 @@ -192,7 +192,7 @@ public final class ApplicationManifest { * * @return an artifact for the generated manifest */ - static Artifact generateManifest(RuleContext ruleContext, String manifestPackage) { + public static Artifact generateManifest(RuleContext ruleContext, String manifestPackage) { Artifact generatedManifest = ruleContext.getUniqueDirectoryArtifact( ruleContext.getRule().getName() + "_generated", @@ -216,19 +216,35 @@ public final class ApplicationManifest { return generatedManifest; } + /** Gets a map of manifest values from this rule's 'manifest_values' attribute */ static ImmutableMap<String, String> getManifestValues(RuleContext context) { + return getManifestValues( + context, + context.attributes().isAttributeValueExplicitlySpecified("manifest_values") + ? context.attributes().get("manifest_values", Type.STRING_DICT) + : null); + } + + /** Gets and expands an expanded map of manifest values from some raw map of manifest values. */ + static ImmutableMap<String, String> getManifestValues( + RuleContext ruleContext, @Nullable Map<String, String> rawMap) { Map<String, String> manifestValues = new TreeMap<>(); - if (context.attributes().isAttributeValueExplicitlySpecified("manifest_values")) { - manifestValues.putAll(context.attributes().get("manifest_values", Type.STRING_DICT)); + if (rawMap != null) { + manifestValues.putAll(rawMap); } for (String variable : manifestValues.keySet()) { manifestValues.put( - variable, context.getExpander().expand("manifest_values", manifestValues.get(variable))); + variable, + ruleContext.getExpander().expand("manifest_values", manifestValues.get(variable))); } return ImmutableMap.copyOf(manifestValues); } + public ImmutableMap<String, String> getManifestValues() { + return manifestValues; + } + private final Artifact manifest; private final ImmutableMap<String, String> manifestValues; private final AndroidAaptVersion targetAaptVersion; @@ -241,7 +257,13 @@ public final class ApplicationManifest { } public ApplicationManifest mergeWith(RuleContext ruleContext, ResourceDependencies resourceDeps) { - return maybeMergeWith(ruleContext, manifest, resourceDeps, manifestValues) + return maybeMergeWith( + ruleContext, + manifest, + resourceDeps, + manifestValues, + useLegacyMerging(ruleContext), + AndroidCommon.getJavaPackage(ruleContext)) .map(merged -> new ApplicationManifest(ruleContext, merged, targetAaptVersion)) .orElse(this); } @@ -250,11 +272,14 @@ public final class ApplicationManifest { RuleContext ruleContext, Artifact primaryManifest, ResourceDependencies resourceDeps, - Map<String, String> manifestValues) { + Map<String, String> manifestValues, + boolean useLegacyMerging, + String customPackage) { Map<Artifact, Label> mergeeManifests = getMergeeManifests(resourceDeps.getResourceContainers()); - if (useLegacyMerging(ruleContext)) { + if (useLegacyMerging) { if (!mergeeManifests.isEmpty()) { + Artifact outputManifest = ruleContext.getUniqueDirectoryArtifact( ruleContext.getRule().getName() + "_merged", @@ -285,7 +310,7 @@ public final class ApplicationManifest { .setMergeeManifests(mergeeManifests) .setLibrary(false) .setManifestValues(manifestValues) - .setCustomPackage(AndroidCommon.getJavaPackage(ruleContext)) + .setCustomPackage(customPackage) .setManifestOutput(outputManifest) .setLogOut(mergeLog) .build(ruleContext); @@ -295,24 +320,30 @@ public final class ApplicationManifest { return Optional.empty(); } - private static boolean useLegacyMerging(RuleContext ruleContext) { - boolean legacy = false; - if (ruleContext.isLegalFragment(AndroidConfiguration.class) - && ruleContext.getRule().isAttrDefined("manifest_merger", STRING)) { - AndroidManifestMerger merger = - AndroidManifestMerger.fromString(ruleContext.attributes().get("manifest_merger", STRING)); - if (merger == null) { - merger = ruleContext.getFragment(AndroidConfiguration.class).getManifestMerger(); - } - if (merger == AndroidManifestMerger.LEGACY) { - ruleContext.ruleWarning( - "manifest_merger 'legacy' is deprecated. Please update to 'android'.\n" - + "See https://developer.android.com/studio/build/manifest-merge.html for more " - + "information about the manifest merger."); - } - legacy = merger == AndroidManifestMerger.LEGACY; + /** Checks if the legacy manifest merger should be used, based on a rule attribute */ + static boolean useLegacyMerging(RuleContext ruleContext) { + return ruleContext.isLegalFragment(AndroidConfiguration.class) + && ruleContext.getRule().isAttrDefined("manifest_merger", STRING) + && useLegacyMerging(ruleContext, ruleContext.attributes().get("manifest_merger", STRING)); + } + + /** + * Checks if the legacy manifest merger should be used, based on an optional string specifying the + * merger to use. + */ + public static boolean useLegacyMerging(RuleContext ruleContext, @Nullable String mergerString) { + AndroidManifestMerger merger = AndroidManifestMerger.fromString(mergerString); + if (merger == null) { + merger = ruleContext.getFragment(AndroidConfiguration.class).getManifestMerger(); + } + if (merger == AndroidManifestMerger.LEGACY) { + ruleContext.ruleWarning( + "manifest_merger 'legacy' is deprecated. Please update to 'android'.\n" + + "See https://developer.android.com/studio/build/manifest-merge.html for more " + + "information about the manifest merger."); } - return legacy; + + return merger == AndroidManifestMerger.LEGACY; } private static Map<Artifact, Label> getMergeeManifests( diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AssetDependencies.java b/src/main/java/com/google/devtools/build/lib/rules/android/AssetDependencies.java index cc9c8dc5ae..1cfe929fc6 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AssetDependencies.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AssetDependencies.java @@ -38,14 +38,15 @@ public class AssetDependencies { private final NestedSet<Artifact> transitiveAssets; private final NestedSet<Artifact> transitiveSymbols; - static AssetDependencies fromRuleDeps(RuleContext ruleContext, boolean neverlink) { + public static AssetDependencies fromRuleDeps(RuleContext ruleContext, boolean neverlink) { return fromProviders( AndroidCommon.getTransitivePrerequisites( ruleContext, Mode.TARGET, AndroidAssetsInfo.PROVIDER), neverlink); } - static AssetDependencies fromProviders(Iterable<AndroidAssetsInfo> providers, boolean neverlink) { + public static AssetDependencies fromProviders( + Iterable<AndroidAssetsInfo> providers, boolean neverlink) { NestedSetBuilder<ParsedAndroidAssets> direct = NestedSetBuilder.naiveLinkOrder(); NestedSetBuilder<ParsedAndroidAssets> transitive = NestedSetBuilder.naiveLinkOrder(); NestedSetBuilder<Artifact> assets = NestedSetBuilder.naiveLinkOrder(); 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 8a0d0e66ab..438f12cbc0 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 @@ -13,6 +13,7 @@ // limitations under the License. package com.google.devtools.build.lib.rules.android; +import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.config.CompilationMode; @@ -52,7 +53,11 @@ public class ProcessedAndroidData { /** Processes Android data (assets, resources, and manifest) for android_binary targets. */ public static ProcessedAndroidData processBinaryDataFrom( - RuleContext ruleContext, StampedAndroidManifest manifest, boolean conditionalKeepRules) + RuleContext ruleContext, + StampedAndroidManifest manifest, + boolean conditionalKeepRules, + Map<String, String> manifestValues, + AndroidAaptVersion aaptVersion) throws RuleErrorException, InterruptedException { if (conditionalKeepRules && AndroidAaptVersion.chooseTargetAaptVersion(ruleContext) != AndroidAaptVersion.AAPT2) { @@ -61,7 +66,7 @@ public class ProcessedAndroidData { } AndroidResourcesProcessorBuilder builder = - builderForNonIncrementalTopLevelTarget(ruleContext, manifest) + builderForNonIncrementalTopLevelTarget(ruleContext, manifest, manifestValues, aaptVersion) .setUseCompiledResourcesForMerge( AndroidAaptVersion.chooseTargetAaptVersion(ruleContext) == AndroidAaptVersion.AAPT2 && AndroidCommon.getAndroidConfig(ruleContext).skipParsingAction()) @@ -95,11 +100,13 @@ public class ProcessedAndroidData { RuleContext ruleContext, StampedAndroidManifest manifest, Artifact apkOut, - String proguardPrefix) + String proguardPrefix, + Map<String, String> manifestValues) throws RuleErrorException { AndroidResourcesProcessorBuilder builder = - builderForTopLevelTarget(ruleContext, manifest, proguardPrefix).setApkOut(apkOut); + builderForTopLevelTarget(ruleContext, manifest, proguardPrefix, manifestValues) + .setApkOut(apkOut); return buildActionForBinary(ruleContext, builder, manifest); } @@ -135,10 +142,14 @@ public class ProcessedAndroidData { /** Processes Android data (assets, resources, and manifest) for android_local_test targets. */ public static ProcessedAndroidData processLocalTestDataFrom( - RuleContext ruleContext, StampedAndroidManifest manifest) + RuleContext ruleContext, + StampedAndroidManifest manifest, + Map<String, String> manifestValues, + AndroidAaptVersion aaptVersion) throws RuleErrorException, InterruptedException { - return builderForNonIncrementalTopLevelTarget(ruleContext, manifest) + return builderForNonIncrementalTopLevelTarget( + ruleContext, manifest, manifestValues, aaptVersion) .setUseCompiledResourcesForMerge( AndroidAaptVersion.chooseTargetAaptVersion(ruleContext) == AndroidAaptVersion.AAPT2 && AndroidCommon.getAndroidConfig(ruleContext).skipParsingAction()) @@ -161,27 +172,24 @@ public class ProcessedAndroidData { RuleContext ruleContext, StampedAndroidManifest manifest, String packageUnderTest, - boolean hasLocalResourceFiles) - throws InterruptedException, RuleErrorException { + boolean hasLocalResourceFiles, + AndroidAaptVersion aaptVersion, + AndroidResources resources, + ResourceDependencies resourceDeps, + AndroidAssets assets, + AssetDependencies assetDeps) + throws InterruptedException { AndroidResourcesProcessorBuilder builder = - builderForNonIncrementalTopLevelTarget(ruleContext, manifest) + builderForNonIncrementalTopLevelTarget( + ruleContext, manifest, ImmutableMap.of(), aaptVersion) .setMainDexProguardOut(AndroidBinary.createMainDexProguardSpec(ruleContext)) .setPackageUnderTest(packageUnderTest) - .setIsTestWithResources(hasLocalResourceFiles); - - if (hasLocalResourceFiles) { - builder - .withResourceDependencies( - ResourceDependencies.fromRuleDeps(ruleContext, /* neverlink = */ false)) - .withAssetDependencies( - AssetDependencies.fromRuleDeps(ruleContext, /* neverlink = */ false)); - } + .setIsTestWithResources(hasLocalResourceFiles) + .withResourceDependencies(resourceDeps) + .withAssetDependencies(assetDeps); - return builder.build( - AndroidResources.from(ruleContext, "local_resource_files"), - AndroidAssets.from(ruleContext), - manifest); + return builder.build(resources, assets, manifest); } /** @@ -190,18 +198,22 @@ public class ProcessedAndroidData { * <p>The builder will be populated with commonly-used settings and outputs. */ private static AndroidResourcesProcessorBuilder builderForNonIncrementalTopLevelTarget( - RuleContext ruleContext, StampedAndroidManifest manifest) - throws InterruptedException, RuleErrorException { + RuleContext ruleContext, + StampedAndroidManifest manifest, + Map<String, String> manifestValues, + AndroidAaptVersion aaptVersion) + throws InterruptedException { - return builderForTopLevelTarget(ruleContext, manifest, "") - .targetAaptVersion(AndroidAaptVersion.chooseTargetAaptVersion(ruleContext)) + return builderForTopLevelTarget(ruleContext, manifest, "", manifestValues) + .targetAaptVersion(aaptVersion) // Outputs .setApkOut(ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_APK)) .setRTxtOut(ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT)) .setSourceJarOut( ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_JAVA_SOURCE_JAR)) - .setSymbols(ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_MERGED_SYMBOLS)); + .setSymbols( + ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_MERGED_SYMBOLS)); } /** @@ -210,9 +222,10 @@ public class ProcessedAndroidData { * <p>The builder will be populated with commonly-used settings and outputs. */ private static AndroidResourcesProcessorBuilder builderForTopLevelTarget( - RuleContext ruleContext, StampedAndroidManifest manifest, String proguardPrefix) { - Map<String, String> manifestValues = ApplicationManifest.getManifestValues(ruleContext); - + RuleContext ruleContext, + StampedAndroidManifest manifest, + String proguardPrefix, + Map<String, String> manifestValues) { return new AndroidResourcesProcessorBuilder(ruleContext) // Settings .setDebug(ruleContext.getConfiguration().getCompilationMode() != CompilationMode.OPT) @@ -272,10 +285,10 @@ public class ProcessedAndroidData { * <p>Registers an action to run R class generation, the last step needed in resource processing. * Returns the fully processed data, including validated resources, wrapped in a ResourceApk. */ - public ResourceApk generateRClass(RuleContext ruleContext) - throws RuleErrorException, InterruptedException { + public ResourceApk generateRClass(RuleContext ruleContext, AndroidAaptVersion aaptVersion) + throws InterruptedException { return new RClassGeneratorActionBuilder(ruleContext) - .targetAaptVersion(AndroidAaptVersion.chooseTargetAaptVersion(ruleContext)) + .targetAaptVersion(aaptVersion) .withDependencies(resourceDeps) .setClassJarOut( ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_CLASS_JAR)) 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 324766d323..7b128596eb 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 @@ -20,6 +20,7 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.config.CompilationMode; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import java.util.Optional; import javax.annotation.Nullable; /** @@ -228,35 +229,49 @@ public final class ResourceApk { return resourceDeps.toInfo(validatedResources); } - public void addToConfiguredTargetBuilder( - RuleConfiguredTargetBuilder builder, Label label, boolean includeSkylarkApiProvider) { - AndroidResourcesInfo resourceInfo = toResourceInfo(label); - builder.addNativeDeclaredProvider(resourceInfo); + // TODO(b/77574966): Stop returning an Optional once we get rid of ResourceContainer and can + // guarantee that only properly merged assets are passed into this object. + Optional<AndroidAssetsInfo> toAssetsInfo(Label label) { + if (primaryAssets instanceof MergedAndroidAssets) { + MergedAndroidAssets merged = (MergedAndroidAssets) primaryAssets; + AndroidAssetsInfo assetsInfo = merged.toProvider(); + return Optional.of(assetsInfo); + } else if (primaryAssets == null) { + return Optional.of(assetDeps.toInfo(label)); + } else { + return Optional.empty(); + } + } - // TODO(b/77574966): Remove this cast once we get rid of ResourceContainer and can guarantee - // that only properly merged resources are passed into this object. + // TODO(b/77574966): Remove this cast once we get rid of ResourceContainer and can guarantee + // that only properly merged resources are passed into this object. + Optional<AndroidManifestInfo> toManifestInfo() { if (validatedResources instanceof ValidatedAndroidResources) { ValidatedAndroidResources validated = (ValidatedAndroidResources) validatedResources; - builder.addNativeDeclaredProvider(validated.getStampedManifest().toProvider()); + return Optional.of(validated.getStampedManifest().toProvider()); } - // TODO(b/77574966): Remove this cast once we get rid of ResourceContainer and can guarantee - // that only properly merged resources are passed into this object. - if (primaryAssets instanceof MergedAndroidAssets) { - MergedAndroidAssets merged = (MergedAndroidAssets) primaryAssets; - AndroidAssetsInfo assetsInfo = merged.toProvider(); - builder.addNativeDeclaredProvider(assetsInfo); + return Optional.empty(); + } - if (assetsInfo.getValidationResult() != null) { - // Asset merging output isn't consumed by anything. Require it to be run by top-level - // targets - // so we can validate there are no asset merging conflicts. - builder.addOutputGroup(OutputGroupInfo.HIDDEN_TOP_LEVEL, assetsInfo.getValidationResult()); - } + public void addToConfiguredTargetBuilder( + RuleConfiguredTargetBuilder builder, Label label, boolean includeSkylarkApiProvider) { + AndroidResourcesInfo resourceInfo = toResourceInfo(label); + builder.addNativeDeclaredProvider(resourceInfo); - } else if (primaryAssets == null) { - builder.addNativeDeclaredProvider(assetDeps.toInfo(label)); + Optional<AndroidManifestInfo> manifestInfo = toManifestInfo(); + manifestInfo.ifPresent(builder::addNativeDeclaredProvider); + + Optional<AndroidAssetsInfo> assetsInfo = toAssetsInfo(label); + if (assetsInfo.isPresent()) { + builder.addNativeDeclaredProvider(assetsInfo.get()); + if (assetsInfo.get().getValidationResult() != null) { + // Asset merging output isn't consumed by anything. Require it to be run by top-level targets + // so we can validate there are no asset merging conflicts. + builder.addOutputGroup( + OutputGroupInfo.HIDDEN_TOP_LEVEL, assetsInfo.get().getValidationResult()); + } } if (includeSkylarkApiProvider) { |