diff options
author | 2018-05-09 08:51:20 -0700 | |
---|---|---|
committer | 2018-05-09 08:53:12 -0700 | |
commit | eac5be6eb075e2fab8c0c703a320daaaef850c87 (patch) | |
tree | c7ea2b49eef6d7721e453c44ecada46f9075a319 /src/main/java/com/google/devtools | |
parent | b1dd4e3ad80cd978ed6c86c67fac43f6e0b153b1 (diff) |
Expose single method for doing all android_library data processing in Skylark
RELNOTES: none
PiperOrigin-RevId: 195977060
Diffstat (limited to 'src/main/java/com/google/devtools')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java | 235 |
1 files changed, 235 insertions, 0 deletions
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 3566594fa1..5fa56a3be0 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 @@ -14,6 +14,7 @@ package com.google.devtools.build.lib.rules.android; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.FileProvider; @@ -529,6 +530,211 @@ public class AndroidSkylarkData { .toProvider(deps, definesLocalResources); } + /** + * Skylark API for doing all resource, asset, and manifest processing for an android_library + * + * <p>TODO(b/79159379): Stop passing SkylarkRuleContext here + * + * @param ctx the SkylarkRuleContext. We will soon change to using an ActionConstructionContext + * instead. See b/79159379 + */ + @SkylarkCallable( + name = "process_library_data", + mandatoryPositionals = 2, // ctx and libraryClassJar are required + parameters = { + @Param( + name = "manifest", + positional = false, + type = Artifact.class, + defaultValue = "None", + named = true, + noneable = true, + doc = + "If passed, the manifest to use for this target. Otherwise, a dummy manifest will" + + " be generated."), + @Param( + name = "resources", + positional = false, + defaultValue = "None", + type = SkylarkList.class, + generic1 = FileProvider.class, + named = true, + noneable = true, + doc = "Providers of this target's resources"), + @Param( + name = "assets", + positional = false, + defaultValue = "None", + type = SkylarkList.class, + generic1 = ConfiguredTarget.class, + noneable = true, + named = true, + doc = + "Targets containing raw assets for this target. If passed, 'assets_dir' must also" + + " be passed."), + @Param( + name = "assets_dir", + positional = false, + defaultValue = "None", + type = String.class, + noneable = true, + named = true, + doc = + "Directory the assets are contained in. Must be passed if and only if 'assets' is" + + " passed. This path will be split off of the asset paths on the device."), + @Param( + name = "exports_manifest", + positional = false, + defaultValue = "None", + type = Boolean.class, + named = true, + noneable = true, + doc = + "Defaults to False. If passed as True, this manifest will be exported to and" + + " eventually merged into targets that depend on it. Otherwise, it won't be" + + " inherited."), + @Param( + name = "custom_package", + positional = false, + defaultValue = "None", + type = String.class, + noneable = true, + named = true, + doc = + "The Android application package to stamp the manifest with. If not provided, the" + + " current Java package, derived from the location of this target's BUILD" + + " file, will be used. For example, given a BUILD file in" + + " 'java/com/foo/bar/BUILD', the package would be 'com.foo.bar'."), + @Param( + name = "neverlink", + positional = false, + defaultValue = "False", + type = Boolean.class, + named = true, + doc = + "Defaults to False. If passed as True, these resources and assets will not be" + + " inherited by targets that depend on this one."), + @Param( + name = "enable_data_binding", + positional = false, + defaultValue = "False", + type = Boolean.class, + named = true, + doc = + "Defaults to False. If True, processes data binding expressions in layout" + + " resources."), + @Param( + name = "proguard_specs", + type = SkylarkList.class, + generic1 = ConfiguredTarget.class, + defaultValue = "[]", + positional = false, + named = true, + doc = + "Files to be used as Proguard specification for this target, which will be" + + " inherited in the top-level target"), + @Param( + name = "deps", + positional = false, + defaultValue = "[]", + type = SkylarkList.class, + generic1 = AndroidAssetsInfo.class, + named = true, + doc = + "Dependency targets. Providers will be extracted from these dependencies for each" + + " type of data."), + }, + doc = + "Performs full processing of data for android_library or similar rules. Returns a dict" + + " from provider type to providers for the target.") + public SkylarkDict<NativeProvider<?>, NativeInfo> processLibraryData( + SkylarkRuleContext ctx, + Artifact libraryClassJar, + Object manifest, + Object resources, + Object assets, + Object assetsDir, + Object exportsManifest, + Object customPackage, + boolean neverlink, + boolean enableDataBinding, + SkylarkList<ConfiguredTarget> proguardSpecs, + SkylarkList<ConfiguredTarget> deps) + throws InterruptedException, EvalException { + + SkylarkList<AndroidResourcesInfo> resourceDeps = + getProviders(deps, AndroidResourcesInfo.PROVIDER); + SkylarkList<AndroidAssetsInfo> assetDeps = getProviders(deps, AndroidAssetsInfo.PROVIDER); + + ImmutableMap.Builder<NativeProvider<?>, NativeInfo> infoBuilder = ImmutableMap.builder(); + + AndroidResourcesInfo resourcesInfo; + AndroidAssetsInfo assetsInfo; + if (isNone(manifest) + && isNone(resources) + && isNone(assets) + && isNone(assetsDir) + && isNone(exportsManifest)) { + + // If none of these parameters were specified, for backwards compatibility, do not trigger + // data processing. + resourcesInfo = resourcesFromDeps(ctx, resourceDeps, neverlink, customPackage); + assetsInfo = assetsFromDeps(ctx, assetDeps, neverlink); + + infoBuilder.put(AndroidResourcesInfo.PROVIDER, resourcesInfo); + } else { + + AndroidManifestInfo baseManifest = + stampAndroidManifest( + ctx, + manifest, + customPackage, + fromNoneableOrDefault(exportsManifest, Boolean.class, false)); + + SkylarkDict<NativeProvider<?>, NativeInfo> resourceOutput = + mergeResources( + ctx, + baseManifest, + listFromNoneableOrEmpty(resources, ConfiguredTarget.class), + resourceDeps, + neverlink, + enableDataBinding); + + resourcesInfo = (AndroidResourcesInfo) resourceOutput.get(AndroidResourcesInfo.PROVIDER); + assetsInfo = mergeAssets(ctx, assets, assetsDir, assetDeps, neverlink); + + infoBuilder.putAll(resourceOutput); + } + + + AndroidLibraryAarInfo aarInfo = + makeAar( + ctx, + resourcesInfo, + assetsInfo, + libraryClassJar, + proguardSpecs, + getProviders(deps, AndroidLibraryAarInfo.PROVIDER), + neverlink); + + // Only expose the aar provider in non-neverlinked actions + if (!neverlink) { + infoBuilder.put(AndroidLibraryAarInfo.PROVIDER, aarInfo); + } + + // Expose the updated manifest that was changed by resource processing + // TODO(b/30817309): Use the base manifest once manifests are no longer changed in resource + // processing + AndroidManifestInfo manifestInfo = resourcesInfo.getManifest().toProvider(); + + return SkylarkDict.copyOf( + /* env = */ null, + infoBuilder + .put(AndroidAssetsInfo.PROVIDER, assetsInfo) + .put(AndroidManifestInfo.PROVIDER, manifestInfo) + .build()); + } + /** Checks if a "Noneable" object passed by Skylark is "None", which Java should treat as null. */ private static boolean isNone(Object object) { return object == Runtime.NONE; @@ -555,6 +761,15 @@ public class AndroidSkylarkData { return clazz.cast(object); } + private static <T> T fromNoneableOrDefault(Object object, Class<T> clazz, T defaultValue) { + T value = fromNoneable(object, clazz); + if (value == null) { + return defaultValue; + } + + return value; + } + /** * Converts a "Noneable" Object passed by Skylark to a List of the appropriate type. * @@ -570,4 +785,24 @@ public class AndroidSkylarkData { return SkylarkList.castList(asList, clazz, null); } + + private static <T> SkylarkList<T> listFromNoneableOrEmpty(Object object, Class<T> clazz) + throws EvalException { + List<T> value = listFromNoneable(object, clazz); + if (value == null) { + return SkylarkList.createImmutable(ImmutableList.of()); + } + + return SkylarkList.createImmutable(value); + } + + private static <T extends NativeInfo> SkylarkList<T> getProviders( + SkylarkList<ConfiguredTarget> targets, NativeProvider<T> provider) { + return SkylarkList.createImmutable( + targets + .stream() + .map(target -> target.get(provider)) + .filter(Objects::nonNull) + .collect(ImmutableList.toImmutableList())); + } } |