Link.cpp revision d0f492db038c6210c1138865d816bfb134376538
11ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/* 21ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Copyright (C) 2015 The Android Open Source Project 31ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 41ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 51ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * you may not use this file except in compliance with the License. 61ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * You may obtain a copy of the License at 71ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 81ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 91ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Unless required by applicable law or agreed to in writing, software 111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * See the License for the specific language governing permissions and 141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * limitations under the License. 151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */ 161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 17ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <sys/stat.h> 18ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 19ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <fstream> 20ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <queue> 21ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <unordered_map> 22ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <vector> 23ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 24ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/errors.h" 25ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/file.h" 26f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski#include "android-base/stringprintf.h" 27d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski#include "androidfw/StringPiece.h" 28ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "google/protobuf/io/coded_stream.h" 29ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "AppInfo.h" 311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "Debug.h" 321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "Flags.h" 336a008170cb18666e04c42856f992fc7a0afa1e1fAdam Lesinski#include "Locale.h" 341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "NameMangler.h" 3559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "ResourceUtils.h" 36d0f492db038c6210c1138865d816bfb134376538Adam Lesinski#include "cmd/Util.h" 371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "compile/IdAssigner.h" 386a008170cb18666e04c42856f992fc7a0afa1e1fAdam Lesinski#include "filter/ConfigFilter.h" 391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "flatten/Archive.h" 401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "flatten/TableFlattener.h" 411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "flatten/XmlFlattener.h" 4206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski#include "io/BigBufferInputStream.h" 43a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski#include "io/FileSystem.h" 44d0f492db038c6210c1138865d816bfb134376538Adam Lesinski#include "io/Util.h" 45a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski#include "io/ZipArchive.h" 46ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "java/JavaClassGenerator.h" 47ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "java/ManifestClassGenerator.h" 48ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "java/ProguardRules.h" 491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "link/Linkers.h" 50cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski#include "link/ManifestFixer.h" 51467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "link/ReferenceLinker.h" 521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "link/TableMerger.h" 53d48944a745f9ed121e6bde22ef6feb3a44fbec39Adam Lesinski#include "optimize/ResourceDeduper.h" 54d48944a745f9ed121e6bde22ef6feb3a44fbec39Adam Lesinski#include "optimize/VersionCollapser.h" 551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "process/IResourceTableConsumer.h" 561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "process/SymbolTable.h" 5759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "proto/ProtoSerialize.h" 58355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski#include "split/TableSplitter.h" 591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "unflatten/BinaryResourceParser.h" 601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/Files.h" 61467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "xml/XmlDom.h" 621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 63d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinskiusing android::StringPiece; 64f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinskiusing android::base::StringPrintf; 655eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt { 671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 68ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski// The type of package to build. 69ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinskienum class PackageType { 70ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski kApp, 71ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski kSharedLib, 72ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski kStaticLib, 73ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski}; 74ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct LinkOptions { 76ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski PackageType package_type = PackageType::kApp; 77ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string output_path; 79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string manifest_path; 80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> include_paths; 81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> overlay_files; 82b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski std::vector<std::string> assets_dirs; 83ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool output_to_directory = false; 84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool auto_add_overlay = false; 85cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 86cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Java/Proguard options. 87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> generate_java_class_path; 88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> custom_java_package; 89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::set<std::string> extra_java_packages; 90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> generate_proguard_rules_path; 91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> generate_main_dex_proguard_rules_path; 92ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool generate_non_final_ids = false; 93ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> javadoc_annotations; 94ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> private_symbols; 95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // Optimizations/features. 97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_auto_version = false; 98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_version_vectors = false; 994d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki bool no_version_transitions = false; 100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_resource_deduping = false; 101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_xml_namespaces = false; 102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool do_not_compress_anything = false; 103ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unordered_set<std::string> extensions_to_not_compress; 104ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 105ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // Static lib options. 106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_static_lib_packages = false; 107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 108ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // AndroidManifest.xml massaging options. 109ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ManifestFixerOptions manifest_fixer_options; 110ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // Products to use/filter on. 112cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unordered_set<std::string> products; 113cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 114c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski // Flattening options. 115c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski TableFlattenerOptions table_flattener_options; 116c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 117cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Split APK options. 118ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski TableSplitterOptions table_splitter_options; 119ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<SplitConstraints> split_constraints; 120ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> split_paths; 121cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 122cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Stable ID options. 123ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unordered_map<ResourceName, ResourceId> stable_id_map; 124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> resource_id_map_path; 1251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}; 1261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 12764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiclass LinkContext : public IAaptContext { 128cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public: 129d0f492db038c6210c1138865d816bfb134376538Adam Lesinski LinkContext() : name_mangler_({}), symbols_(&name_mangler_) { 130d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 1311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 132d0f492db038c6210c1138865d816bfb134376538Adam Lesinski IDiagnostics* GetDiagnostics() override { 133d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return &diagnostics_; 134d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 1351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 136d0f492db038c6210c1138865d816bfb134376538Adam Lesinski NameMangler* GetNameMangler() override { 137d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return &name_mangler_; 138d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 1391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 140ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski void SetNameManglerPolicy(const NameManglerPolicy& policy) { 141ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski name_mangler_ = NameMangler(policy); 142cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 14364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const std::string& GetCompilationPackage() override { 145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return compilation_package_; 146cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski void SetCompilationPackage(const StringPiece& package_name) { 149d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski compilation_package_ = package_name.to_string(); 150cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 15164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 152d0f492db038c6210c1138865d816bfb134376538Adam Lesinski uint8_t GetPackageId() override { 153d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return package_id_; 154d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 1551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 156d0f492db038c6210c1138865d816bfb134376538Adam Lesinski void SetPackageId(uint8_t id) { 157d0f492db038c6210c1138865d816bfb134376538Adam Lesinski package_id_ = id; 158d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 15964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 160d0f492db038c6210c1138865d816bfb134376538Adam Lesinski SymbolTable* GetExternalSymbols() override { 161d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return &symbols_; 162d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 163355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 164d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool IsVerbose() override { 165d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return verbose_; 166d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 16764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 168d0f492db038c6210c1138865d816bfb134376538Adam Lesinski void SetVerbose(bool val) { 169d0f492db038c6210c1138865d816bfb134376538Adam Lesinski verbose_ = val; 170d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 17164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 172d0f492db038c6210c1138865d816bfb134376538Adam Lesinski int GetMinSdkVersion() override { 173d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return min_sdk_version_; 174d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 175fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski 176d0f492db038c6210c1138865d816bfb134376538Adam Lesinski void SetMinSdkVersion(int minSdk) { 177d0f492db038c6210c1138865d816bfb134376538Adam Lesinski min_sdk_version_ = minSdk; 178d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 179fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski 180cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private: 181ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DISALLOW_COPY_AND_ASSIGN(LinkContext); 182ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 183ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski StdErrDiagnostics diagnostics_; 184ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski NameMangler name_mangler_; 185ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string compilation_package_; 186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski uint8_t package_id_ = 0x0; 187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski SymbolTable symbols_; 188ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool verbose_ = false; 189ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski int min_sdk_version_ = 0; 1901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}; 1911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 192ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic bool FlattenXml(xml::XmlResource* xml_res, const StringPiece& path, 193d0f492db038c6210c1138865d816bfb134376538Adam Lesinski Maybe<size_t> max_sdk_level, bool keep_raw_values, IArchiveWriter* writer, 194d0f492db038c6210c1138865d816bfb134376538Adam Lesinski IAaptContext* context) { 195cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski BigBuffer buffer(1024); 196cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski XmlFlattenerOptions options = {}; 197ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options.keep_raw_values = keep_raw_values; 198ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options.max_sdk_level = max_sdk_level; 199cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski XmlFlattener flattener(&buffer, options); 200ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!flattener.Consume(context, xml_res)) { 201cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 202cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 204ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context->IsVerbose()) { 205cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski DiagMessage msg; 206cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski msg << "writing " << path << " to archive"; 207ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (max_sdk_level) { 208d0f492db038c6210c1138865d816bfb134376538Adam Lesinski msg << " maxSdkLevel=" << max_sdk_level.value() << " keepRawValues=" << keep_raw_values; 209355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 210ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context->GetDiagnostics()->Note(msg); 211cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 21259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 21306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski io::BigBufferInputStream input_stream(&buffer); 214d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return io::CopyInputStreamToArchive(context, &input_stream, path.to_string(), 215d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ArchiveEntry::kCompress, writer); 216355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 21759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 218d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic std::unique_ptr<ResourceTable> LoadTableFromPb(const Source& source, const void* data, 219d0f492db038c6210c1138865d816bfb134376538Adam Lesinski size_t len, IDiagnostics* diag) { 220ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski pb::ResourceTable pb_table; 221ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!pb_table.ParseFromArray(data, len)) { 222ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(source) << "invalid compiled table"); 223cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return {}; 224cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 225cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 22606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski std::unique_ptr<ResourceTable> table = DeserializeTableFromPb(pb_table, source, diag); 227cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!table) { 228cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return {}; 229cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 230cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return table; 231355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 2321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 233355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski/** 234355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * Inflates an XML file from the source path. 235355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski */ 236d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path, IDiagnostics* diag) { 237cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::ifstream fin(path, std::ifstream::binary); 238cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fin) { 239ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(path) << strerror(errno)); 240cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return {}; 241cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 242ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return xml::Inflate(&fin, diag, Source(path)); 243355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 2441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 245355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskistruct ResourceFileFlattenerOptions { 246ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_auto_version = false; 247ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_version_vectors = false; 2484d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki bool no_version_transitions = false; 249ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_xml_namespaces = false; 250ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool keep_raw_values = false; 251ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool do_not_compress_anything = false; 252ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool update_proguard_spec = false; 253ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unordered_set<std::string> extensions_to_not_compress; 254355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}; 255355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 256355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskiclass ResourceFileFlattener { 257cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public: 258d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ResourceFileFlattener(const ResourceFileFlattenerOptions& options, IAaptContext* context, 259d0f492db038c6210c1138865d816bfb134376538Adam Lesinski proguard::KeepSet* keep_set) 260d0f492db038c6210c1138865d816bfb134376538Adam Lesinski : options_(options), context_(context), keep_set_(keep_set) { 261d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 2621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 263ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool Flatten(ResourceTable* table, IArchiveWriter* archive_writer); 264355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 265cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private: 266cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski struct FileOperation { 267cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ConfigDescription config; 2685eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 269cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The entry this file came from. 270cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const ResourceEntry* entry; 2715eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 272cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The file to copy as-is. 273ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::IFile* file_to_copy; 2745eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 275cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The XML to process and flatten. 276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<xml::XmlResource> xml_to_flatten; 2775eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 278cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The destination to write this file to. 279ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string dst_path; 280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool skip_version = false; 281cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski }; 282355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 283ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski uint32_t GetCompressionFlags(const StringPiece& str); 284355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 285ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool LinkAndVersionXmlFile(ResourceTable* table, FileOperation* file_op, 286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::queue<FileOperation>* out_file_op_queue); 287355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 288ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceFileFlattenerOptions options_; 289ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski IAaptContext* context_; 290ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski proguard::KeepSet* keep_set_; 291355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}; 292355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiuint32_t ResourceFileFlattener::GetCompressionFlags(const StringPiece& str) { 294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.do_not_compress_anything) { 295cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 0; 296cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 297355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& extension : options_.extensions_to_not_compress) { 299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (util::EndsWith(str, extension)) { 300cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 0; 301355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 302cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 303cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ArchiveEntry::kCompress; 304355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 305355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 3064d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Arakistatic bool IsTransitionElement(const std::string& name) { 307d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return name == "fade" || name == "changeBounds" || name == "slide" || name == "explode" || 308d0f492db038c6210c1138865d816bfb134376538Adam Lesinski name == "changeImageTransform" || name == "changeTransform" || 309d0f492db038c6210c1138865d816bfb134376538Adam Lesinski name == "changeClipBounds" || name == "autoTransition" || name == "recolor" || 310d0f492db038c6210c1138865d816bfb134376538Adam Lesinski name == "changeScroll" || name == "transitionSet" || name == "transition" || 311d0f492db038c6210c1138865d816bfb134376538Adam Lesinski name == "transitionManager"; 3124d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki} 3134d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki 314d0f492db038c6210c1138865d816bfb134376538Adam Lesinskibool ResourceFileFlattener::LinkAndVersionXmlFile(ResourceTable* table, FileOperation* file_op, 315d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::queue<FileOperation>* out_file_op_queue) { 316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski xml::XmlResource* doc = file_op->xml_to_flatten.get(); 317cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const Source& src = doc->file.source; 318355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 319ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage() << "linking " << src.path); 321cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 322355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 323ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XmlReferenceLinker xml_linker; 324ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!xml_linker.Consume(context_, doc)) { 325cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 326cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 327355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 328d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (options_.update_proguard_spec && !proguard::CollectProguardRules(src, doc, keep_set_)) { 329cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 330cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 331cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 332ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.no_xml_namespaces) { 333ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XmlNamespaceRemover namespace_remover; 334ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!namespace_remover.Consume(context_, doc)) { 335cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 336355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 337cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 338355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 339ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!options_.no_auto_version) { 340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.no_version_vectors) { 341cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Skip this if it is a vector or animated-vector. 342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski xml::Element* el = xml::FindRootElement(doc); 343ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (el && el->namespace_uri.empty()) { 344cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (el->name == "vector" || el->name == "animated-vector") { 345cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // We are NOT going to version this file. 346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_op->skip_version = true; 347cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 348a7cc3f1d79eb7a02a68928381998137f2f9b10a3Alexandria Cornwall } 349cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 350a7cc3f1d79eb7a02a68928381998137f2f9b10a3Alexandria Cornwall } 3514d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki if (options_.no_version_transitions) { 3524d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki // Skip this if it is a transition resource. 3534d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki xml::Element* el = xml::FindRootElement(doc); 3544d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki if (el && el->namespace_uri.empty()) { 3554d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki if (IsTransitionElement(el->name)) { 3564d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki // We are NOT going to version this file. 3574d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki file_op->skip_version = true; 3584d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki return true; 3594d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki } 3604d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki } 3614d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki } 362a7cc3f1d79eb7a02a68928381998137f2f9b10a3Alexandria Cornwall 363ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ConfigDescription& config = file_op->config; 364cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 365cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Find the first SDK level used that is higher than this defined config and 366cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // not superseded by a lower or equal SDK level resource. 367ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const int min_sdk_version = context_->GetMinSdkVersion(); 368ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (int sdk_level : xml_linker.sdk_levels()) { 369ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (sdk_level > min_sdk_version && sdk_level > config.sdkVersion) { 370d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!ShouldGenerateVersionedResource(file_op->entry, config, sdk_level)) { 371cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // If we shouldn't generate a versioned resource, stop checking. 372cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski break; 373626a69f34536d01db0847df0051199beaecce060Adam Lesinski } 374626a69f34536d01db0847df0051199beaecce060Adam Lesinski 375ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceFile versioned_file_desc = doc->file; 376ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski versioned_file_desc.config.sdkVersion = (uint16_t)sdk_level; 377cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 378ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski FileOperation new_file_op; 379d0f492db038c6210c1138865d816bfb134376538Adam Lesinski new_file_op.xml_to_flatten = 380d0f492db038c6210c1138865d816bfb134376538Adam Lesinski util::make_unique<xml::XmlResource>(versioned_file_desc, doc->root->Clone()); 381ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_file_op.config = versioned_file_desc.config; 382ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_file_op.entry = file_op->entry; 383d0f492db038c6210c1138865d816bfb134376538Adam Lesinski new_file_op.dst_path = 384d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ResourceUtils::BuildResourceFileName(versioned_file_desc, context_->GetNameMangler()); 385cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 386ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 387d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage(versioned_file_desc.source) 388d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "auto-versioning resource from config '" << config 389d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "' -> '" << versioned_file_desc.config << "'"); 390cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 391cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 392ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool added = table->AddFileReferenceAllowMangled( 393d0f492db038c6210c1138865d816bfb134376538Adam Lesinski versioned_file_desc.name, versioned_file_desc.config, versioned_file_desc.source, 394d0f492db038c6210c1138865d816bfb134376538Adam Lesinski new_file_op.dst_path, nullptr, context_->GetDiagnostics()); 395cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!added) { 396cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 39752364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski } 398cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 399ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski out_file_op_queue->push(std::move(new_file_op)); 400cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski break; 401cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 40252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski } 403cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 404cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 405355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 40652364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 407355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski/** 408cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Do not insert or remove any resources while executing in this function. It 409cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * will 410355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * corrupt the iteration order. 411355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski */ 412d0f492db038c6210c1138865d816bfb134376538Adam Lesinskibool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archive_writer) { 413cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool error = false; 414d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files; 415cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 416cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (auto& pkg : table->packages) { 417cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (auto& type : pkg->types) { 418cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Sort by config and name, so that we get better locality in the zip 419cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // file. 420ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski config_sorted_files.clear(); 421ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::queue<FileOperation> file_operations; 422cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 423cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Populate the queue with all files in the ResourceTable. 424cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (auto& entry : type->entries) { 425ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& config_value : entry->values) { 426d0f492db038c6210c1138865d816bfb134376538Adam Lesinski FileReference* file_ref = ValueCast<FileReference>(config_value->value.get()); 427ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!file_ref) { 428cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski continue; 429cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 430355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 431ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::IFile* file = file_ref->file; 432cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!file) { 433ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(file_ref->GetSource()) 434cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << "file not found"); 435cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 436cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 437355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 438ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski FileOperation file_op; 439ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_op.entry = entry.get(); 440ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_op.dst_path = *file_ref->path; 441ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_op.config = config_value->config; 442355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 443ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece src_path = file->GetSource().path; 444cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (type->type != ResourceType::kRaw && 445d0f492db038c6210c1138865d816bfb134376538Adam Lesinski (util::EndsWith(src_path, ".xml.flat") || util::EndsWith(src_path, ".xml"))) { 446ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<io::IData> data = file->OpenAsData(); 447cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!data) { 448ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(file->GetSource()) 449cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << "failed to open file"); 450cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 451355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 452355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 453d0f492db038c6210c1138865d816bfb134376538Adam Lesinski file_op.xml_to_flatten = xml::Inflate(data->data(), data->size(), 454d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics(), file->GetSource()); 455355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!file_op.xml_to_flatten) { 457cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 458a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } 459cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 460ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_op.xml_to_flatten->file.config = config_value->config; 461ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_op.xml_to_flatten->file.source = file_ref->GetSource(); 462d0f492db038c6210c1138865d816bfb134376538Adam Lesinski file_op.xml_to_flatten->file.name = ResourceName(pkg->name, type->type, entry->name); 463cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 464cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Enqueue the XML files to be processed. 465ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_operations.push(std::move(file_op)); 466cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 467ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_op.file_to_copy = file; 468cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 469cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // NOTE(adamlesinski): Explicitly construct a StringPiece here, or 470ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // else we end up copying the string in the std::make_pair() method, 471ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // then creating a StringPiece from the copy, which would cause us 472ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // to end up referencing garbage in the map. 473ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece entry_name(entry->name); 474d0f492db038c6210c1138865d816bfb134376538Adam Lesinski config_sorted_files[std::make_pair(config_value->config, entry_name)] = 475d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::move(file_op); 476cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 477cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 478cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 479cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 480cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Now process the XML queue 481ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (; !file_operations.empty(); file_operations.pop()) { 482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski FileOperation& file_op = file_operations.front(); 483cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 484ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!LinkAndVersionXmlFile(table, &file_op, &file_operations)) { 485cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 486cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski continue; 487cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 488cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 489cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // NOTE(adamlesinski): Explicitly construct a StringPiece here, or else 490cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // we end up copying the string in the std::make_pair() method, then 491ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // creating a StringPiece from the copy, which would cause us to end up 492ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // referencing garbage in the map. 493ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece entry_name(file_op.entry->name); 494d0f492db038c6210c1138865d816bfb134376538Adam Lesinski config_sorted_files[std::make_pair(file_op.config, entry_name)] = std::move(file_op); 495cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 496cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 497cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (error) { 498cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 499cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 500cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 501cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Now flatten the sorted values. 502ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& map_entry : config_sorted_files) { 503ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ConfigDescription& config = map_entry.first.first; 504ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const FileOperation& file_op = map_entry.second; 505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 506ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (file_op.xml_to_flatten) { 507ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<size_t> max_sdk_level; 508ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!options_.no_auto_version && !file_op.skip_version) { 509d0f492db038c6210c1138865d816bfb134376538Adam Lesinski max_sdk_level = std::max<size_t>(std::max<size_t>(config.sdkVersion, 1u), 510d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetMinSdkVersion()); 511cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 512cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 513d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool result = FlattenXml(file_op.xml_to_flatten.get(), file_op.dst_path, max_sdk_level, 514d0f492db038c6210c1138865d816bfb134376538Adam Lesinski options_.keep_raw_values, archive_writer, context_); 515cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!result) { 516cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 517cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 518cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 519d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool result = 520d0f492db038c6210c1138865d816bfb134376538Adam Lesinski io::CopyFileToArchive(context_, file_op.file_to_copy, file_op.dst_path, 521d0f492db038c6210c1138865d816bfb134376538Adam Lesinski GetCompressionFlags(file_op.dst_path), archive_writer); 522cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!result) { 523cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 524cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 5251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 526cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 527355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 528cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 529cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return !error; 530355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 531a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski 532d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic bool WriteStableIdMapToPath(IDiagnostics* diag, 533d0f492db038c6210c1138865d816bfb134376538Adam Lesinski const std::unordered_map<ResourceName, ResourceId>& id_map, 534d0f492db038c6210c1138865d816bfb134376538Adam Lesinski const std::string& id_map_path) { 535ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::ofstream fout(id_map_path, std::ofstream::binary); 536cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fout) { 537ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(id_map_path) << strerror(errno)); 538cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 539cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 540bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 541ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const auto& entry : id_map) { 542cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const ResourceName& name = entry.first; 543cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const ResourceId& id = entry.second; 544cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski fout << name << " = " << id << "\n"; 545cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 546bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 547cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fout) { 548d0f492db038c6210c1138865d816bfb134376538Adam Lesinski diag->Error(DiagMessage(id_map_path) << "failed writing to file: " 549d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << android::base::SystemErrorCodeToString(errno)); 550cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 551cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 552bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 553cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 554bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski} 555bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 556d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic bool LoadStableIdMap(IDiagnostics* diag, const std::string& path, 557d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::unordered_map<ResourceName, ResourceId>* out_id_map) { 558cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string content; 559cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!android::base::ReadFileToString(path, &content)) { 560ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(path) << "failed reading stable ID file"); 561cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 562cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 563bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 564ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski out_id_map->clear(); 565ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t line_no = 0; 566ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (StringPiece line : util::Tokenize(content, '\n')) { 567ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski line_no++; 568ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski line = util::TrimWhitespace(line); 569cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (line.empty()) { 570cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski continue; 571cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 572bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 573cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski auto iter = std::find(line.begin(), line.end(), '='); 574cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (iter == line.end()) { 575ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(Source(path, line_no)) << "missing '='"); 576cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 577cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 578bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 579cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceNameRef name; 580ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski StringPiece res_name_str = 581ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski util::TrimWhitespace(line.substr(0, std::distance(line.begin(), iter))); 582ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!ResourceUtils::ParseResourceName(res_name_str, &name)) { 583d0f492db038c6210c1138865d816bfb134376538Adam Lesinski diag->Error(DiagMessage(Source(path, line_no)) << "invalid resource name '" << res_name_str 584d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "'"); 585cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 586cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 587bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 588ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const size_t res_id_start_idx = std::distance(line.begin(), iter) + 1; 589ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const size_t res_id_str_len = line.size() - res_id_start_idx; 590d0f492db038c6210c1138865d816bfb134376538Adam Lesinski StringPiece res_id_str = util::TrimWhitespace(line.substr(res_id_start_idx, res_id_str_len)); 591bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 592ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<ResourceId> maybe_id = ResourceUtils::ParseResourceId(res_id_str); 593ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!maybe_id) { 594d0f492db038c6210c1138865d816bfb134376538Adam Lesinski diag->Error(DiagMessage(Source(path, line_no)) << "invalid resource ID '" << res_id_str 595d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "'"); 596cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 597bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski } 598cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 599ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski (*out_id_map)[name.ToResourceName()] = maybe_id.value(); 600cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 601cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 602bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski} 603bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 604355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskiclass LinkCommand { 605cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public: 606cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski LinkCommand(LinkContext* context, const LinkOptions& options) 607ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski : options_(options), 608ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_(context), 609ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski final_table_(), 610d0f492db038c6210c1138865d816bfb134376538Adam Lesinski file_collection_(util::make_unique<io::FileCollection>()) { 611d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 612cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 613cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 614cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Creates a SymbolTable that loads symbols from the various APKs and caches 615ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski * the results for faster lookup. 616cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 617ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool LoadSymbolsFromIncludePaths() { 618ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<AssetManagerSymbolSource> asset_source = 619cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski util::make_unique<AssetManagerSymbolSource>(); 620ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& path : options_.include_paths) { 621ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 622d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage(path) << "loading include path"); 623cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 624cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 625cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // First try to load the file as a static lib. 626ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string error_str; 627ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski std::unique_ptr<ResourceTable> include_static = LoadStaticLibrary(path, &error_str); 628ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (include_static) { 629ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (options_.package_type != PackageType::kStaticLib) { 630ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski // Can't include static libraries when not building a static library (they have no IDs 631ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski // assigned). 632ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error( 633ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski DiagMessage(path) << "can't include static library when not building a static lib"); 634cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 635cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 63664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 637cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // If we are using --no-static-lib-packages, we need to rename the 638f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski // package of this table to our compilation package. 639ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.no_static_lib_packages) { 640f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski // Since package names can differ, and multiple packages can exist in a ResourceTable, 641f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski // we place the requirement that all static libraries are built with the package 642f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski // ID 0x7f. So if one is not found, this is an error. 643f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (ResourceTablePackage* pkg = include_static->FindPackageById(kAppPackageId)) { 644ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski pkg->name = context_->GetCompilationPackage(); 645f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } else { 646f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(path) 647f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski << "no package with ID 0x7f found in static library"); 648f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski return false; 649cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 650355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 65164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 652ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetExternalSymbols()->AppendSource( 653ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski util::make_unique<ResourceTableSymbolSource>(include_static.get())); 6541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 655ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski static_table_includes_.push_back(std::move(include_static)); 656fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski 657ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else if (!error_str.empty()) { 658cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // We had an error with reading, so fail. 659ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(path) << error_str); 660cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 661cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 662fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski 663ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!asset_source->AddAssetPath(path)) { 664ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage(path) << "failed to load include path"); 665cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 666cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 667cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 668fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski 669ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski // Capture the shared libraries so that the final resource table can be properly flattened 670ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski // with support for shared libraries. 671ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski for (auto& entry : asset_source->GetAssignedPackageIds()) { 672f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (entry.first > kFrameworkPackageId && entry.first < kAppPackageId) { 673ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski final_table_.included_packages_[entry.first] = entry.second; 674ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski } 675ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski } 676ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 677ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetExternalSymbols()->AppendSource(std::move(asset_source)); 678cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 679cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 68036c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 681b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski Maybe<AppInfo> ExtractAppInfoFromManifest(xml::XmlResource* xml_res, IDiagnostics* diag) { 682cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Make sure the first element is <manifest> with package attribute. 683b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski xml::Element* manifest_el = xml::FindRootElement(xml_res->root.get()); 684b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (manifest_el == nullptr) { 685b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski return {}; 686b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski } 68736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 688b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski AppInfo app_info; 689b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski 690b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (!manifest_el->namespace_uri.empty() || manifest_el->name != "manifest") { 691b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski diag->Error(DiagMessage(xml_res->file.source) << "root tag must be <manifest>"); 692b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski return {}; 693b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski } 694fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski 695b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski xml::Attribute* package_attr = manifest_el->FindAttribute({}, "package"); 696b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (!package_attr) { 697b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski diag->Error(DiagMessage(xml_res->file.source) 698b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski << "<manifest> must have a 'package' attribute"); 699b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski return {}; 700b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski } 701b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski app_info.package = package_attr->value; 702b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski 703b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (xml::Attribute* version_code_attr = 704b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode")) { 705b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski Maybe<uint32_t> maybe_code = ResourceUtils::ParseInt(version_code_attr->value); 706b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (!maybe_code) { 707b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number)) 708b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski << "invalid android:versionCode '" << version_code_attr->value << "'"); 7091ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return {}; 710cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 711b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski app_info.version_code = maybe_code.value(); 712b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski } 713cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 714b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (xml::Attribute* revision_code_attr = 715b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode")) { 716b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski Maybe<uint32_t> maybe_code = ResourceUtils::ParseInt(revision_code_attr->value); 717b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (!maybe_code) { 718b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number)) 719b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski << "invalid android:revisionCode '" << revision_code_attr->value << "'"); 720b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski return {}; 721cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 722b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski app_info.revision_code = maybe_code.value(); 723b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski } 724cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 725b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (xml::Attribute* split_name_attr = manifest_el->FindAttribute({}, "split")) { 726b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (!split_name_attr->value.empty()) { 727b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski app_info.split_name = split_name_attr->value; 728cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 729b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski } 730cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 731b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (xml::Element* uses_sdk_el = manifest_el->FindChild({}, "uses-sdk")) { 732b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (xml::Attribute* min_sdk = 733b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski uses_sdk_el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion")) { 734d0f492db038c6210c1138865d816bfb134376538Adam Lesinski app_info.min_sdk_version = ResourceUtils::ParseSdkVersion(min_sdk->value); 735cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 736cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 737b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski return app_info; 738cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 739cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 740cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 741b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski * Precondition: ResourceTable doesn't have any IDs assigned yet, nor is it linked. 742cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Postcondition: ResourceTable has only one package left. All others are 743ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski * stripped, or there is an error and false is returned. 744cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 745ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool VerifyNoExternalPackages() { 746d0f492db038c6210c1138865d816bfb134376538Adam Lesinski auto is_ext_package_func = [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool { 747ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return context_->GetCompilationPackage() != pkg->name || !pkg->id || 748ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski pkg->id.value() != context_->GetPackageId(); 749cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski }; 7501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 751cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool error = false; 752ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const auto& package : final_table_.packages) { 753ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (is_ext_package_func(package)) { 754cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // We have a package that is not related to the one we're building! 755cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (const auto& type : package->types) { 756cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (const auto& entry : type->entries) { 757ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceNameRef res_name(package->name, type->type, entry->name); 758cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 759ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const auto& config_value : entry->values) { 760cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Special case the occurrence of an ID that is being generated 761ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // for the 'android' package. This is due to legacy reasons. 762d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (ValueCast<Id>(config_value->value.get()) && package->name == "android") { 763d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Warn(DiagMessage(config_value->value->GetSource()) 764d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "generated id '" << res_name 765d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "' for external package '" << package->name 766d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "'"); 767cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 768d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(config_value->value->GetSource()) 769d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "defined resource '" << res_name 770d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "' for external package '" << package->name 771d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "'"); 772cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 773cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 7741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 775cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 7761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 777cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 778cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 779979ccb2e6f3f1f7f00a448eb440a85daf033dc9eAdam Lesinski 780d0f492db038c6210c1138865d816bfb134376538Adam Lesinski auto new_end_iter = std::remove_if(final_table_.packages.begin(), final_table_.packages.end(), 781d0f492db038c6210c1138865d816bfb134376538Adam Lesinski is_ext_package_func); 782ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski final_table_.packages.erase(new_end_iter, final_table_.packages.end()); 783cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return !error; 784cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 785cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 786cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 787cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Returns true if no IDs have been set, false otherwise. 788cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 789ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool VerifyNoIdsSet() { 790ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const auto& package : final_table_.packages) { 791cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (const auto& type : package->types) { 792cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (type->id) { 793f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "type " << type->type << " has ID " 794f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski << StringPrintf("%02x", type->id.value()) 795f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski << " assigned"); 796cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 797cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 798cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 799cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (const auto& entry : type->entries) { 800cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (entry->id) { 801ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceNameRef res_name(package->name, type->type, entry->name); 802ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error( 803f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski DiagMessage() << "entry " << res_name << " has ID " 804f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski << StringPrintf("%02x", entry->id.value()) << " assigned"); 805cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 806cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 80764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 808cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 80964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 810cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 811cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 81264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 813ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<IArchiveWriter> MakeArchiveWriter(const StringPiece& out) { 814ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.output_to_directory) { 815ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return CreateDirectoryArchiveWriter(context_->GetDiagnostics(), out); 816cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 817ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return CreateZipFileArchiveWriter(context_->GetDiagnostics(), out); 8181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 819cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 8201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 821ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool FlattenTable(ResourceTable* table, IArchiveWriter* writer) { 822cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski BigBuffer buffer(1024); 823c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski TableFlattener flattener(options_.table_flattener_options, &buffer); 824ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!flattener.Consume(context_, table)) { 82506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed to flatten resource table"); 826cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 827cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 8281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 82906460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski io::BigBufferInputStream input_stream(&buffer); 830d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return io::CopyInputStreamToArchive(context_, &input_stream, "resources.arsc", 831d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ArchiveEntry::kAlign, writer); 832cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 833cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 834ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool FlattenTableToPb(ResourceTable* table, IArchiveWriter* writer) { 83506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski std::unique_ptr<pb::ResourceTable> pb_table = SerializeTableToPb(table); 836d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return io::CopyProtoToArchive(context_, pb_table.get(), "resources.arsc.flat", 0, writer); 837cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 8381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 839d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool WriteJavaFile(ResourceTable* table, const StringPiece& package_name_to_generate, 840ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& out_package, 841ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const JavaClassGeneratorOptions& java_options) { 842ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!options_.generate_java_class_path) { 843cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 8441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 8451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 846ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string out_path = options_.generate_java_class_path.value(); 847ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file::AppendPath(&out_path, file::PackageToPath(out_package)); 848ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!file::mkdirs(out_path)) { 849d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed to create directory '" << out_path 850d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "'"); 851cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 852cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 853ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 854ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file::AppendPath(&out_path, "R.java"); 855ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 856ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::ofstream fout(out_path, std::ofstream::binary); 857cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fout) { 858d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() 859d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed writing to '" << out_path 860d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "': " << android::base::SystemErrorCodeToString(errno)); 861cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 862ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 863ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 864ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski JavaClassGenerator generator(context_, table, java_options); 865ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!generator.Generate(package_name_to_generate, out_package, &fout)) { 86606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(out_path) << generator.getError()); 867cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 868cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 8691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 870cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fout) { 871d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() 872d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed writing to '" << out_path 873d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "': " << android::base::SystemErrorCodeToString(errno)); 8741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 875cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 876cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 8771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 878ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool WriteManifestJavaFile(xml::XmlResource* manifest_xml) { 879ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!options_.generate_java_class_path) { 880cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 88164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 88264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 883ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<ClassDefinition> manifest_class = 884ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski GenerateManifestClass(context_->GetDiagnostics(), manifest_xml); 88564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 886ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!manifest_class) { 887cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Something bad happened, but we already logged it, so exit. 888cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 88964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 89064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 891ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (manifest_class->empty()) { 892cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Empty Manifest class, no need to generate it. 893cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 894cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 89564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 896cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Add any JavaDoc annotations to the generated class. 897ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& annotation : options_.javadoc_annotations) { 898ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string proper_annotation = "@"; 899ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski proper_annotation += annotation; 900ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski manifest_class->GetCommentBuilder()->AppendComment(proper_annotation); 901cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 90264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 903ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const std::string& package_utf8 = context_->GetCompilationPackage(); 90464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 905ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string out_path = options_.generate_java_class_path.value(); 906ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file::AppendPath(&out_path, file::PackageToPath(package_utf8)); 90764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 908ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!file::mkdirs(out_path)) { 909d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed to create directory '" << out_path 910d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "'"); 911cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 912cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 91364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 914ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file::AppendPath(&out_path, "Manifest.java"); 91564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 916ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::ofstream fout(out_path, std::ofstream::binary); 917cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fout) { 918d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() 919d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed writing to '" << out_path 920d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "': " << android::base::SystemErrorCodeToString(errno)); 921cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 922cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 92364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 924d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8, true, &fout)) { 925d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() 926d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed writing to '" << out_path 927d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "': " << android::base::SystemErrorCodeToString(errno)); 928cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 929cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 930cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 931cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 93264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 933d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool WriteProguardFile(const Maybe<std::string>& out, const proguard::KeepSet& keep_set) { 934cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!out) { 935cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 936fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski } 937fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 938ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const std::string& out_path = out.value(); 939ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::ofstream fout(out_path, std::ofstream::binary); 940cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fout) { 941d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() 942d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed to open '" << out_path 943d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "': " << android::base::SystemErrorCodeToString(errno)); 944cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 945cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 946a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski 947ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski proguard::WriteKeepSet(&fout, keep_set); 948cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fout) { 949d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() 950d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed writing to '" << out_path 951d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "': " << android::base::SystemErrorCodeToString(errno)); 952cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 953cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 954cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 955cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 956fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 957ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<ResourceTable> LoadStaticLibrary(const std::string& input, 958ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string* out_error) { 959cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<io::ZipFileCollection> collection = 960ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::ZipFileCollection::Create(input, out_error); 961cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!collection) { 962cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return {}; 963cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 964ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return LoadTablePbFromCollection(collection.get()); 965cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 966fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 967d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::unique_ptr<ResourceTable> LoadTablePbFromCollection(io::IFileCollection* collection) { 968ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::IFile* file = collection->FindFile("resources.arsc.flat"); 969cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!file) { 970cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return {}; 971fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski } 972fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 973ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<io::IData> data = file->OpenAsData(); 974ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return LoadTableFromPb(file->GetSource(), data->data(), data->size(), 975ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()); 976cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 977fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 978ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool MergeStaticLibrary(const std::string& input, bool override) { 979ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 980d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage() << "merging static library " << input); 981cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 982fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 983ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string error_str; 984cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<io::ZipFileCollection> collection = 985ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::ZipFileCollection::Create(input, &error_str); 986cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!collection) { 987ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(input) << error_str); 988cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 989cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 990fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 991b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski std::unique_ptr<ResourceTable> table = LoadTablePbFromCollection(collection.get()); 992cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!table) { 993b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(input) << "invalid static library"); 994cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 995cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 996cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 997f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski ResourceTablePackage* pkg = table->FindPackageById(kAppPackageId); 998cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!pkg) { 999b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(input) << "static library has no package"); 1000cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1001cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1002cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1003cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool result; 1004ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.no_static_lib_packages) { 1005cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Merge all resources as if they were in the compilation package. This is 1006ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // the old behavior of aapt. 1007cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1008cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Add the package to the set of --extra-packages so we emit an R.java for 1009ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // each library package. 1010cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!pkg->name.empty()) { 1011ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options_.extra_java_packages.insert(pkg->name); 1012cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1013cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1014cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski pkg->name = ""; 1015cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (override) { 1016b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski result = table_merger_->MergeOverlay(Source(input), table.get(), collection.get()); 1017cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1018b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski result = table_merger_->Merge(Source(input), table.get(), collection.get()); 1019cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1020cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1021cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1022cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // This is the proper way to merge libraries, where the package name is 1023ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // preserved and resource names are mangled. 1024d0f492db038c6210c1138865d816bfb134376538Adam Lesinski result = 1025d0f492db038c6210c1138865d816bfb134376538Adam Lesinski table_merger_->MergeAndMangle(Source(input), pkg->name, table.get(), collection.get()); 1026cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1027cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1028cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!result) { 1029cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1030cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1031cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1032cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Make sure to move the collection into the set of IFileCollections. 1033ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski collections_.push_back(std::move(collection)); 1034cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 1035cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1036fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1037ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool MergeResourceTable(io::IFile* file, bool override) { 1038ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 1039d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage() << "merging resource table " 1040d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << file->GetSource()); 1041cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1042fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1043ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<io::IData> data = file->OpenAsData(); 1044cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!data) { 1045d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << "failed to open file"); 1046cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1047cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1048fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1049cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<ResourceTable> table = 1050d0f492db038c6210c1138865d816bfb134376538Adam Lesinski LoadTableFromPb(file->GetSource(), data->data(), data->size(), context_->GetDiagnostics()); 1051cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!table) { 1052cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1053fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski } 1054fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1055cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool result = false; 1056cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (override) { 1057ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result = table_merger_->MergeOverlay(file->GetSource(), table.get()); 1058cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1059ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result = table_merger_->Merge(file->GetSource(), table.get()); 1060cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1061cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return result; 1062cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 106364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 1064d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool MergeCompiledFile(io::IFile* file, ResourceFile* file_desc, bool override) { 1065ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 1066d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage() << "merging '" << file_desc->name 1067d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "' from compiled file " 1068d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << file->GetSource()); 1069cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1070a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski 1071cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool result = false; 1072cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (override) { 1073ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result = table_merger_->MergeFileOverlay(*file_desc, file); 1074cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1075ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result = table_merger_->MergeFile(*file_desc, file); 1076cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1077a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski 1078cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!result) { 1079cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1080cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1081a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski 1082cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Add the exports of this file to the table. 1083ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (SourcedResourceName& exported_symbol : file_desc->exported_symbols) { 1084ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (exported_symbol.name.package.empty()) { 1085ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski exported_symbol.name.package = context_->GetCompilationPackage(); 1086cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1087a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski 1088ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceNameRef res_name = exported_symbol.name; 10895eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 1090ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<ResourceName> mangled_name = 1091ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetNameMangler()->MangleName(exported_symbol.name); 1092ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (mangled_name) { 1093ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski res_name = mangled_name.value(); 1094cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 109552364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 1096cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<Id> id = util::make_unique<Id>(); 1097ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski id->SetSource(file_desc->source.WithLine(exported_symbol.line)); 1098ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool result = final_table_.AddResourceAllowMangled( 1099d0f492db038c6210c1138865d816bfb134376538Adam Lesinski res_name, ConfigDescription::DefaultConfig(), std::string(), std::move(id), 1100d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()); 1101cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!result) { 1102cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1103cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1105cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 1106cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1107cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1108cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 1109cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Takes a path to load as a ZIP file and merges the files within into the 1110cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * master ResourceTable. 1111cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * If override is true, conflicting resources are allowed to override each 1112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski * other, in order of last seen. 1113cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * 1114cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * An io::IFileCollection is created from the ZIP file and added to the set of 1115cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * io::IFileCollections that are open. 1116cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 1117ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool MergeArchive(const std::string& input, bool override) { 1118ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 1119d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage() << "merging archive " << input); 1120fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski } 1121fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1122ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string error_str; 1123cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<io::ZipFileCollection> collection = 1124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::ZipFileCollection::Create(input, &error_str); 1125cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!collection) { 1126ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(input) << error_str); 1127cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1128cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 112936c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1130cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool error = false; 1131ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto iter = collection->Iterator(); iter->HasNext();) { 1132ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!MergeFile(iter->Next(), override)) { 1133cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 1134cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1135cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 113636c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1137cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Make sure to move the collection into the set of IFileCollections. 1138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski collections_.push_back(std::move(collection)); 1139cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return !error; 1140cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1141cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1142cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 1143cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Takes a path to load and merge into the master ResourceTable. If override 1144cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * is true, 1145cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * conflicting resources are allowed to override each other, in order of last 1146cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * seen. 1147cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * 1148cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * If the file path ends with .flata, .jar, .jack, or .zip the file is treated 1149cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * as ZIP archive 1150cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * and the files within are merged individually. 1151cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * 1152cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Otherwise the files is processed on its own. 1153cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 1154ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool MergePath(const std::string& path, bool override) { 1155ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (util::EndsWith(path, ".flata") || util::EndsWith(path, ".jar") || 1156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski util::EndsWith(path, ".jack") || util::EndsWith(path, ".zip")) { 1157ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return MergeArchive(path, override); 1158ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else if (util::EndsWith(path, ".apk")) { 1159ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return MergeStaticLibrary(path, override); 1160ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 1161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 1162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::IFile* file = file_collection_->InsertFile(path); 1163ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return MergeFile(file, override); 1164cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1165cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1166cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 1167cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Takes a file to load and merge into the master ResourceTable. If override 1168cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * is true, 1169cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * conflicting resources are allowed to override each other, in order of last 1170cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * seen. 1171cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * 1172cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * If the file ends with .arsc.flat, then it is loaded as a ResourceTable and 1173cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * merged into the 1174cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * master ResourceTable. If the file ends with .flat, then it is treated like 1175cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * a compiled file 1176cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * and the header data is read and merged into the final ResourceTable. 1177cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * 1178cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * All other file types are ignored. This is because these files could be 1179cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * coming from a zip, 1180cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * where we could have other files like classes.dex. 1181cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 1182ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool MergeFile(io::IFile* file, bool override) { 1183ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const Source& src = file->GetSource(); 1184ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (util::EndsWith(src.path, ".arsc.flat")) { 1185ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return MergeResourceTable(file, override); 1186cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else if (util::EndsWith(src.path, ".flat")) { 1188cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Try opening the file and looking for an Export header. 1189ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<io::IData> data = file->OpenAsData(); 1190cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!data) { 1191ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to open"); 1192cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1193cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 119436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1195ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CompiledFileInputStream input_stream(data->data(), data->size()); 1196ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski uint32_t num_files = 0; 1197ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!input_stream.ReadLittleEndian32(&num_files)) { 1198d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(src) << "failed read num files"); 1199cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1200cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 120136c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1202ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (uint32_t i = 0; i < num_files; i++) { 1203ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski pb::CompiledFile compiled_file; 1204ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!input_stream.ReadCompiledFile(&compiled_file)) { 1205d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(src) 1206d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed to read compiled file header"); 1207cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 120836c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski } 120936c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1210cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski uint64_t offset, len; 1211ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!input_stream.ReadDataMetaData(&offset, &len)) { 1212d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to read data meta data"); 1213cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 121436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski } 121536c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1216d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::unique_ptr<ResourceFile> resource_file = DeserializeCompiledFileFromPb( 1217d0f492db038c6210c1138865d816bfb134376538Adam Lesinski compiled_file, file->GetSource(), context_->GetDiagnostics()); 1218ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!resource_file) { 1219cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 122036c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski } 122136c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1222d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!MergeCompiledFile(file->CreateFileSegment(offset, len), resource_file.get(), 1223d0f492db038c6210c1138865d816bfb134376538Adam Lesinski override)) { 1224cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 122536c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski } 1226cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1227cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 1228d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } else if (util::EndsWith(src.path, ".xml") || util::EndsWith(src.path, ".png")) { 12296a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski // Since AAPT compiles these file types and appends .flat to them, seeing 12306a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski // their raw extensions is a sign that they weren't compiled. 1231d0f492db038c6210c1138865d816bfb134376538Adam Lesinski const StringPiece file_type = util::EndsWith(src.path, ".xml") ? "XML" : "PNG"; 1232d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(src) << "uncompiled " << file_type 1233d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << " file passed as argument. Must be " 1234d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "compiled first into .flat file."); 12356a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski return false; 123636c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski } 123736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1238cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Ignore non .flat files. This could be classes.dex or something else that 1239cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // happens 1240cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // to be in an archive. 1241cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 1242cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1243cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1244b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski bool CopyAssetsDirsToApk(IArchiveWriter* writer) { 1245b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski std::map<std::string, std::unique_ptr<io::RegularFile>> merged_assets; 1246b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski for (const std::string& assets_dir : options_.assets_dirs) { 1247b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski Maybe<std::vector<std::string>> files = 1248b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski file::FindFiles(assets_dir, context_->GetDiagnostics(), nullptr); 1249b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski if (!files) { 1250b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski return false; 1251b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1252b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski 1253b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski for (const std::string& file : files.value()) { 1254b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski std::string full_key = "assets/" + file; 1255b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski std::string full_path = assets_dir; 1256b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski file::AppendPath(&full_path, file); 1257b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski 1258b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski auto iter = merged_assets.find(full_key); 1259b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski if (iter == merged_assets.end()) { 1260b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski merged_assets.emplace(std::move(full_key), 1261b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski util::make_unique<io::RegularFile>(Source(std::move(full_path)))); 1262b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } else if (context_->IsVerbose()) { 1263b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski context_->GetDiagnostics()->Warn(DiagMessage(iter->second->GetSource()) 1264b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski << "asset file overrides '" << full_path << "'"); 1265b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1266b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1267b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1268b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski 1269b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski for (auto& entry : merged_assets) { 1270b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski uint32_t compression_flags = ArchiveEntry::kCompress; 1271b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski std::string extension = file::GetExtension(entry.first).to_string(); 1272b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski if (options_.extensions_to_not_compress.count(extension) > 0) { 1273b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski compression_flags = 0u; 1274b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1275b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski 1276d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!io::CopyFileToArchive(context_, entry.second.get(), entry.first, compression_flags, 1277d0f492db038c6210c1138865d816bfb134376538Adam Lesinski writer)) { 1278b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski return false; 1279b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1280b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1281b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski return true; 1282b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1283b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski 1284cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 1285cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Writes the AndroidManifest, ResourceTable, and all XML files referenced by 1286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski * the ResourceTable to the IArchiveWriter. 1287cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 1288d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set, xml::XmlResource* manifest, 1289d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ResourceTable* table) { 1290ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski const bool keep_raw_values = options_.package_type == PackageType::kStaticLib; 1291d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool result = 1292d0f492db038c6210c1138865d816bfb134376538Adam Lesinski FlattenXml(manifest, "AndroidManifest.xml", {}, keep_raw_values, writer, context_); 1293cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!result) { 1294cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1295cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1296cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1297ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceFileFlattenerOptions file_flattener_options; 1298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_flattener_options.keep_raw_values = keep_raw_values; 1299d0f492db038c6210c1138865d816bfb134376538Adam Lesinski file_flattener_options.do_not_compress_anything = options_.do_not_compress_anything; 1300d0f492db038c6210c1138865d816bfb134376538Adam Lesinski file_flattener_options.extensions_to_not_compress = options_.extensions_to_not_compress; 1301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_flattener_options.no_auto_version = options_.no_auto_version; 1302ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_flattener_options.no_version_vectors = options_.no_version_vectors; 13034d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki file_flattener_options.no_version_transitions = options_.no_version_transitions; 1304ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_flattener_options.no_xml_namespaces = options_.no_xml_namespaces; 1305ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_flattener_options.update_proguard_spec = 1306ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski static_cast<bool>(options_.generate_proguard_rules_path); 1307cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1308ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski ResourceFileFlattener file_flattener(file_flattener_options, context_, keep_set); 1309cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!file_flattener.Flatten(table, writer)) { 1311ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed linking file resources"); 1312cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1313cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1314cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1315ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (options_.package_type == PackageType::kStaticLib) { 1316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!FlattenTableToPb(table, writer)) { 1317cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1318cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1319cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!FlattenTable(table, writer)) { 1321ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed to write resources.arsc"); 1322cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1323cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1324cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1325cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 1326cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 13279ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 1328ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski int Run(const std::vector<std::string>& input_files) { 1329cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Load the AndroidManifest.xml 1330ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<xml::XmlResource> manifest_xml = 1331ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski LoadXml(options_.manifest_path, context_->GetDiagnostics()); 1332ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!manifest_xml) { 1333cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1334cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 13351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1336d0f492db038c6210c1138865d816bfb134376538Adam Lesinski // First extract the Package name without modifying it (via --rename-manifest-package). 1337d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (Maybe<AppInfo> maybe_app_info = 1338d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics())) { 1339ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const AppInfo& app_info = maybe_app_info.value(); 1340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->SetCompilationPackage(app_info.package); 1341cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1342fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1343ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ManifestFixer manifest_fixer(options_.manifest_fixer_options); 1344ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!manifest_fixer.Consume(context_, manifest_xml.get())) { 1345cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1346cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 13471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1348d0f492db038c6210c1138865d816bfb134376538Adam Lesinski Maybe<AppInfo> maybe_app_info = 1349d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics()); 1350ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!maybe_app_info) { 1351cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1352cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 13531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const AppInfo& app_info = maybe_app_info.value(); 1355d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->SetMinSdkVersion(app_info.min_sdk_version.value_or_default(0)); 13561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1357d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->SetNameManglerPolicy(NameManglerPolicy{context_->GetCompilationPackage()}); 1358f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski 1359f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski // Override the package ID when it is "android". 1360f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (context_->GetCompilationPackage() == "android") { 1361ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->SetPackageId(0x01); 1362f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski 1363f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski // Verify we're building a regular app. 1364f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (options_.package_type != PackageType::kApp) { 1365f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context_->GetDiagnostics()->Error( 1366f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski DiagMessage() << "package 'android' can only be built as a regular app"); 1367f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski return 1; 1368f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } 1369cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 13701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1371ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!LoadSymbolsFromIncludePaths()) { 1372cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1373cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 13741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1375ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski TableMergerOptions table_merger_options; 1376ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_merger_options.auto_add_overlay = options_.auto_add_overlay; 1377d0f492db038c6210c1138865d816bfb134376538Adam Lesinski table_merger_ = util::make_unique<TableMerger>(context_, &final_table_, table_merger_options); 13781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1379ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 1380ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage() 1381f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski << StringPrintf("linking package '%s' using package ID %02x", 1382f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context_->GetCompilationPackage().data(), 1383f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context_->GetPackageId())); 1384cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1385bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 1386ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& input : input_files) { 1387ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!MergePath(input, false)) { 1388d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed parsing input"); 1389cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1390cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1391cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 13921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1393ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& input : options_.overlay_files) { 1394ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!MergePath(input, true)) { 1395d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed parsing overlays"); 1396cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1397cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1398cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 139964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 1400ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!VerifyNoExternalPackages()) { 1401cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1402cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 14031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1404ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (options_.package_type != PackageType::kStaticLib) { 1405cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski PrivateAttributeMover mover; 1406ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!mover.Consume(context_, &final_table_)) { 1407d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed moving private attributes"); 1408cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1409cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 141036c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1411cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Assign IDs if we are building a regular app. 1412ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski IdAssigner id_assigner(&options_.stable_id_map); 1413ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!id_assigner.Consume(context_, &final_table_)) { 1414ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed assigning IDs"); 1415cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1416cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 141736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1418cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Now grab each ID and emit it as a file. 1419ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.resource_id_map_path) { 1420ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& package : final_table_.packages) { 1421cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (auto& type : package->types) { 1422cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (auto& entry : type->entries) { 1423cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceName name(package->name, type->type, entry->name); 1424cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The IDs are guaranteed to exist. 1425d0f492db038c6210c1138865d816bfb134376538Adam Lesinski options_.stable_id_map[std::move(name)] = 1426d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ResourceId(package->id.value(), type->id.value(), entry->id.value()); 14271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1428cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 142936c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski } 143036c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1431d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!WriteStableIdMapToPath(context_->GetDiagnostics(), options_.stable_id_map, 1432ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options_.resource_id_map_path.value())) { 1433cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 143436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski } 1435cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1436cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1437cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Static libs are merged with other apps, and ID collisions are bad, so 1438cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // verify that 1439cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // no IDs have been set. 1440ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!VerifyNoIdsSet()) { 1441cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1442cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1443cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1444cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1445cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Add the names to mangle based on our source merge earlier. 1446d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->SetNameManglerPolicy( 1447d0f492db038c6210c1138865d816bfb134376538Adam Lesinski NameManglerPolicy{context_->GetCompilationPackage(), table_merger_->merged_packages()}); 1448cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1449cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Add our table to the symbol table. 1450ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetExternalSymbols()->PrependSource( 1451ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski util::make_unique<ResourceTableSymbolSource>(&final_table_)); 1452cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1453cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ReferenceLinker linker; 1454ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!linker.Consume(context_, &final_table_)) { 1455d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed linking references"); 1456cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1457cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1458cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1459ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (options_.package_type == PackageType::kStaticLib) { 1460ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!options_.products.empty()) { 1461ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Warn(DiagMessage() 1462ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski << "can't select products when building static library"); 1463cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1464cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1465ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ProductFilter product_filter(options_.products); 1466ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!product_filter.Consume(context_, &final_table_)) { 1467ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed stripping products"); 1468cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1469cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1470cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 147136c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1472ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!options_.no_auto_version) { 1473cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AutoVersioner versioner; 1474ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!versioner.Consume(context_, &final_table_)) { 1475d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed versioning styles"); 1476cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1477cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1478cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 147977788eb4cf0c5dba0f7370192e40364fe853050aAlexandria Cornwall 1480ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (options_.package_type != PackageType::kStaticLib && context_->GetMinSdkVersion() > 0) { 1481ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 1482d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage() 1483d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "collapsing resource versions for minimum SDK " 1484d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << context_->GetMinSdkVersion()); 1485cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 148636c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1487cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski VersionCollapser collapser; 1488ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!collapser.Consume(context_, &final_table_)) { 1489cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1490cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1491cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1492355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 1493ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!options_.no_resource_deduping) { 1494cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceDeduper deduper; 1495ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!deduper.Consume(context_, &final_table_)) { 1496ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed deduping resources"); 1497cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1498cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1499cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1500cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1501ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski proguard::KeepSet proguard_keep_set; 1502ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski proguard::KeepSet proguard_main_dex_keep_set; 1503cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1504ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (options_.package_type == PackageType::kStaticLib) { 1505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.table_splitter_options.config_filter != nullptr || 1506672384b41e1fc7195424533b7aa6753fb771a6cbPierre Lecesne !options_.table_splitter_options.preferred_densities.empty()) { 1507ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Warn(DiagMessage() 1508ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski << "can't strip resources when building static library"); 1509cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1510cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1511d0f492db038c6210c1138865d816bfb134376538Adam Lesinski // Adjust the SplitConstraints so that their SDK version is stripped if it is less than or 1512d0f492db038c6210c1138865d816bfb134376538Adam Lesinski // equal to the minSdk. 1513d0f492db038c6210c1138865d816bfb134376538Adam Lesinski options_.split_constraints = 1514d0f492db038c6210c1138865d816bfb134376538Adam Lesinski AdjustSplitConstraintsForMinSdk(context_->GetMinSdkVersion(), options_.split_constraints); 1515cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1516d0f492db038c6210c1138865d816bfb134376538Adam Lesinski TableSplitter table_splitter(options_.split_constraints, options_.table_splitter_options); 1517ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!table_splitter.VerifySplitConstraints(context_)) { 1518cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1519cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1520ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_splitter.SplitTable(&final_table_); 1521cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1522cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Now we need to write out the Split APKs. 1523ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto path_iter = options_.split_paths.begin(); 1524d0f492db038c6210c1138865d816bfb134376538Adam Lesinski auto split_constraints_iter = options_.split_constraints.begin(); 1525d0f492db038c6210c1138865d816bfb134376538Adam Lesinski for (std::unique_ptr<ResourceTable>& split_table : table_splitter.splits()) { 1526ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 1527d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage(*path_iter) 1528d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "generating split with configurations '" 1529d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << util::Joiner(split_constraints_iter->configs, ", ") 1530d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "'"); 15311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 15321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1533d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::unique_ptr<IArchiveWriter> archive_writer = MakeArchiveWriter(*path_iter); 1534ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!archive_writer) { 1535d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed to create archive"); 1536cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 15371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 15381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1539cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Generate an AndroidManifest.xml for each split. 1540ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<xml::XmlResource> split_manifest = 1541ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski GenerateSplitManifest(app_info, *split_constraints_iter); 15421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1543cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski XmlReferenceLinker linker; 1544ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!linker.Consume(context_, split_manifest.get())) { 1545d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() 1546d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed to create Split AndroidManifest.xml"); 1547cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1548467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 1549467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 1550d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!WriteApk(archive_writer.get(), &proguard_keep_set, split_manifest.get(), 1551d0f492db038c6210c1138865d816bfb134376538Adam Lesinski split_table.get())) { 1552cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1553637b4820dc1858dacbf562ca65c13b4be0249e0eAlexandria Cornwall } 1554637b4820dc1858dacbf562ca65c13b4be0249e0eAlexandria Cornwall 1555ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ++path_iter; 1556ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ++split_constraints_iter; 1557cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1558cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 15599e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski 1560cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Start writing the base APK. 1561b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski std::unique_ptr<IArchiveWriter> archive_writer = MakeArchiveWriter(options_.output_path); 1562ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!archive_writer) { 1563b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed to create archive"); 1564cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1565cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 15669e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski 1567cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool error = false; 1568cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski { 1569cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // AndroidManifest.xml has no resource name, but the CallSite is built 1570cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // from the name 1571cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // (aka, which package the AndroidManifest.xml is coming from). 1572cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // So we give it a package name so it can see local resources. 1573ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski manifest_xml->file.name.package = context_->GetCompilationPackage(); 1574ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 1575ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XmlReferenceLinker manifest_linker; 1576ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (manifest_linker.Consume(context_, manifest_xml.get())) { 1577ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.generate_proguard_rules_path && 1578b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski !proguard::CollectProguardRulesForManifest(Source(options_.manifest_path), 1579b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski manifest_xml.get(), &proguard_keep_set)) { 1580cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 15811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 15821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1583ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.generate_main_dex_proguard_rules_path && 1584b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski !proguard::CollectProguardRulesForManifest(Source(options_.manifest_path), 1585b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski manifest_xml.get(), 1586b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski &proguard_main_dex_keep_set, true)) { 1587cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 1588e49bb30dab4c37926962e8b408045e5a45f52c40Rohit Agrawal } 1589e49bb30dab4c37926962e8b408045e5a45f52c40Rohit Agrawal 1590ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.generate_java_class_path) { 1591ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!WriteManifestJavaFile(manifest_xml.get())) { 1592cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 1593cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 15941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 15951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1596ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.no_xml_namespaces) { 1597cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // PackageParser will fail if URIs are removed from 1598cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // AndroidManifest.xml. 1599ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XmlNamespaceRemover namespace_remover(true /* keepUris */); 1600ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!namespace_remover.Consume(context_, manifest_xml.get())) { 1601cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 1602cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 16031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1604cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1605cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 1606cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 16071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1608fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1609cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (error) { 1610b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed processing manifest"); 1611cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1612cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1613a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 1614b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski if (!WriteApk(archive_writer.get(), &proguard_keep_set, manifest_xml.get(), &final_table_)) { 1615b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski return 1; 1616b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1617b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski 1618b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski if (!CopyAssetsDirsToApk(archive_writer.get())) { 1619cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1620cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1621fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1622ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.generate_java_class_path) { 1623b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski // The set of packages whose R class to call in the main classes 1624b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski // onResourcesLoaded callback. 1625b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski std::vector<std::string> packages_to_callback; 1626b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski 1627b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski JavaClassGeneratorOptions template_options; 1628b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski template_options.types = JavaClassGeneratorOptions::SymbolTypes::kAll; 1629b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski template_options.javadoc_annotations = options_.javadoc_annotations; 1630fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski 1631ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (options_.package_type == PackageType::kStaticLib || options_.generate_non_final_ids) { 1632b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski template_options.use_final = false; 1633ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski } 1634ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 1635ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (options_.package_type == PackageType::kSharedLib) { 1636b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski template_options.use_final = false; 1637b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski template_options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{}; 1638cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 163964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 1640ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece actual_package = context_->GetCompilationPackage(); 1641ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski StringPiece output_package = context_->GetCompilationPackage(); 1642ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.custom_java_package) { 1643cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Override the output java package to the custom one. 1644ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski output_package = options_.custom_java_package.value(); 1645cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 16461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1647b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski // Generate the private symbols if required. 1648ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.private_symbols) { 1649b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski packages_to_callback.push_back(options_.private_symbols.value()); 1650b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski 1651cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // If we defined a private symbols package, we only emit Public symbols 1652cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // to the original package, and private and public symbols to the 1653cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // private package. 1654b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski JavaClassGeneratorOptions options = template_options; 1655b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate; 1656b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski if (!WriteJavaFile(&final_table_, actual_package, options_.private_symbols.value(), 1657b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski options)) { 1658b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski return 1; 1659b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski } 1660b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski } 16611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1662b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski // Generate all the symbols for all extra packages. 1663b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski for (const std::string& extra_package : options_.extra_java_packages) { 1664b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski packages_to_callback.push_back(extra_package); 1665b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski 1666b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski JavaClassGeneratorOptions options = template_options; 1667b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski options.types = JavaClassGeneratorOptions::SymbolTypes::kAll; 1668b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski if (!WriteJavaFile(&final_table_, actual_package, extra_package, options)) { 1669cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1670c51562cf5acda7849a34c4ae2a88077c068859c0Adam Lesinski } 1671b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski } 16721e21ff00b005110128245a4b0d13a7513a2d5e0cAdam Lesinski 1673b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski // Generate the main public R class. 1674b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski JavaClassGeneratorOptions options = template_options; 1675b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski 1676b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski // Only generate public symbols if we have a private package. 1677b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski if (options_.private_symbols) { 1678b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic; 1679cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1680c51562cf5acda7849a34c4ae2a88077c068859c0Adam Lesinski 1681b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski if (options.rewrite_callback_options) { 1682b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski options.rewrite_callback_options.value().packages_to_callback = 1683b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski std::move(packages_to_callback); 1684cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 168564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 1686b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski if (!WriteJavaFile(&final_table_, actual_package, output_package, options)) { 1687b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski return 1; 1688cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1689fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski } 1690fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski 1691b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski if (!WriteProguardFile(options_.generate_proguard_rules_path, proguard_keep_set)) { 1692cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1693e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 1694e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 1695ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!WriteProguardFile(options_.generate_main_dex_proguard_rules_path, 1696ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski proguard_main_dex_keep_set)) { 1697cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1698cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1699cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 0; 1700cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1701355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 1702cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private: 1703ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski LinkOptions options_; 1704ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski LinkContext* context_; 1705ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceTable final_table_; 1706355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 1707ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<TableMerger> table_merger_; 1708355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 1709cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // A pointer to the FileCollection representing the filesystem (not archives). 1710ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<io::FileCollection> file_collection_; 17116a008170cb18666e04c42856f992fc7a0afa1e1fAdam Lesinski 1712cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // A vector of IFileCollections. This is mainly here to keep ownership of the 1713cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // collections. 1714ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::unique_ptr<io::IFileCollection>> collections_; 1715bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 1716cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // A vector of ResourceTables. This is here to retain ownership, so that the 1717ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski // SymbolTable can use these. 1718ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::unique_ptr<ResourceTable>> static_table_includes_; 1719ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 1720ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski // The set of shared libraries being used, mapping their assigned package ID to package name. 1721ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski std::map<size_t, std::string> shared_libs_; 1722cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}; 172336c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1724ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiint Link(const std::vector<StringPiece>& args) { 1725cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski LinkContext context; 1726cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski LinkOptions options; 1727ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> overlay_arg_list; 1728ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> extra_java_packages; 1729f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski Maybe<std::string> package_id; 1730113ee097386380daa8f01d74916504a9a1338a63Adam Lesinski std::vector<std::string> configs; 1731ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> preferred_density; 1732ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> product_list; 1733ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool legacy_x_flag = false; 1734ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool require_localization = false; 1735cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool verbose = false; 1736ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski bool shared_lib = false; 1737ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski bool static_lib = false; 1738ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> stable_id_file_path; 1739ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> split_args; 1740cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Flags flags = 1741cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Flags() 1742d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .RequiredFlag("-o", "Output path.", &options.output_path) 1743d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .RequiredFlag("--manifest", "Path to the Android manifest to build.", 1744ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.manifest_path) 1745d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalFlagList("-I", "Adds an Android APK to link against.", &options.include_paths) 1746b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski .OptionalFlagList("-A", 1747b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski "An assets directory to include in the APK. These are unprocessed.", 1748b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski &options.assets_dirs) 1749c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlagList("-R", 1750c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski "Compilation unit to link, using `overlay` semantics.\n" 1751c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski "The last conflicting resource given takes precedence.", 1752c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &overlay_arg_list) 1753f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski .OptionalFlag("--package-id", 1754f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski "Specify the package ID to use for this app. Must be greater or equal to\n" 1755f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski "0x7f and can't be used with --static-lib or --shared-lib.", 1756f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski &package_id) 1757d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalFlag("--java", "Directory in which to generate R.java.", 1758ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.generate_java_class_path) 1759d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalFlag("--proguard", "Output file for generated Proguard rules.", 1760ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.generate_proguard_rules_path) 1761c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlag("--proguard-main-dex", 1762d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Output file for generated Proguard rules for the main dex.", 1763c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &options.generate_main_dex_proguard_rules_path) 1764d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalSwitch("--no-auto-version", 1765d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Disables automatic style and layout SDK versioning.", 1766ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.no_auto_version) 1767ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalSwitch("--no-version-vectors", 1768d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Disables automatic versioning of vector drawables. Use this only\n" 1769d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "when building with vector drawable support library.", 1770ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.no_version_vectors) 17714d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki .OptionalSwitch("--no-version-transitions", 1772d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Disables automatic versioning of transition resources. Use this only\n" 1773d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "when building with transition support library.", 17744d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki &options.no_version_transitions) 1775ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalSwitch("--no-resource-deduping", 1776cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "Disables automatic deduping of resources with\n" 1777cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "identical values across compatible configurations.", 1778ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.no_resource_deduping) 1779c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalSwitch("--enable-sparse-encoding", 1780c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski "Enables encoding sparse entries using a binary search tree.\n" 1781c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski "This decreases APK size at the cost of resource retrieval performance.", 1782c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &options.table_flattener_options.use_sparse_entries) 1783d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01.", 1784c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &legacy_x_flag) 1785d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalSwitch("-z", "Require localization of strings marked 'suggested'.", 1786ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &require_localization) 1787113ee097386380daa8f01d74916504a9a1338a63Adam Lesinski .OptionalFlagList("-c", 1788c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski "Comma separated list of configurations to include. The default\n" 1789d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "is all configurations.", 1790c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &configs) 1791c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlag("--preferred-density", 1792c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski "Selects the closest matching density and strips out all others.", 1793c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &preferred_density) 1794c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlag("--product", "Comma separated list of product names to keep", &product_list) 1795ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalSwitch("--output-to-dir", 1796d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Outputs the APK contents to a directory specified by -o.", 1797ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.output_to_directory) 1798ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalSwitch("--no-xml-namespaces", 1799d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Removes XML namespace prefix and URI information from\n" 1800d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "AndroidManifest.xml and XML binaries in res/*.", 1801ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.no_xml_namespaces) 1802ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalFlag("--min-sdk-version", 1803d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Default minimum SDK version to use for AndroidManifest.xml.", 1804ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.manifest_fixer_options.min_sdk_version_default) 1805c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlag("--target-sdk-version", 1806d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Default target SDK version to use for AndroidManifest.xml.", 1807c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &options.manifest_fixer_options.target_sdk_version_default) 1808ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalFlag("--version-code", 1809d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Version code (integer) to inject into the AndroidManifest.xml if none is\n" 1810d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "present.", 1811ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.manifest_fixer_options.version_code_default) 1812ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalFlag("--version-name", 1813d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Version name to inject into the AndroidManifest.xml if none is present.", 1814ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.manifest_fixer_options.version_name_default) 1815d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalSwitch("--shared-lib", "Generates a shared Android runtime library.", 1816d0f492db038c6210c1138865d816bfb134376538Adam Lesinski &shared_lib) 1817d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib) 1818ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalSwitch("--no-static-lib-packages", 1819d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Merge all library resources under the app's package.", 1820ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.no_static_lib_packages) 1821ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalSwitch("--non-final-ids", 1822d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Generates R.java without the final modifier. This is implied when\n" 1823d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "--static-lib is specified.", 1824ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.generate_non_final_ids) 1825c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlag("--stable-ids", "File containing a list of name to ID mapping.", 1826ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &stable_id_file_path) 1827c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlag("--emit-ids", 1828d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Emit a file at the given path with a list of name to ID mappings,\n" 1829d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "suitable for use with --stable-ids.", 1830c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &options.resource_id_map_path) 1831ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalFlag("--private-symbols", 1832d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Package name to use when generating R.java for private symbols.\n" 1833d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "If not specified, public and private symbols will use the application's\n" 1834d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "package name.", 1835ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.private_symbols) 1836d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalFlag("--custom-package", "Custom Java package under which to generate R.java.", 1837ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.custom_java_package) 1838ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalFlagList("--extra-packages", 1839d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Generate the same R.java but with different package names.", 1840ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &extra_java_packages) 1841ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalFlagList("--add-javadoc-annotation", 1842d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Adds a JavaDoc annotation to all generated Java classes.", 1843ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.javadoc_annotations) 1844ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalSwitch("--auto-add-overlay", 1845d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Allows the addition of new resources in overlays without\n" 1846d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "<add-resource> tags.", 1847ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.auto_add_overlay) 1848d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml.", 1849ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.manifest_fixer_options.rename_manifest_package) 1850c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlag("--rename-instrumentation-target-package", 1851d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Changes the name of the target package for instrumentation. Most useful\n" 1852d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "when used in conjunction with --rename-manifest-package.", 1853c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &options.manifest_fixer_options.rename_instrumentation_target_package) 1854d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalFlagList("-0", "File extensions not to compress.", 1855ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.extensions_to_not_compress) 1856c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlagList("--split", 1857d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Split resources matching a set of configs out to a Split APK.\n" 1858d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Syntax: path/to/output.apk:<config>[,<config>[...]].", 1859c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &split_args) 1860d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalSwitch("-v", "Enables verbose logging.", &verbose); 1861cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1862ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!flags.Parse("aapt2 link", args, &std::cerr)) { 1863cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1864cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1865cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1866d0f492db038c6210c1138865d816bfb134376538Adam Lesinski // Expand all argument-files passed into the command line. These start with '@'. 1867ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> arg_list; 1868ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& arg : flags.GetArgs()) { 1869ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (util::StartsWith(arg, "@")) { 1870cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const std::string path = arg.substr(1, arg.size() - 1); 1871cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string error; 1872ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!file::AppendArgsFromFile(path, &arg_list, &error)) { 1873ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context.GetDiagnostics()->Error(DiagMessage(path) << error); 1874cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1875cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1876cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1877ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski arg_list.push_back(arg); 1878cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1879cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1880cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1881cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Expand all argument-files passed to -R. 1882ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& arg : overlay_arg_list) { 1883ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (util::StartsWith(arg, "@")) { 1884cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const std::string path = arg.substr(1, arg.size() - 1); 1885cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string error; 1886ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!file::AppendArgsFromFile(path, &options.overlay_files, &error)) { 1887ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context.GetDiagnostics()->Error(DiagMessage(path) << error); 1888cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1889cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1890cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1891ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options.overlay_files.push_back(arg); 1892cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1893cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1894cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1895cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (verbose) { 1896ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context.SetVerbose(verbose); 1897cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1898cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1899f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (shared_lib && static_lib) { 1900f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.GetDiagnostics()->Error(DiagMessage() 1901f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski << "only one of --shared-lib and --static-lib can be defined"); 1902f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski return 1; 1903f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } 1904f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski 1905f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (shared_lib) { 1906f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski options.package_type = PackageType::kSharedLib; 1907f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.SetPackageId(0x00); 1908f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } else if (static_lib) { 1909f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski options.package_type = PackageType::kStaticLib; 1910f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.SetPackageId(kAppPackageId); 1911f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } else { 1912f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski options.package_type = PackageType::kApp; 1913f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.SetPackageId(kAppPackageId); 1914f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } 1915f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski 1916f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (package_id) { 1917f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (options.package_type != PackageType::kApp) { 1918f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.GetDiagnostics()->Error( 1919f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski DiagMessage() << "can't specify --package-id when not building a regular app"); 1920f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski return 1; 1921f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } 1922f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski 1923f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski const Maybe<uint32_t> maybe_package_id_int = ResourceUtils::ParseInt(package_id.value()); 1924f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (!maybe_package_id_int) { 1925f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.GetDiagnostics()->Error(DiagMessage() << "package ID '" << package_id.value() 1926f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski << "' is not a valid integer"); 1927f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski return 1; 1928f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } 1929f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski 1930f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski const uint32_t package_id_int = maybe_package_id_int.value(); 1931f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (package_id_int < kAppPackageId || package_id_int > std::numeric_limits<uint8_t>::max()) { 1932f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.GetDiagnostics()->Error( 1933f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski DiagMessage() << StringPrintf( 1934f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski "invalid package ID 0x%02x. Must be in the range 0x7f-0xff.", package_id_int)); 1935f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski return 1; 1936f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } 1937f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.SetPackageId(static_cast<uint8_t>(package_id_int)); 1938f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } 1939f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski 1940cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Populate the set of extra packages for which to generate R.java. 1941ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (std::string& extra_package : extra_java_packages) { 1942cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // A given package can actually be a colon separated list of packages. 1943ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (StringPiece package : util::Split(extra_package, ':')) { 1944d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski options.extra_java_packages.insert(package.to_string()); 1945cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1946cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1947cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1948ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (product_list) { 1949ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (StringPiece product : util::Tokenize(product_list.value(), ',')) { 1950cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (product != "" && product != "default") { 1951d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski options.products.insert(product.to_string()); 1952cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1953cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1954cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1955cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1956d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::unique_ptr<IConfigFilter> filter; 1957f4dacf29cc995fad4aea8e8f25811f9ee4685d91Mihai Nita if (!configs.empty()) { 1958d0f492db038c6210c1138865d816bfb134376538Adam Lesinski filter = ParseConfigFilterParameters(configs, context.GetDiagnostics()); 1959d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (filter == nullptr) { 1960d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return 1; 1961cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1962d0f492db038c6210c1138865d816bfb134376538Adam Lesinski options.table_splitter_options.config_filter = filter.get(); 1963cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1964cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1965ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (preferred_density) { 1966d0f492db038c6210c1138865d816bfb134376538Adam Lesinski Maybe<uint16_t> density = 1967d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ParseTargetDensityParameter(preferred_density.value(), context.GetDiagnostics()); 1968d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!density) { 1969cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1970cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1971d0f492db038c6210c1138865d816bfb134376538Adam Lesinski options.table_splitter_options.preferred_densities.push_back(density.value()); 1972d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 1973cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1974d0f492db038c6210c1138865d816bfb134376538Adam Lesinski // Parse the split parameters. 1975d0f492db038c6210c1138865d816bfb134376538Adam Lesinski for (const std::string& split_arg : split_args) { 1976d0f492db038c6210c1138865d816bfb134376538Adam Lesinski options.split_paths.push_back({}); 1977d0f492db038c6210c1138865d816bfb134376538Adam Lesinski options.split_constraints.push_back({}); 1978d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!ParseSplitParameter(split_arg, context.GetDiagnostics(), &options.split_paths.back(), 1979d0f492db038c6210c1138865d816bfb134376538Adam Lesinski &options.split_constraints.back())) { 1980cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1981cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1982cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1983cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1984ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (options.package_type != PackageType::kStaticLib && stable_id_file_path) { 1985ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!LoadStableIdMap(context.GetDiagnostics(), stable_id_file_path.value(), 1986ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.stable_id_map)) { 1987cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1988cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1989cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1990cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1991cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Populate some default no-compress extensions that are already compressed. 1992ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options.extensions_to_not_compress.insert( 1993cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski {".jpg", ".jpeg", ".png", ".gif", ".wav", ".mp2", ".mp3", ".ogg", 1994cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ".aac", ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet", ".rtttl", 1995cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ".imy", ".xmf", ".mp4", ".m4a", ".m4v", ".3gp", ".3gpp", ".3g2", 1996cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ".3gpp2", ".amr", ".awb", ".wma", ".wmv", ".webm", ".mkv"}); 1997cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1998cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Turn off auto versioning for static-libs. 1999ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (options.package_type == PackageType::kStaticLib) { 2000ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options.no_auto_version = true; 2001ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options.no_version_vectors = true; 20024d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki options.no_version_transitions = true; 2003cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2004cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 2005cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski LinkCommand cmd(&context, options); 2006ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return cmd.Run(arg_list); 20071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 20081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2009cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} // namespace aapt 2010