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 1bc70634838e93..ec9911f44c5987 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 @@ -179,7 +179,14 @@ ParsedAndroidAssets parse(AndroidDataContext dataContext) throws InterruptedExce /** Convenience method to do all of asset processing - parsing and merging. */ public MergedAndroidAssets process(AndroidDataContext dataContext, AssetDependencies assetDeps) throws InterruptedException { - return parse(dataContext).merge(dataContext, assetDeps); + ParsedAndroidAssets parsedAssets = parse(dataContext); + + boolean mergeAssets = dataContext.getAndroidConfig().outputLibraryMergedAssets() + || dataContext.throwOnResourceConflict(); + + return mergeAssets ? + parsedAssets.merge(dataContext, assetDeps) : + MergedAndroidAssets.of(parsedAssets, null, assetDeps); } @Override diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java index 76164b18fe9fed..157184a8ffa1be 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java @@ -909,6 +909,14 @@ public static class Options extends FragmentOptions { + " instead of declarations plus all dependency references.") public boolean namespacedRClass; + @Option( + name = "output_library_merged_assets", + defaultValue = "true", + documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, + effectTags = {OptionEffectTag.UNKNOWN}, + help = "If disabled, does not produce merged asset.zip outputs for library targets") + public boolean outputLibraryMergedAssets; + @Option( name = "legacy_main_dex_list_generator", // TODO(b/147692286): Update this default value to R8's GenerateMainDexList binary after @@ -1012,6 +1020,7 @@ public FragmentOptions getHost() { private final boolean useRTxtFromMergedResources; private final boolean linkLibraryResources; private final boolean namespacedRClass; + private final boolean outputLibraryMergedAssets; private final Label legacyMainDexListGenerator; private final boolean disableInstrumentationManifestMerging; private final boolean incompatibleUseToolchainResolution; @@ -1072,6 +1081,7 @@ public AndroidConfiguration(BuildOptions buildOptions) throws InvalidConfigurati this.useRTxtFromMergedResources = options.useRTxtFromMergedResources; this.linkLibraryResources = options.linkLibraryResources; this.namespacedRClass = options.namespacedRClass; + this.outputLibraryMergedAssets = options.outputLibraryMergedAssets; this.legacyMainDexListGenerator = options.legacyMainDexListGenerator; this.disableInstrumentationManifestMerging = options.disableInstrumentationManifestMerging; this.incompatibleUseToolchainResolution = options.incompatibleUseToolchainResolution; @@ -1349,6 +1359,10 @@ public boolean disableInstrumentationManifestMerging() { return disableInstrumentationManifestMerging; } + boolean outputLibraryMergedAssets() { + return outputLibraryMergedAssets; + } + /** Returns the label provided with --legacy_main_dex_list_generator, if any. */ // TODO(b/147692286): Move R8's main dex list tool into tool repository. @StarlarkConfigurationField( diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/MergedAndroidAssets.java b/src/main/java/com/google/devtools/build/lib/rules/android/MergedAndroidAssets.java index 2c685ccc16851a..dd77dd700b2bd7 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/MergedAndroidAssets.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/MergedAndroidAssets.java @@ -27,8 +27,8 @@ static MergedAndroidAssets mergeFrom( AndroidDataContext dataContext, ParsedAndroidAssets parsed, AssetDependencies deps) throws InterruptedException { - Artifact mergedAssets = - dataContext.createOutputArtifact(AndroidRuleClasses.ANDROID_ASSETS_ZIP); + Artifact mergedAssets = dataContext.getAndroidConfig().outputLibraryMergedAssets() ? + dataContext.createOutputArtifact(AndroidRuleClasses.ANDROID_ASSETS_ZIP) : null; BusyBoxActionBuilder builder = BusyBoxActionBuilder.create(dataContext, "MERGE_ASSETS"); if (dataContext.throwOnResourceConflict()) { @@ -36,7 +36,7 @@ static MergedAndroidAssets mergeFrom( } builder - .addOutput("--assetsOutput", mergedAssets) + .maybeAddOutput("--assetsOutput", mergedAssets) .addInput( "--primaryData", AndroidDataConverter.PARSED_ASSET_CONVERTER.map(parsed), diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidAssetMergingAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidAssetMergingAction.java index 6d871a65c55041..8818a97b571b76 100644 --- a/src/tools/android/java/com/google/devtools/build/android/AndroidAssetMergingAction.java +++ b/src/tools/android/java/com/google/devtools/build/android/AndroidAssetMergingAction.java @@ -13,9 +13,9 @@ // limitations under the License. package com.google.devtools.build.android; -import com.android.builder.core.VariantType; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.devtools.build.android.AndroidDataMerger.ContentComparingChecker; import com.google.devtools.build.android.Converters.PathConverter; import com.google.devtools.build.android.Converters.SerializedAndroidDataConverter; import com.google.devtools.build.android.Converters.SerializedAndroidDataListConverter; @@ -133,30 +133,46 @@ void run(Path tmp, ExecutorServiceCloser executorService) throws Exception { Preconditions.checkNotNull(options.primary); - MergedAndroidData mergedData = - AndroidResourceMerger.mergeDataAndWrite( - options.primary, - /* primaryManifest = */ null, - options.directData, - options.transitiveData, - /* resourcesOut = */ ignored, - mergedAssets, - /* cruncher = */ null, - VariantType.LIBRARY, - /* symbolsOut = */ null, - /* rclassWriter = */ null, - options.throwOnAssetConflict, - executorService); + final ParsedAndroidData.Builder primaryBuilder = ParsedAndroidData.Builder.newBuilder(); + final AndroidParsedDataDeserializer deserializer = AndroidParsedDataDeserializer.create(); + options.primary.deserialize( + DependencyInfo.DependencyType.PRIMARY, deserializer, primaryBuilder.consumers()); + ParsedAndroidData primaryData = primaryBuilder.build(); + + UnwrittenMergedAndroidData unwrittenMergedData = AndroidResourceMerger.mergeData( + executorService, + options.transitiveData, + options.directData, + primaryData, + /* primaryManifest = */ null, + /* allowPrimaryOverrideAll = */ false, + deserializer, + options.throwOnAssetConflict, + ContentComparingChecker.create()); logCompletion("Merging"); - Preconditions.checkState( - !Files.exists(ignored), - "The asset merging action should not produce non-asset merge results!"); - - ResourcesZip.from(ignored, mergedData.getAssetDir()) - .writeTo(options.assetsOutput, /* compress= */ true); - logCompletion("Create assets zip"); + if (options.assetsOutput != null) { + MergedAndroidData writtenMergedData = + AndroidResourceMerger.writeMergedData( + ignored, + mergedAssets, + /* cruncher = */ null, + /* symbolsOut = */ null, + /* rclassWriter = */ null, + executorService, + unwrittenMergedData); + + logCompletion("Writing"); + + Preconditions.checkState( + !Files.exists(ignored), + "The asset merging action should not produce non-asset merge results!"); + + ResourcesZip.from(ignored, writtenMergedData.getAssetDir()) + .writeTo(options.assetsOutput, /* compress= */ true); + logCompletion("Create assets zip"); + } } @Override diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java index 37deb219d63a66..f95064eb905eb7 100644 --- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java +++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java @@ -86,7 +86,7 @@ static MergingException withMessage(String message) { * Merges all secondary resources with the primary resources, given that the primary resources * have not yet been parsed and serialized. */ - public static MergedAndroidData mergeDataAndWrite( + static MergedAndroidData mergeDataAndWrite( final UnvalidatedAndroidData primary, final List direct, final List transitive, @@ -99,91 +99,39 @@ public static MergedAndroidData mergeDataAndWrite( boolean throwOnResourceConflict) { try (ExecutorServiceCloser executorService = ExecutorServiceCloser.createWithFixedPoolOf(15)) { final ParsedAndroidData parsedPrimary = ParsedAndroidData.from(primary); - return mergeDataAndWrite( - parsedPrimary, - primary.getManifest(), - direct, - transitive, + return writeMergedData( resourcesOut, assetsOut, cruncher, - type, symbolsOut, /* rclassWriter= */ null, - AndroidParsedDataDeserializer.withFilteredResources(filteredResources), - throwOnResourceConflict, - executorService); + executorService, + mergeData( + executorService, + transitive, + direct, + parsedPrimary, + primary.getManifest(), + type != VariantType.LIBRARY, + AndroidParsedDataDeserializer.withFilteredResources(filteredResources), + throwOnResourceConflict, + ContentComparingChecker.create())); } catch (IOException e) { throw MergingException.wrapException(e); } } - /** - * Merges all secondary resources with the primary resources, given that the primary resources - * have been separately parsed and serialized. - */ - public static MergedAndroidData mergeDataAndWrite( - final SerializedAndroidData primary, - final Path primaryManifest, - final List direct, - final List transitive, + /** Writes out merged data. */ + static MergedAndroidData writeMergedData( final Path resourcesOut, final Path assetsOut, @Nullable final PngCruncher cruncher, - final VariantType type, - @Nullable final Path symbolsOut, - @Nullable final AndroidResourceClassWriter rclassWriter, - boolean throwOnResourceConflict, - ListeningExecutorService executorService) { - final ParsedAndroidData.Builder primaryBuilder = ParsedAndroidData.Builder.newBuilder(); - final AndroidParsedDataDeserializer deserializer = AndroidParsedDataDeserializer.create(); - primary.deserialize( - DependencyInfo.DependencyType.PRIMARY, deserializer, primaryBuilder.consumers()); - ParsedAndroidData primaryData = primaryBuilder.build(); - return mergeDataAndWrite( - primaryData, - primaryManifest, - direct, - transitive, - resourcesOut, - assetsOut, - cruncher, - type, - symbolsOut, - rclassWriter, - deserializer, - throwOnResourceConflict, - executorService); - } - - /** Merges all secondary resources with the primary resources. */ - private static MergedAndroidData mergeDataAndWrite( - final ParsedAndroidData primary, - final Path primaryManifest, - final List direct, - final List transitive, - final Path resourcesOut, - final Path assetsOut, - @Nullable final PngCruncher cruncher, - final VariantType type, @Nullable final Path symbolsOut, @Nullable AndroidResourceClassWriter rclassWriter, - AndroidParsedDataDeserializer deserializer, - boolean throwOnResourceConflict, - ListeningExecutorService executorService) { + ListeningExecutorService executorService, + UnwrittenMergedAndroidData merged) { Stopwatch timer = Stopwatch.createStarted(); try { - UnwrittenMergedAndroidData merged = - mergeData( - executorService, - transitive, - direct, - primary, - primaryManifest, - type != VariantType.LIBRARY, - deserializer, - throwOnResourceConflict, - ContentComparingChecker.create()); timer.reset().start(); if (symbolsOut != null) { AndroidDataSerializer serializer = AndroidDataSerializer.create(); @@ -212,7 +160,7 @@ private static MergedAndroidData mergeDataAndWrite( } } - private static UnwrittenMergedAndroidData mergeData( + static UnwrittenMergedAndroidData mergeData( ListeningExecutorService executorService, List transitive, List direct,