| // 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"); |
| } |
| } |
| } |