Halt resource_files.zip generation for Robolectric builds to enable skipping aapt2 convert. resource_files.zip is unused by Robolectric builds. We can forego its creation. By using a lack of resource_files.zip as a marker, ResourceLinker can skip the costly 'aapt2 convert' step. PiperOrigin-RevId: 949770100 Change-Id: I76b857dd252ffeec53b6d107fa18481929be4e06
diff --git a/rules/android_local_test/impl.bzl b/rules/android_local_test/impl.bzl index fe61058..67e57de 100644 --- a/rules/android_local_test/impl.bzl +++ b/rules/android_local_test/impl.bzl
@@ -118,6 +118,7 @@ shrink_resources = attrs.tristate.no, build_java_with_final_resources = True, generate_out_symbols = False, + generate_resource_files_zip = False, crunch_png = False, aapt = get_android_toolchain(ctx).aapt2.files_to_run, android_jar = get_android_sdk(ctx).android_jar, @@ -209,18 +210,14 @@ ) def _process_deploy_jar(ctx, java_package, jvm_ctx, proto_ctx, resources_ctx, **_unused_sub_ctxs): - res_file_path = resources_ctx.validation_result.short_path subs = { "%android_merged_manifest%": resources_ctx.processed_manifest.short_path, - "%android_merged_resources%": "jar:file:" + res_file_path + "!/res", - "%android_merged_assets%": "jar:file:" + res_file_path + "!/assets", # The native resources_ctx has the package field, whereas the starlark resources_ctx uses the java_package "%android_custom_package%": getattr(resources_ctx, "package", java_package or ""), "%android_resource_apk%": resources_ctx.resources_apk.short_path, } res_runfiles = [ resources_ctx.resources_apk, - resources_ctx.validation_result, resources_ctx.processed_manifest, ]
diff --git a/rules/resources.bzl b/rules/resources.bzl index ee1c615..3072d1c 100644 --- a/rules/resources.bzl +++ b/rules/resources.bzl
@@ -496,6 +496,7 @@ generate_minsdk_proguard_config = False, build_java_with_final_resources = False, generate_out_symbols = True, + generate_resource_files_zip = True, feature_flags = "", crunch_png = True, aapt = None, @@ -566,6 +567,7 @@ generally only desirable for test targets that aren't potentially running compile-time optimizations. generate_out_symbols: boolean. Whether to generate the merged symbols binary file. + generate_resource_files_zip: boolean. Whether to generate resource_files.zip. feature_flags: string. The string value for --feature-flags to pass to aapt2. crunch_png: boolean. Determines whether `aapt2 compile` should crunch PNG files. aapt: FilesToRunProvider. The aapt executable or FilesToRunProvider. @@ -736,7 +738,7 @@ ) resource_files_zip = ctx.actions.declare_file( "_migrated/" + ctx.label.name + "_files/resource_files.zip", - ) + ) if generate_resource_files_zip else None out_symbols = ctx.actions.declare_file("_migrated/" + ctx.label.name + "_symbols/merged.bin") if generate_out_symbols else None _busybox.package( ctx,
diff --git a/rules/robolectric_properties_template.txt b/rules/robolectric_properties_template.txt index d05a28c..564bbf2 100644 --- a/rules/robolectric_properties_template.txt +++ b/rules/robolectric_properties_template.txt
@@ -1,5 +1,3 @@ android_merged_manifest=%android_merged_manifest% -android_merged_resources=%android_merged_resources% -android_merged_assets=%android_merged_assets% android_custom_package=%android_custom_package% android_resource_apk=%android_resource_apk%
diff --git a/src/tools/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java b/src/tools/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java index 22f8243..3a52308 100644 --- a/src/tools/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java +++ b/src/tools/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java
@@ -413,6 +413,7 @@ .includeProguardLocationReferences(options.includeProguardLocationReferences) .featureFlags(aaptConfigOptions.featureFlags) .optimizeThroughput(aaptConfigOptions.optimizeThroughput) + .hasResourcesOutput(options.resourcesOutput != null) .link(compiled); profiler.recordEndOf("link").startTask("validate");
diff --git a/src/tools/java/com/google/devtools/build/android/ResourcesZip.java b/src/tools/java/com/google/devtools/build/android/ResourcesZip.java index cd3410a..82c6a03 100644 --- a/src/tools/java/com/google/devtools/build/android/ResourcesZip.java +++ b/src/tools/java/com/google/devtools/build/android/ResourcesZip.java
@@ -241,6 +241,9 @@ @VisibleForTesting ImmutableListMultimap<String, String> parseToolAttributes() throws IOException { + if (attributes == null || !Files.exists(attributes)) { + return ImmutableListMultimap.of(); + } return ToolAttributes.parseFrom( Files.readAllBytes(attributes), ExtensionRegistry.getEmptyRegistry()) .getAttributesMap()
diff --git a/src/tools/java/com/google/devtools/build/android/aapt2/PackagedResources.java b/src/tools/java/com/google/devtools/build/android/aapt2/PackagedResources.java index 7a388e0..6f830f7 100644 --- a/src/tools/java/com/google/devtools/build/android/aapt2/PackagedResources.java +++ b/src/tools/java/com/google/devtools/build/android/aapt2/PackagedResources.java
@@ -16,6 +16,7 @@ import com.google.auto.value.AutoValue; import com.google.devtools.build.android.ResourcesZip; import java.nio.file.Path; +import javax.annotation.Nullable; /** Represents the packaged, flattened resources. */ @AutoValue @@ -23,6 +24,7 @@ public abstract Path apk(); + @Nullable public abstract Path proto(); public abstract Path rTxt(); @@ -33,22 +35,25 @@ public abstract Path javaSourceDirectory(); + @Nullable abstract Path resourceIds(); + @Nullable public abstract Path attributes(); + @Nullable public abstract Path packages(); public static PackagedResources of( Path outPath, - Path protoPath, + @Nullable Path protoPath, Path rTxt, Path proguardConfig, Path mainDexProguard, Path javaSourceDirectory, - Path resourceIds, - Path attributes, - Path packages) { + @Nullable Path resourceIds, + @Nullable Path attributes, + @Nullable Path packages) { return new AutoValue_PackagedResources( outPath, protoPath,
diff --git a/src/tools/java/com/google/devtools/build/android/aapt2/ResourceLinker.java b/src/tools/java/com/google/devtools/build/android/aapt2/ResourceLinker.java index 5126f30..92cdde5 100644 --- a/src/tools/java/com/google/devtools/build/android/aapt2/ResourceLinker.java +++ b/src/tools/java/com/google/devtools/build/android/aapt2/ResourceLinker.java
@@ -88,6 +88,7 @@ import java.util.zip.DeflaterOutputStream; import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; +import javax.annotation.Nullable; /** Performs linking of {@link CompiledResources} using aapt2. */ public class ResourceLinker { @@ -168,6 +169,7 @@ private List<StaticLibrary> resourceApks = ImmutableList.of(); private String featureFlags = ""; private boolean optimizeThroughput = false; + private boolean hasResourcesOutput = true; private ResourceLinker( Path aapt2, ListeningExecutorService executorService, Path workingDirectory) { @@ -274,6 +276,12 @@ return this; } + @CanIgnoreReturnValue + public ResourceLinker hasResourcesOutput(boolean hasResourcesOutput) { + this.hasResourcesOutput = hasResourcesOutput; + return this; + } + /** * Statically links the {@link CompiledResources} with the dependencies to produce a {@link * StaticLibrary}. @@ -438,20 +446,21 @@ return fileName.substring(0, lastIndex).concat(".").concat(newExtension); } - private ProtoApk linkProtoApk( + private Path linkApk( CompiledResources compiled, Path rTxt, Path proguardConfig, Path mainDexProguard, Path javaSourceDirectory, - Path resourceIds) + @Nullable Path resourceIds, + boolean asProto) throws IOException { Predicate<DirectoryEntry> flatFileShouldKeep = generatePseudoLocale && resourceConfigs.stream().anyMatch(PSEUDO_LOCALE_FILTERS::contains) ? USE_GENERATED : USE_DEFAULT; profiler.startTask("fulllink"); - final Path linked = workingDirectory.resolve("bin." + PROTO_EXTENSION); + final Path linked = workingDirectory.resolve(asProto ? ("bin." + PROTO_EXTENSION) : "bin.apk"); logger.fine( new AaptCommandBuilder(aapt2) .forBuildToolsVersion(buildToolsVersion) @@ -470,8 +479,8 @@ .add("--auto-add-overlay") .when(OVERRIDE_STYLES_INSTEAD_OF_OVERLAYING) .thenAdd("--override-styles-instead-of-overlaying") - // Always link to proto, as resource shrinking needs the extra information. - .add("--proto-format") + .when(asProto) + .thenAdd("--proto-format") .when(debug) .thenAdd("--debug-mode") .add("--custom-package", customPackage) @@ -501,7 +510,8 @@ .when(!resourceConfigs.isEmpty()) .thenAdd("-c", Joiner.on(',').join(resourceConfigs)) .add("--output-text-symbols", rTxt) - .add("--emit-ids", resourceIds) + .when(resourceIds != null) + .thenAdd("--emit-ids", resourceIds) .add("--java", javaSourceDirectory) .add("--proguard", proguardConfig) .add("--proguard-main-dex", mainDexProguard) @@ -512,7 +522,8 @@ .add("--feature-flags", featureFlags) .execute(String.format("Linking %s", compiled.getManifest()))); profiler.recordEndOf("fulllink"); - return ProtoApk.readFrom(optimize(compiled, linked)); + Path optimized = optimize(compiled, linked, asProto); + return asProto ? optimized : copyAndFixCompression(optimized, workingDirectory); } /** Modes for overriding compression of a given file. */ @@ -658,13 +669,14 @@ return attributes; } - private Path optimize(CompiledResources compiled, Path protoApk) throws IOException { + private Path optimize(CompiledResources compiled, Path apk, boolean isProto) throws IOException { if (densities.size() < 2) { - return protoApk; + return apk; } profiler.startTask("optimize"); - final Path optimized = workingDirectory.resolve("optimized." + PROTO_EXTENSION); + final Path optimized = + workingDirectory.resolve(isProto ? ("optimized." + PROTO_EXTENSION) : "optimized.apk"); logger.fine( new AaptCommandBuilder(aapt2) .forBuildToolsVersion(buildToolsVersion) @@ -680,7 +692,7 @@ .when(densities.size() >= 2) .thenAdd("--target-densities", densities.stream().collect(Collectors.joining(","))) .add("-o", optimized) - .add(protoApk.toString()) + .add(apk.toString()) .execute(String.format("Optimizing %s", compiled.getManifest()))); profiler.recordEndOf("optimize"); return optimized; @@ -693,23 +705,48 @@ Path proguardConfig = workingDirectory.resolve("proguard.cfg"); Path mainDexProguard = workingDirectory.resolve("proguard.maindex.cfg"); Path javaSourceDirectory = Files.createDirectories(workingDirectory.resolve("java")); - Path resourceIds = workingDirectory.resolve("ids.txt"); - try (ProtoApk protoApk = - linkProtoApk( - compiled, rTxt, proguardConfig, mainDexProguard, javaSourceDirectory, resourceIds)) { - return PackagedResources.of( - outputAsProto ? protoApk.asApkPath() : convertProtoApkToBinary(protoApk), - protoApk.asApkPath(), - rTxt, - proguardConfig, - mainDexProguard, - javaSourceDirectory, - resourceIds, - extractAttributes(compiled), - extractPackages(compiled)); + Path resourceIds = hasResourcesOutput ? workingDirectory.resolve("ids.txt") : null; + // conditionalKeepRules=true implies resource shrinking, which can only occur if + // resource_files.zip exists. + Preconditions.checkState( + hasResourcesOutput || (!conditionalKeepRules && !outputAsProto), + "Cannot construct proto apk when resource_files.zip is unavailable."); + boolean linkAsProto = hasResourcesOutput || outputAsProto || conditionalKeepRules; + Path apkPath = + linkApk( + compiled, + rTxt, + proguardConfig, + mainDexProguard, + javaSourceDirectory, + resourceIds, + linkAsProto); + if (linkAsProto) { + try (ProtoApk protoApk = ProtoApk.readFrom(apkPath)) { + return PackagedResources.of( + outputAsProto ? protoApk.asApkPath() : convertProtoApkToBinary(protoApk), + protoApk.asApkPath(), + rTxt, + proguardConfig, + mainDexProguard, + javaSourceDirectory, + resourceIds, + extractAttributes(compiled), + extractPackages(compiled)); + } } - } catch (IOException e) { + return PackagedResources.of( + apkPath, + null, + rTxt, + proguardConfig, + mainDexProguard, + javaSourceDirectory, + resourceIds, + null, + null); + } catch (IOException | IllegalStateException e) { throw new LinkError(e); } }