// 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 java.util.stream.Collectors.joining; import com.google.common.collect.Iterables; import com.google.common.collect.Streams; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.rules.android.AndroidConfiguration.AndroidAaptVersion; import com.google.devtools.build.lib.rules.android.DataBinding.DataBindingContext; import com.google.devtools.build.lib.vfs.PathFragment; import javax.annotation.Nullable; /** Builder for creating $android_resource_parser action. */ public class AndroidResourceParsingActionBuilder { // These are only needed when parsing resources with data binding @Nullable private Artifact manifest; @Nullable private String javaPackage; private AndroidResources resources = AndroidResources.empty(); private AndroidAssets assets = AndroidAssets.empty(); // The symbols file is a required output private Artifact output; // Optional outputs @Nullable private Artifact compiledSymbols; @Nullable private Artifact dataBindingInfoZip; /** Set the artifact location for the output protobuf. */ public AndroidResourceParsingActionBuilder setOutput(Artifact output) { this.output = output; return this; } /** Sets the manifest. Will be ignored except when parsing resources with data binding. */ public AndroidResourceParsingActionBuilder setManifest(@Nullable Artifact manifest) { this.manifest = manifest; return this; } /** Sets the Java package. Will be ignored except when parsing resources with data binding. */ public AndroidResourceParsingActionBuilder setJavaPackage(@Nullable String javaPackage) { this.javaPackage = javaPackage; return this; } public AndroidResourceParsingActionBuilder setResources(AndroidResources resources) { this.resources = resources; return this; } public AndroidResourceParsingActionBuilder setAssets(AndroidAssets assets) { this.assets = assets; return this; } public AndroidResourceParsingActionBuilder setCompiledSymbolsOutput( @Nullable Artifact compiledSymbols) { this.compiledSymbols = compiledSymbols; return this; } public AndroidResourceParsingActionBuilder setDataBindingInfoZip(Artifact dataBindingInfoZip) { this.dataBindingInfoZip = dataBindingInfoZip; return this; } private static String convertRoots(Iterable roots) { return Streams.stream(roots).map(Object::toString).collect(joining("#")); } private void build(AndroidDataContext dataContext) { String resourceDirectories = convertRoots(resources.getResourceRoots()) + ":" + convertRoots(assets.getAssetRoots()); Iterable resourceArtifacts = Iterables.concat(assets.getAssets(), resources.getResources()); BusyBoxActionBuilder.create(dataContext, "PARSE") .addInput("--primaryData", resourceDirectories, resourceArtifacts) .addOutput("--output", output) .buildAndRegister("Parsing Android resources", "AndroidResourceParser"); if (compiledSymbols != null) { BusyBoxActionBuilder compiledBuilder = BusyBoxActionBuilder.create(dataContext, "COMPILE_LIBRARY_RESOURCES") .addAapt(AndroidAaptVersion.AAPT2) .addInput("--resources", resourceDirectories, resourceArtifacts) .addOutput("--output", compiledSymbols); if (dataBindingInfoZip != null) { compiledBuilder .addInput("--manifest", manifest) .maybeAddFlag("--packagePath", javaPackage) .addOutput("--dataBindingInfoOut", dataBindingInfoZip); } compiledBuilder.buildAndRegister("Compiling Android resources", "AndroidResourceCompiler"); } } /** * Builds and registers the action, and returns a copy of the passed resources with artifacts for * parsed and compiled information. */ public ParsedAndroidResources build( AndroidDataContext dataContext, AndroidResources androidResources, StampedAndroidManifest manifest, DataBindingContext dataBindingContext) { if (dataBindingInfoZip != null) { // Manifest information is needed for data binding setManifest(manifest.getManifest()); setJavaPackage(manifest.getPackage()); } setResources(androidResources); build(dataContext); return ParsedAndroidResources.of( androidResources, output, compiledSymbols, dataContext.getLabel(), manifest, dataBindingContext); } public ParsedAndroidAssets build(AndroidDataContext dataContext, AndroidAssets assets) { setAssets(assets); build(dataContext); return ParsedAndroidAssets.of(assets, output, compiledSymbols, dataContext.getLabel()); } }