// Copyright 2016 The Bazel Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.devtools.build.lib.rules.android; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.rules.android.AndroidConfiguration.AndroidAaptVersion; import java.util.Collections; import java.util.List; /** Builder for creating resource shrinker actions. */ public class ResourceShrinkerActionBuilder { private AndroidAaptVersion targetAaptVersion; private Artifact resourceFilesZip; private Artifact shrunkJar; private Artifact proguardMapping; private ValidatedAndroidResources primaryResources; private ResourceDependencies dependencyResources; private Artifact resourceApkOut; private Artifact shrunkResourcesOut; private Artifact logOut; private List uncompressedExtensions = Collections.emptyList(); private ResourceFilterFactory resourceFilterFactory = ResourceFilterFactory.empty(); public ResourceShrinkerActionBuilder setUncompressedExtensions( List uncompressedExtensions) { this.uncompressedExtensions = uncompressedExtensions; return this; } /** @param resourceFilterFactory The filters to apply to the resources. */ public ResourceShrinkerActionBuilder setResourceFilterFactory( ResourceFilterFactory resourceFilterFactory) { this.resourceFilterFactory = resourceFilterFactory; return this; } /** @param resourceFilesZip A zip file containing the merged assets and resources to be shrunk. */ public ResourceShrinkerActionBuilder withResourceFiles(Artifact resourceFilesZip) { this.resourceFilesZip = resourceFilesZip; return this; } /** @param shrunkJar The deploy jar of the rule after a dead code removal Proguard pass. */ public ResourceShrinkerActionBuilder withShrunkJar(Artifact shrunkJar) { this.shrunkJar = shrunkJar; return this; } /** @param proguardMapping The Proguard mapping between obfuscated and original code. */ public ResourceShrinkerActionBuilder withProguardMapping(Artifact proguardMapping) { this.proguardMapping = proguardMapping; return this; } /** * @param primary The fully processed {@link ValidatedAndroidResources} of the resources to be * shrunk. Must contain both an R.txt and merged manifest. */ public ResourceShrinkerActionBuilder withPrimary(ValidatedAndroidResources primary) { checkNotNull(primary); checkNotNull(primary.getManifest()); checkNotNull(primary.getRTxt()); this.primaryResources = primary; return this; } /** @param resourceDeps The full dependency tree of resources. */ public ResourceShrinkerActionBuilder withDependencies(ResourceDependencies resourceDeps) { this.dependencyResources = resourceDeps; return this; } /** @param resourceApkOut The location to write the shrunk resource ap_ package. */ public ResourceShrinkerActionBuilder setResourceApkOut(Artifact resourceApkOut) { this.resourceApkOut = resourceApkOut; return this; } /** @param shrunkResourcesOut The location to write the shrunk resource files zip. */ public ResourceShrinkerActionBuilder setShrunkResourcesOut(Artifact shrunkResourcesOut) { this.shrunkResourcesOut = shrunkResourcesOut; return this; } /** @param logOut The location to write the shrinker log. */ public ResourceShrinkerActionBuilder setLogOut(Artifact logOut) { this.logOut = logOut; return this; } /** @param androidAaptVersion The aapt version to target with this action. */ public ResourceShrinkerActionBuilder setTargetAaptVersion(AndroidAaptVersion androidAaptVersion) { this.targetAaptVersion = androidAaptVersion; return this; } public Artifact build(AndroidDataContext dataContext) { checkNotNull(resourceFilesZip); checkNotNull(shrunkJar); checkNotNull(proguardMapping); checkNotNull(primaryResources); checkNotNull(primaryResources.getRTxt()); checkNotNull(primaryResources.getManifest()); checkNotNull(resourceApkOut); BusyBoxActionBuilder builder; if (targetAaptVersion == AndroidAaptVersion.AAPT2) { builder = BusyBoxActionBuilder.create(dataContext, "SHRINK_AAPT2"); } else { builder = BusyBoxActionBuilder.create(dataContext, "SHRINK"); } builder .addAapt(targetAaptVersion) .addAndroidJar() .maybeAddVectoredFlag("--uncompressedExtensions", uncompressedExtensions) .maybeAddFlag("--debug", dataContext.useDebug()) .maybeAddFlag("--resourceConfigs", resourceFilterFactory.getConfigurationFilterString()) .addInput("--resources", resourceFilesZip) .addInput("--shrunkJar", shrunkJar) .addInput("--proguardMapping", proguardMapping) .addInput("--rTxt", primaryResources.getRTxt()) .addInput("--primaryManifest", primaryResources.getManifest()) .maybeAddInput("--dependencyManifest", getManifests(dependencyResources)) .addVectoredFlag( "--resourcePackages", getResourcePackages(primaryResources, dependencyResources)) .addOutput("--shrunkResourceApk", resourceApkOut) .addOutput("--shrunkResources", shrunkResourcesOut) .addOutput("--log", logOut) .buildAndRegister("Shrinking resources", "ResourceShrinker"); return resourceApkOut; } private ImmutableList getManifests(ResourceDependencies resourceDependencies) { ImmutableList.Builder manifests = ImmutableList.builder(); for (ValidatedAndroidResources resources : resourceDependencies.getResourceContainers()) { if (resources.getManifest() != null) { manifests.add(resources.getManifest()); } } return manifests.build(); } private ImmutableList getResourcePackages( ValidatedAndroidResources primaryResources, ResourceDependencies resourceDependencies) { ImmutableList.Builder resourcePackages = ImmutableList.builder(); resourcePackages.add(primaryResources.getJavaPackage()); for (ValidatedAndroidResources resources : resourceDependencies.getResourceContainers()) { resourcePackages.add(resources.getJavaPackage()); } return resourcePackages.build(); } }