| // Copyright 2017 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. | |
| // Copyright 2017 The Bazel Authors. All rights reserved. | |
| package com.google.devtools.build.android; | |
| import com.google.common.base.Preconditions; | |
| import com.google.devtools.build.android.aapt2.Aapt2ConfigOptions; | |
| import com.google.devtools.build.android.aapt2.CompiledResources; | |
| import com.google.devtools.build.android.aapt2.ResourceLinker; | |
| import com.google.devtools.build.android.aapt2.StaticLibrary; | |
| import com.google.devtools.common.options.Option; | |
| import com.google.devtools.common.options.OptionDocumentationCategory; | |
| import com.google.devtools.common.options.OptionEffectTag; | |
| import com.google.devtools.common.options.OptionsBase; | |
| import com.google.devtools.common.options.OptionsParser; | |
| import com.google.devtools.common.options.ShellQuotedParamsFilePreProcessor; | |
| import java.nio.file.FileSystems; | |
| import java.nio.file.Path; | |
| import java.util.List; | |
| import java.util.Optional; | |
| import java.util.stream.Collectors; | |
| /** Performs resource validation and static linking for compiled android resources. */ | |
| public class ValidateAndLinkResourcesAction { | |
| /** Action configuration options. */ | |
| public static class Options extends OptionsBase { | |
| @Option( | |
| name = "compiled", | |
| documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| defaultValue = "null", | |
| converter = Converters.ExistingPathConverter.class, | |
| category = "input", | |
| help = "Compiled resources to link.", | |
| deprecationWarning = "Use --resources.") | |
| // TODO(b/64570523): Still used by blaze. Will be removed as part of the command line cleanup. | |
| @Deprecated | |
| public Path compiled; | |
| @Option( | |
| name = "compiledDep", | |
| documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| defaultValue = "", | |
| converter = Converters.PathListConverter.class, | |
| category = "input", | |
| allowMultiple = true, | |
| help = "Compiled resource dependencies to link.") | |
| public List<Path> compiledDeps; | |
| @Option( | |
| name = "manifest", | |
| documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| defaultValue = "null", | |
| converter = Converters.ExistingPathConverter.class, | |
| category = "input", | |
| help = "Manifest for the library.", | |
| deprecationWarning = "Use --resources.") | |
| // TODO(b/64570523): Still used by blaze. Will be removed as part of the command line cleanup. | |
| @Deprecated | |
| public Path manifest; | |
| @Option( | |
| name = "resources", | |
| documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| defaultValue = "null", | |
| converter = Converters.CompiledResourcesConverter.class, | |
| category = "input", | |
| help = "Compiled resources to link.") | |
| public CompiledResources resources; | |
| // TODO(b/64570523): remove this flag when it is no longer used. | |
| @Option( | |
| name = "libraries", | |
| documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| defaultValue = "null", | |
| converter = Converters.StaticLibraryListConverter.class, | |
| category = "input", | |
| help = "Static libraries to link against. Deprecated, use --library") | |
| public List<StaticLibrary> deprecatedLibraries; | |
| @Option( | |
| name = "library", | |
| documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| defaultValue = "null", | |
| converter = Converters.StaticLibraryConverter.class, | |
| category = "input", | |
| allowMultiple = true, | |
| help = "Static libraries to link against.") | |
| public List<StaticLibrary> libraries; | |
| @Option( | |
| name = "packageForR", | |
| documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| defaultValue = "null", | |
| category = "input", | |
| help = "Package for the resources.") | |
| public String packageForR; | |
| @Option( | |
| name = "staticLibraryOut", | |
| documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| defaultValue = "null", | |
| converter = Converters.PathConverter.class, | |
| category = "output", | |
| help = "Static library produced.") | |
| public Path staticLibraryOut; | |
| @Option( | |
| name = "rTxtOut", | |
| documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| defaultValue = "null", | |
| converter = Converters.PathConverter.class, | |
| category = "output", | |
| help = "R.txt out.") | |
| public Path rTxtOut; | |
| @Option( | |
| name = "sourceJarOut", | |
| documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| converter = Converters.PathConverter.class, | |
| defaultValue = "null", | |
| category = "output", | |
| help = "Generated java classes from the resources.") | |
| public Path sourceJarOut; | |
| } | |
| public static void main(String[] args) throws Exception { | |
| final OptionsParser optionsParser = | |
| OptionsParser.newOptionsParser(Options.class, Aapt2ConfigOptions.class); | |
| optionsParser.enableParamsFileSupport( | |
| new ShellQuotedParamsFilePreProcessor(FileSystems.getDefault())); | |
| optionsParser.parse(args); | |
| Options options = optionsParser.getOptions(Options.class); | |
| final Aapt2ConfigOptions aapt2Options = optionsParser.getOptions(Aapt2ConfigOptions.class); | |
| final Profiler profiler = LoggingProfiler.createAndStart("manifest"); | |
| try (ScopedTemporaryDirectory scopedTmp = | |
| new ScopedTemporaryDirectory("android_resources_tmp"); | |
| ExecutorServiceCloser executorService = ExecutorServiceCloser.createWithFixedPoolOf(15)) { | |
| CompiledResources resources = | |
| // TODO(b/64570523): Remove when the flags are standardized. | |
| Optional.ofNullable(options.resources) | |
| .orElseGet( | |
| () -> | |
| CompiledResources.from( | |
| Preconditions.checkNotNull(options.compiled), | |
| Preconditions.checkNotNull(options.manifest))) | |
| // We need to make the manifest aapt safe (w.r.t., placeholders). For now, just stub | |
| // it out. | |
| .processManifest( | |
| manifest -> | |
| AndroidManifest.parseFrom(manifest) | |
| .writeDummyManifestForAapt( | |
| scopedTmp.getPath().resolve("manifest-aapt-dummy"), | |
| options.packageForR)); | |
| profiler.recordEndOf("manifest").startTask("link"); | |
| ResourceLinker.create(aapt2Options.aapt2, executorService, scopedTmp.getPath()) | |
| .profileUsing(profiler) | |
| .dependencies(Optional.ofNullable(options.deprecatedLibraries).orElse(options.libraries)) | |
| .include( | |
| options.compiledDeps.stream() | |
| .map(CompiledResources::from) | |
| .collect(Collectors.toList())) | |
| .buildVersion(aapt2Options.buildToolsVersion) | |
| .outputAsProto(aapt2Options.resourceTableAsProto) | |
| .linkStatically(resources) | |
| .copyLibraryTo(options.staticLibraryOut) | |
| .copySourceJarTo(options.sourceJarOut) | |
| .copyRTxtTo(options.rTxtOut); | |
| profiler.recordEndOf("link"); | |
| } | |
| } | |
| } |