Link.cpp revision 1e4b0e54a3db31bdbcb9385bf22bab4b96096d1f
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 681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct LinkOptions { 69ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string output_path; 70ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string manifest_path; 71ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> include_paths; 72ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> overlay_files; 73b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski std::vector<std::string> assets_dirs; 74ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool output_to_directory = false; 75ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool auto_add_overlay = false; 76cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 77cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Java/Proguard options. 78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> generate_java_class_path; 79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> custom_java_package; 80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::set<std::string> extra_java_packages; 81418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski Maybe<std::string> generate_text_symbols_path; 82ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> generate_proguard_rules_path; 83ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> generate_main_dex_proguard_rules_path; 84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool generate_non_final_ids = false; 85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> javadoc_annotations; 86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> private_symbols; 87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // Optimizations/features. 89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_auto_version = false; 90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_version_vectors = false; 914d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki bool no_version_transitions = false; 92ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_resource_deduping = false; 93ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_xml_namespaces = false; 94ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool do_not_compress_anything = false; 95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unordered_set<std::string> extensions_to_not_compress; 96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // Static lib options. 98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_static_lib_packages = false; 99ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // AndroidManifest.xml massaging options. 101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ManifestFixerOptions manifest_fixer_options; 102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 103ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // Products to use/filter on. 104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unordered_set<std::string> products; 105cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 106c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski // Flattening options. 107c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski TableFlattenerOptions table_flattener_options; 108c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 109cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Split APK options. 110ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski TableSplitterOptions table_splitter_options; 111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<SplitConstraints> split_constraints; 112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> split_paths; 113cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 114cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Stable ID options. 115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unordered_map<ResourceName, ResourceId> stable_id_map; 116ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> resource_id_map_path; 1171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}; 1181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 11964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiclass LinkContext : public IAaptContext { 120cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public: 121d0f492db038c6210c1138865d816bfb134376538Adam Lesinski LinkContext() : name_mangler_({}), symbols_(&name_mangler_) { 122d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 1231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 124b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski PackageType GetPackageType() override { 125b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski return package_type_; 126b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski } 127b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski 128b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski void SetPackageType(PackageType type) { 129b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski package_type_ = type; 130b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski } 131b522f04bc2a581e2877bef4a44ac00b827f879edAdam 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 183b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski PackageType package_type_ = PackageType::kApp; 184ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski StdErrDiagnostics diagnostics_; 185ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski NameMangler name_mangler_; 186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string compilation_package_; 187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski uint8_t package_id_ = 0x0; 188ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski SymbolTable symbols_; 189ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool verbose_ = false; 190ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski int min_sdk_version_ = 0; 1911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}; 1921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1931e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// A custom delegate that generates compatible pre-O IDs for use with feature splits. 1941e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// Feature splits use package IDs > 7f, which in Java (since Java doesn't have unsigned ints) 1951e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// is interpreted as a negative number. Some verification was wrongly assuming negative values 1961e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// were invalid. 1971e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// 1981e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// This delegate will attempt to masquerade any '@id/' references with ID 0xPPTTEEEE, 1991e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// where PP > 7f, as 0x7fPPEEEE. Any potential overlapping is verified and an error occurs if such 2001e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// an overlap exists. 2011e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinskiclass FeatureSplitSymbolTableDelegate : public DefaultSymbolTableDelegate { 2021e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski public: 2031e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski FeatureSplitSymbolTableDelegate(IAaptContext* context) : context_(context) { 2041e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski } 2051e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski 2061e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski virtual ~FeatureSplitSymbolTableDelegate() = default; 2071e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski 2081e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski virtual std::unique_ptr<SymbolTable::Symbol> FindByName( 2091e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski const ResourceName& name, 2101e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski const std::vector<std::unique_ptr<ISymbolSource>>& sources) override { 2111e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski std::unique_ptr<SymbolTable::Symbol> symbol = 2121e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski DefaultSymbolTableDelegate::FindByName(name, sources); 2131e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski if (symbol == nullptr) { 2141e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski return {}; 2151e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski } 2161e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski 2171e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski // Check to see if this is an 'id' with the target package. 2181e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski if (name.type == ResourceType::kId && symbol->id) { 2191e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski ResourceId* id = &symbol->id.value(); 2201e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski if (id->package_id() > kAppPackageId) { 2211e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski // Rewrite the resource ID to be compatible pre-O. 2221e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski ResourceId rewritten_id(kAppPackageId, id->package_id(), id->entry_id()); 2231e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski 2241e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski // Check that this doesn't overlap another resource. 2251e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski if (DefaultSymbolTableDelegate::FindById(rewritten_id, sources) != nullptr) { 2261e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski // The ID overlaps, so log a message (since this is a weird failure) and fail. 2271e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "Failed to rewrite " << name 2281e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski << " for pre-O feature split support"); 2291e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski return {}; 2301e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski } 2311e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski 2321e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski if (context_->IsVerbose()) { 2331e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski context_->GetDiagnostics()->Note(DiagMessage() << "rewriting " << name << " (" << *id 2341e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski << ") -> (" << rewritten_id << ")"); 2351e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski } 2361e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski 2371e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski *id = rewritten_id; 2381e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski } 2391e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski } 2401e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski return symbol; 2411e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski } 2421e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski 2431e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski private: 2441e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski DISALLOW_COPY_AND_ASSIGN(FeatureSplitSymbolTableDelegate); 2451e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski 2461e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski IAaptContext* context_; 2471e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski}; 2481e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski 249ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic bool FlattenXml(xml::XmlResource* xml_res, const StringPiece& path, 250d0f492db038c6210c1138865d816bfb134376538Adam Lesinski Maybe<size_t> max_sdk_level, bool keep_raw_values, IArchiveWriter* writer, 251d0f492db038c6210c1138865d816bfb134376538Adam Lesinski IAaptContext* context) { 252cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski BigBuffer buffer(1024); 253cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski XmlFlattenerOptions options = {}; 254ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options.keep_raw_values = keep_raw_values; 255ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options.max_sdk_level = max_sdk_level; 256cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski XmlFlattener flattener(&buffer, options); 257ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!flattener.Consume(context, xml_res)) { 258cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 259cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 261ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context->IsVerbose()) { 262cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski DiagMessage msg; 263cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski msg << "writing " << path << " to archive"; 264ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (max_sdk_level) { 265d0f492db038c6210c1138865d816bfb134376538Adam Lesinski msg << " maxSdkLevel=" << max_sdk_level.value() << " keepRawValues=" << keep_raw_values; 266355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 267ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context->GetDiagnostics()->Note(msg); 268cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 26959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 27006460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski io::BigBufferInputStream input_stream(&buffer); 271d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return io::CopyInputStreamToArchive(context, &input_stream, path.to_string(), 272d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ArchiveEntry::kCompress, writer); 273355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 27459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 275d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic std::unique_ptr<ResourceTable> LoadTableFromPb(const Source& source, const void* data, 276d0f492db038c6210c1138865d816bfb134376538Adam Lesinski size_t len, IDiagnostics* diag) { 277ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski pb::ResourceTable pb_table; 278ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!pb_table.ParseFromArray(data, len)) { 279ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(source) << "invalid compiled table"); 280cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return {}; 281cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 282cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 28306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski std::unique_ptr<ResourceTable> table = DeserializeTableFromPb(pb_table, source, diag); 284cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!table) { 285cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return {}; 286cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 287cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return table; 288355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 2891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 290355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski/** 291355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * Inflates an XML file from the source path. 292355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski */ 293d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path, IDiagnostics* diag) { 294cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::ifstream fin(path, std::ifstream::binary); 295cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fin) { 296ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(path) << strerror(errno)); 297cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return {}; 298cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return xml::Inflate(&fin, diag, Source(path)); 300355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 3011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 302355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskistruct ResourceFileFlattenerOptions { 303ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_auto_version = false; 304ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_version_vectors = false; 3054d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki bool no_version_transitions = false; 306ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool no_xml_namespaces = false; 307ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool keep_raw_values = false; 308ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool do_not_compress_anything = false; 309ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool update_proguard_spec = false; 310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unordered_set<std::string> extensions_to_not_compress; 311355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}; 312355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 313355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskiclass ResourceFileFlattener { 314cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public: 315d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ResourceFileFlattener(const ResourceFileFlattenerOptions& options, IAaptContext* context, 316d0f492db038c6210c1138865d816bfb134376538Adam Lesinski proguard::KeepSet* keep_set) 317d0f492db038c6210c1138865d816bfb134376538Adam Lesinski : options_(options), context_(context), keep_set_(keep_set) { 318d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 3191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool Flatten(ResourceTable* table, IArchiveWriter* archive_writer); 321355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 322cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private: 323cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski struct FileOperation { 324cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ConfigDescription config; 3255eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 326cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The entry this file came from. 327cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const ResourceEntry* entry; 3285eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 329cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The file to copy as-is. 330ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::IFile* file_to_copy; 3315eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 332cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The XML to process and flatten. 333ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<xml::XmlResource> xml_to_flatten; 3345eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 335cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The destination to write this file to. 336ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string dst_path; 337ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool skip_version = false; 338cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski }; 339355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski uint32_t GetCompressionFlags(const StringPiece& str); 341355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool LinkAndVersionXmlFile(ResourceTable* table, FileOperation* file_op, 343ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::queue<FileOperation>* out_file_op_queue); 344355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 345ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceFileFlattenerOptions options_; 346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski IAaptContext* context_; 347ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski proguard::KeepSet* keep_set_; 348355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}; 349355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 350ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiuint32_t ResourceFileFlattener::GetCompressionFlags(const StringPiece& str) { 351ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.do_not_compress_anything) { 352cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 0; 353cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 354355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& extension : options_.extensions_to_not_compress) { 356ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (util::EndsWith(str, extension)) { 357cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 0; 358355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 359cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 360cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ArchiveEntry::kCompress; 361355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 362355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 3634d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Arakistatic bool IsTransitionElement(const std::string& name) { 364d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return name == "fade" || name == "changeBounds" || name == "slide" || name == "explode" || 365d0f492db038c6210c1138865d816bfb134376538Adam Lesinski name == "changeImageTransform" || name == "changeTransform" || 366d0f492db038c6210c1138865d816bfb134376538Adam Lesinski name == "changeClipBounds" || name == "autoTransition" || name == "recolor" || 367d0f492db038c6210c1138865d816bfb134376538Adam Lesinski name == "changeScroll" || name == "transitionSet" || name == "transition" || 368d0f492db038c6210c1138865d816bfb134376538Adam Lesinski name == "transitionManager"; 3694d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki} 3704d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki 371d0f492db038c6210c1138865d816bfb134376538Adam Lesinskibool ResourceFileFlattener::LinkAndVersionXmlFile(ResourceTable* table, FileOperation* file_op, 372d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::queue<FileOperation>* out_file_op_queue) { 373ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski xml::XmlResource* doc = file_op->xml_to_flatten.get(); 374cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const Source& src = doc->file.source; 375355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 376ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 377ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage() << "linking " << src.path); 378cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 379355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 380ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XmlReferenceLinker xml_linker; 381ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!xml_linker.Consume(context_, doc)) { 382cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 383cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 384355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 385d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (options_.update_proguard_spec && !proguard::CollectProguardRules(src, doc, keep_set_)) { 386cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 387cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 388cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 389ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.no_xml_namespaces) { 390ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XmlNamespaceRemover namespace_remover; 391ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!namespace_remover.Consume(context_, doc)) { 392cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 393355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 394cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 395355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 396ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!options_.no_auto_version) { 397ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.no_version_vectors) { 398cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Skip this if it is a vector or animated-vector. 399ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski xml::Element* el = xml::FindRootElement(doc); 400ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (el && el->namespace_uri.empty()) { 401cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (el->name == "vector" || el->name == "animated-vector") { 402cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // We are NOT going to version this file. 403ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_op->skip_version = true; 404cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 405a7cc3f1d79eb7a02a68928381998137f2f9b10a3Alexandria Cornwall } 406cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 407a7cc3f1d79eb7a02a68928381998137f2f9b10a3Alexandria Cornwall } 4084d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki if (options_.no_version_transitions) { 4094d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki // Skip this if it is a transition resource. 4104d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki xml::Element* el = xml::FindRootElement(doc); 4114d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki if (el && el->namespace_uri.empty()) { 4124d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki if (IsTransitionElement(el->name)) { 4134d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki // We are NOT going to version this file. 4144d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki file_op->skip_version = true; 4154d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki return true; 4164d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki } 4174d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki } 4184d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki } 419a7cc3f1d79eb7a02a68928381998137f2f9b10a3Alexandria Cornwall 420ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ConfigDescription& config = file_op->config; 421cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 422cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Find the first SDK level used that is higher than this defined config and 423cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // not superseded by a lower or equal SDK level resource. 424ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const int min_sdk_version = context_->GetMinSdkVersion(); 425ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (int sdk_level : xml_linker.sdk_levels()) { 426ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (sdk_level > min_sdk_version && sdk_level > config.sdkVersion) { 427d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!ShouldGenerateVersionedResource(file_op->entry, config, sdk_level)) { 428cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // If we shouldn't generate a versioned resource, stop checking. 429cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski break; 430626a69f34536d01db0847df0051199beaecce060Adam Lesinski } 431626a69f34536d01db0847df0051199beaecce060Adam Lesinski 432ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceFile versioned_file_desc = doc->file; 433ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski versioned_file_desc.config.sdkVersion = (uint16_t)sdk_level; 434cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 435ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski FileOperation new_file_op; 436ea134e08d70d156bdd17714d5f9ab9c44c91d4faAdam Lesinski new_file_op.xml_to_flatten = util::make_unique<xml::XmlResource>( 437ea134e08d70d156bdd17714d5f9ab9c44c91d4faAdam Lesinski versioned_file_desc, StringPool{}, doc->root->Clone()); 438ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_file_op.config = versioned_file_desc.config; 439ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_file_op.entry = file_op->entry; 440d0f492db038c6210c1138865d816bfb134376538Adam Lesinski new_file_op.dst_path = 441d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ResourceUtils::BuildResourceFileName(versioned_file_desc, context_->GetNameMangler()); 442cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 443ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 444d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage(versioned_file_desc.source) 445d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "auto-versioning resource from config '" << config 446d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "' -> '" << versioned_file_desc.config << "'"); 447cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 448cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 449ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool added = table->AddFileReferenceAllowMangled( 450d0f492db038c6210c1138865d816bfb134376538Adam Lesinski versioned_file_desc.name, versioned_file_desc.config, versioned_file_desc.source, 451d0f492db038c6210c1138865d816bfb134376538Adam Lesinski new_file_op.dst_path, nullptr, context_->GetDiagnostics()); 452cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!added) { 453cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 45452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski } 455cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski out_file_op_queue->push(std::move(new_file_op)); 457cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski break; 458cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 45952364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski } 460cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 461cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 462355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 46352364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 464355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski/** 465cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Do not insert or remove any resources while executing in this function. It 466cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * will 467355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * corrupt the iteration order. 468355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski */ 469d0f492db038c6210c1138865d816bfb134376538Adam Lesinskibool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archive_writer) { 470cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool error = false; 471d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files; 472cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 473cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (auto& pkg : table->packages) { 474cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (auto& type : pkg->types) { 475cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Sort by config and name, so that we get better locality in the zip 476cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // file. 477ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski config_sorted_files.clear(); 478ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::queue<FileOperation> file_operations; 479cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 480cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Populate the queue with all files in the ResourceTable. 481cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (auto& entry : type->entries) { 482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& config_value : entry->values) { 483d0f492db038c6210c1138865d816bfb134376538Adam Lesinski FileReference* file_ref = ValueCast<FileReference>(config_value->value.get()); 484ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!file_ref) { 485cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski continue; 486cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 487355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 488ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::IFile* file = file_ref->file; 489cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!file) { 490ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(file_ref->GetSource()) 491cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << "file not found"); 492cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 493cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 494355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 495ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski FileOperation file_op; 496ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_op.entry = entry.get(); 497ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_op.dst_path = *file_ref->path; 498ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_op.config = config_value->config; 499355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 500ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece src_path = file->GetSource().path; 501cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (type->type != ResourceType::kRaw && 502d0f492db038c6210c1138865d816bfb134376538Adam Lesinski (util::EndsWith(src_path, ".xml.flat") || util::EndsWith(src_path, ".xml"))) { 503ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<io::IData> data = file->OpenAsData(); 504cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!data) { 505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(file->GetSource()) 506cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << "failed to open file"); 507cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 508355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 509355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 510d0f492db038c6210c1138865d816bfb134376538Adam Lesinski file_op.xml_to_flatten = xml::Inflate(data->data(), data->size(), 511d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics(), file->GetSource()); 512355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 513ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!file_op.xml_to_flatten) { 514cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 515a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } 516cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 517ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_op.xml_to_flatten->file.config = config_value->config; 518ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_op.xml_to_flatten->file.source = file_ref->GetSource(); 519d0f492db038c6210c1138865d816bfb134376538Adam Lesinski file_op.xml_to_flatten->file.name = ResourceName(pkg->name, type->type, entry->name); 520cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 521cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Enqueue the XML files to be processed. 522ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_operations.push(std::move(file_op)); 523cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 524ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_op.file_to_copy = file; 525cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 526cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // NOTE(adamlesinski): Explicitly construct a StringPiece here, or 527ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // else we end up copying the string in the std::make_pair() method, 528ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // then creating a StringPiece from the copy, which would cause us 529ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // to end up referencing garbage in the map. 530ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece entry_name(entry->name); 531d0f492db038c6210c1138865d816bfb134376538Adam Lesinski config_sorted_files[std::make_pair(config_value->config, entry_name)] = 532d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::move(file_op); 533cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 534cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 535cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 536cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 537cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Now process the XML queue 538ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (; !file_operations.empty(); file_operations.pop()) { 539ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski FileOperation& file_op = file_operations.front(); 540cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 541ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!LinkAndVersionXmlFile(table, &file_op, &file_operations)) { 542cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 543cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski continue; 544cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 545cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 546cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // NOTE(adamlesinski): Explicitly construct a StringPiece here, or else 547cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // we end up copying the string in the std::make_pair() method, then 548ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // creating a StringPiece from the copy, which would cause us to end up 549ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // referencing garbage in the map. 550ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece entry_name(file_op.entry->name); 551d0f492db038c6210c1138865d816bfb134376538Adam Lesinski config_sorted_files[std::make_pair(file_op.config, entry_name)] = std::move(file_op); 552cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 553cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 554cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (error) { 555cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 556cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 557cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 558cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Now flatten the sorted values. 559ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& map_entry : config_sorted_files) { 560ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ConfigDescription& config = map_entry.first.first; 561ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const FileOperation& file_op = map_entry.second; 562ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 563ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (file_op.xml_to_flatten) { 564ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<size_t> max_sdk_level; 565ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!options_.no_auto_version && !file_op.skip_version) { 566d0f492db038c6210c1138865d816bfb134376538Adam Lesinski max_sdk_level = std::max<size_t>(std::max<size_t>(config.sdkVersion, 1u), 567d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetMinSdkVersion()); 568cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 569cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 570d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool result = FlattenXml(file_op.xml_to_flatten.get(), file_op.dst_path, max_sdk_level, 571d0f492db038c6210c1138865d816bfb134376538Adam Lesinski options_.keep_raw_values, archive_writer, context_); 572cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!result) { 573cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 574cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 575cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 576d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool result = 577d0f492db038c6210c1138865d816bfb134376538Adam Lesinski io::CopyFileToArchive(context_, file_op.file_to_copy, file_op.dst_path, 578d0f492db038c6210c1138865d816bfb134376538Adam Lesinski GetCompressionFlags(file_op.dst_path), archive_writer); 579cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!result) { 580cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 581cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 5821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 583cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 584355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 585cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 586cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return !error; 587355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 588a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski 589d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic bool WriteStableIdMapToPath(IDiagnostics* diag, 590d0f492db038c6210c1138865d816bfb134376538Adam Lesinski const std::unordered_map<ResourceName, ResourceId>& id_map, 591d0f492db038c6210c1138865d816bfb134376538Adam Lesinski const std::string& id_map_path) { 592ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::ofstream fout(id_map_path, std::ofstream::binary); 593cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fout) { 594ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(id_map_path) << strerror(errno)); 595cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 596cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 597bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 598ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const auto& entry : id_map) { 599cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const ResourceName& name = entry.first; 600cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const ResourceId& id = entry.second; 601cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski fout << name << " = " << id << "\n"; 602cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 603bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 604cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fout) { 605d0f492db038c6210c1138865d816bfb134376538Adam Lesinski diag->Error(DiagMessage(id_map_path) << "failed writing to file: " 606d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << android::base::SystemErrorCodeToString(errno)); 607cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 608cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 609bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 610cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 611bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski} 612bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 613d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic bool LoadStableIdMap(IDiagnostics* diag, const std::string& path, 614d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::unordered_map<ResourceName, ResourceId>* out_id_map) { 615cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string content; 616cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!android::base::ReadFileToString(path, &content)) { 617ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(path) << "failed reading stable ID file"); 618cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 619cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 620bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 621ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski out_id_map->clear(); 622ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t line_no = 0; 623ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (StringPiece line : util::Tokenize(content, '\n')) { 624ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski line_no++; 625ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski line = util::TrimWhitespace(line); 626cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (line.empty()) { 627cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski continue; 628cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 629bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 630cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski auto iter = std::find(line.begin(), line.end(), '='); 631cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (iter == line.end()) { 632ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(Source(path, line_no)) << "missing '='"); 633cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 634cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 635bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 636cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceNameRef name; 637ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski StringPiece res_name_str = 638ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski util::TrimWhitespace(line.substr(0, std::distance(line.begin(), iter))); 639ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!ResourceUtils::ParseResourceName(res_name_str, &name)) { 640d0f492db038c6210c1138865d816bfb134376538Adam Lesinski diag->Error(DiagMessage(Source(path, line_no)) << "invalid resource name '" << res_name_str 641d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "'"); 642cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 643cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 644bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 645ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const size_t res_id_start_idx = std::distance(line.begin(), iter) + 1; 646ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const size_t res_id_str_len = line.size() - res_id_start_idx; 647d0f492db038c6210c1138865d816bfb134376538Adam Lesinski StringPiece res_id_str = util::TrimWhitespace(line.substr(res_id_start_idx, res_id_str_len)); 648bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 649ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<ResourceId> maybe_id = ResourceUtils::ParseResourceId(res_id_str); 650ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!maybe_id) { 651d0f492db038c6210c1138865d816bfb134376538Adam Lesinski diag->Error(DiagMessage(Source(path, line_no)) << "invalid resource ID '" << res_id_str 652d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "'"); 653cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 654bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski } 655cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 656ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski (*out_id_map)[name.ToResourceName()] = maybe_id.value(); 657cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 658cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 659bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski} 660bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 661355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskiclass LinkCommand { 662cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public: 663cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski LinkCommand(LinkContext* context, const LinkOptions& options) 664ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski : options_(options), 665ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_(context), 666ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski final_table_(), 667d0f492db038c6210c1138865d816bfb134376538Adam Lesinski file_collection_(util::make_unique<io::FileCollection>()) { 668d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 669cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 670cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 671cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Creates a SymbolTable that loads symbols from the various APKs and caches 672ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski * the results for faster lookup. 673cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 674ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool LoadSymbolsFromIncludePaths() { 675ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<AssetManagerSymbolSource> asset_source = 676cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski util::make_unique<AssetManagerSymbolSource>(); 677ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& path : options_.include_paths) { 678ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 679d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage(path) << "loading include path"); 680cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 681cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 682cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // First try to load the file as a static lib. 683ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string error_str; 684ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski std::unique_ptr<ResourceTable> include_static = LoadStaticLibrary(path, &error_str); 685ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (include_static) { 686b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski if (context_->GetPackageType() != PackageType::kStaticLib) { 687ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski // Can't include static libraries when not building a static library (they have no IDs 688ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski // assigned). 689ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error( 690ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski DiagMessage(path) << "can't include static library when not building a static lib"); 691cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 692cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 69364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 694cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // If we are using --no-static-lib-packages, we need to rename the 695f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski // package of this table to our compilation package. 696ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.no_static_lib_packages) { 697f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski // Since package names can differ, and multiple packages can exist in a ResourceTable, 698f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski // we place the requirement that all static libraries are built with the package 699f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski // ID 0x7f. So if one is not found, this is an error. 700f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (ResourceTablePackage* pkg = include_static->FindPackageById(kAppPackageId)) { 701ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski pkg->name = context_->GetCompilationPackage(); 702f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } else { 703f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(path) 704f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski << "no package with ID 0x7f found in static library"); 705f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski return false; 706cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 707355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 70864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 709ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetExternalSymbols()->AppendSource( 710ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski util::make_unique<ResourceTableSymbolSource>(include_static.get())); 7111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 712ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski static_table_includes_.push_back(std::move(include_static)); 713fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski 714ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else if (!error_str.empty()) { 715cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // We had an error with reading, so fail. 716ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(path) << error_str); 717cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 718cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 719fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski 720ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!asset_source->AddAssetPath(path)) { 721ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage(path) << "failed to load include path"); 722cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 723cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 724cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 725fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski 726ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski // Capture the shared libraries so that the final resource table can be properly flattened 727ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski // with support for shared libraries. 728ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski for (auto& entry : asset_source->GetAssignedPackageIds()) { 729f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (entry.first > kFrameworkPackageId && entry.first < kAppPackageId) { 730ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski final_table_.included_packages_[entry.first] = entry.second; 731ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski } 732ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski } 733ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 734ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetExternalSymbols()->AppendSource(std::move(asset_source)); 735cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 736cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 73736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 738b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski Maybe<AppInfo> ExtractAppInfoFromManifest(xml::XmlResource* xml_res, IDiagnostics* diag) { 739cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Make sure the first element is <manifest> with package attribute. 740b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski xml::Element* manifest_el = xml::FindRootElement(xml_res->root.get()); 741b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (manifest_el == nullptr) { 742b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski return {}; 743b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski } 74436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 745b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski AppInfo app_info; 746b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski 747b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (!manifest_el->namespace_uri.empty() || manifest_el->name != "manifest") { 748b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski diag->Error(DiagMessage(xml_res->file.source) << "root tag must be <manifest>"); 749b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski return {}; 750b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski } 751fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski 752b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski xml::Attribute* package_attr = manifest_el->FindAttribute({}, "package"); 753b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (!package_attr) { 754b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski diag->Error(DiagMessage(xml_res->file.source) 755b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski << "<manifest> must have a 'package' attribute"); 756b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski return {}; 757b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski } 758b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski app_info.package = package_attr->value; 759b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski 760b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (xml::Attribute* version_code_attr = 761b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode")) { 762b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski Maybe<uint32_t> maybe_code = ResourceUtils::ParseInt(version_code_attr->value); 763b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (!maybe_code) { 764b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number)) 765b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski << "invalid android:versionCode '" << version_code_attr->value << "'"); 7661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return {}; 767cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 768b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski app_info.version_code = maybe_code.value(); 769b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski } 770cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 771b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (xml::Attribute* revision_code_attr = 772b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode")) { 773b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski Maybe<uint32_t> maybe_code = ResourceUtils::ParseInt(revision_code_attr->value); 774b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (!maybe_code) { 775b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number)) 776b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski << "invalid android:revisionCode '" << revision_code_attr->value << "'"); 777b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski return {}; 778cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 779b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski app_info.revision_code = maybe_code.value(); 780b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski } 781cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 782b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (xml::Attribute* split_name_attr = manifest_el->FindAttribute({}, "split")) { 783b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (!split_name_attr->value.empty()) { 784b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski app_info.split_name = split_name_attr->value; 785cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 786b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski } 787cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 788b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (xml::Element* uses_sdk_el = manifest_el->FindChild({}, "uses-sdk")) { 789b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski if (xml::Attribute* min_sdk = 790b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski uses_sdk_el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion")) { 791d0f492db038c6210c1138865d816bfb134376538Adam Lesinski app_info.min_sdk_version = ResourceUtils::ParseSdkVersion(min_sdk->value); 792cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 793cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 794b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski return app_info; 795cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 796cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 797cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 798b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski * Precondition: ResourceTable doesn't have any IDs assigned yet, nor is it linked. 799cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Postcondition: ResourceTable has only one package left. All others are 800ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski * stripped, or there is an error and false is returned. 801cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 802ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool VerifyNoExternalPackages() { 803d0f492db038c6210c1138865d816bfb134376538Adam Lesinski auto is_ext_package_func = [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool { 804ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return context_->GetCompilationPackage() != pkg->name || !pkg->id || 805ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski pkg->id.value() != context_->GetPackageId(); 806cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski }; 8071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 808cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool error = false; 809ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const auto& package : final_table_.packages) { 810ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (is_ext_package_func(package)) { 811cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // We have a package that is not related to the one we're building! 812cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (const auto& type : package->types) { 813cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (const auto& entry : type->entries) { 814ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceNameRef res_name(package->name, type->type, entry->name); 815cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 816ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const auto& config_value : entry->values) { 817cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Special case the occurrence of an ID that is being generated 818ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // for the 'android' package. This is due to legacy reasons. 819d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (ValueCast<Id>(config_value->value.get()) && package->name == "android") { 820d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Warn(DiagMessage(config_value->value->GetSource()) 821d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "generated id '" << res_name 822d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "' for external package '" << package->name 823d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "'"); 824cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 825d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(config_value->value->GetSource()) 826d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "defined resource '" << res_name 827d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "' for external package '" << package->name 828d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "'"); 829cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 830cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 8311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 832cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 8331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 834cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 835cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 836979ccb2e6f3f1f7f00a448eb440a85daf033dc9eAdam Lesinski 837d0f492db038c6210c1138865d816bfb134376538Adam Lesinski auto new_end_iter = std::remove_if(final_table_.packages.begin(), final_table_.packages.end(), 838d0f492db038c6210c1138865d816bfb134376538Adam Lesinski is_ext_package_func); 839ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski final_table_.packages.erase(new_end_iter, final_table_.packages.end()); 840cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return !error; 841cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 842cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 843cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 844cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Returns true if no IDs have been set, false otherwise. 845cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 846ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool VerifyNoIdsSet() { 847ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const auto& package : final_table_.packages) { 848cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (const auto& type : package->types) { 849cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (type->id) { 850f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "type " << type->type << " has ID " 851f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski << StringPrintf("%02x", type->id.value()) 852f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski << " assigned"); 853cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 854cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 855cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 856cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (const auto& entry : type->entries) { 857cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (entry->id) { 858ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceNameRef res_name(package->name, type->type, entry->name); 859ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error( 860f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski DiagMessage() << "entry " << res_name << " has ID " 861f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski << StringPrintf("%02x", entry->id.value()) << " assigned"); 862cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 863cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 86464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 865cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 86664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 867cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 868cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 86964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 870ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<IArchiveWriter> MakeArchiveWriter(const StringPiece& out) { 871ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.output_to_directory) { 872ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return CreateDirectoryArchiveWriter(context_->GetDiagnostics(), out); 873cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 874ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return CreateZipFileArchiveWriter(context_->GetDiagnostics(), out); 8751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 876cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 8771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 878ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool FlattenTable(ResourceTable* table, IArchiveWriter* writer) { 879cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski BigBuffer buffer(1024); 880c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski TableFlattener flattener(options_.table_flattener_options, &buffer); 881ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!flattener.Consume(context_, table)) { 88206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed to flatten resource table"); 883cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 884cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 8851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 88606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski io::BigBufferInputStream input_stream(&buffer); 887d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return io::CopyInputStreamToArchive(context_, &input_stream, "resources.arsc", 888d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ArchiveEntry::kAlign, writer); 889cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 890cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 891ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool FlattenTableToPb(ResourceTable* table, IArchiveWriter* writer) { 89206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski std::unique_ptr<pb::ResourceTable> pb_table = SerializeTableToPb(table); 893d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return io::CopyProtoToArchive(context_, pb_table.get(), "resources.arsc.flat", 0, writer); 894cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 8951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 896d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool WriteJavaFile(ResourceTable* table, const StringPiece& package_name_to_generate, 897418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski const StringPiece& out_package, const JavaClassGeneratorOptions& java_options, 898418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski const Maybe<std::string> out_text_symbols_path = {}) { 899ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!options_.generate_java_class_path) { 900cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 9011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 9021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 903ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string out_path = options_.generate_java_class_path.value(); 904ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file::AppendPath(&out_path, file::PackageToPath(out_package)); 905ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!file::mkdirs(out_path)) { 906d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed to create directory '" << out_path 907d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "'"); 908cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 909cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 910ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 911ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file::AppendPath(&out_path, "R.java"); 912ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 913ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::ofstream fout(out_path, std::ofstream::binary); 914cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fout) { 915d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() 916d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed writing to '" << out_path 917d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "': " << android::base::SystemErrorCodeToString(errno)); 918cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 919ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 920ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 921418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski std::unique_ptr<std::ofstream> fout_text; 922418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski if (out_text_symbols_path) { 923418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski fout_text = 924418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski util::make_unique<std::ofstream>(out_text_symbols_path.value(), std::ofstream::binary); 925418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski if (!*fout_text) { 926418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski context_->GetDiagnostics()->Error( 927418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski DiagMessage() << "failed writing to '" << out_text_symbols_path.value() 928418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski << "': " << android::base::SystemErrorCodeToString(errno)); 929418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski return false; 930418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski } 931418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski } 932418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski 933ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski JavaClassGenerator generator(context_, table, java_options); 934418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski if (!generator.Generate(package_name_to_generate, out_package, &fout, fout_text.get())) { 93506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(out_path) << generator.getError()); 936cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 937cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 9381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 939cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fout) { 940d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() 941d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed writing to '" << out_path 942d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "': " << android::base::SystemErrorCodeToString(errno)); 9431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 944cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 945cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 9461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 947ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool WriteManifestJavaFile(xml::XmlResource* manifest_xml) { 948ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!options_.generate_java_class_path) { 949cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 95064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 95164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 952ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<ClassDefinition> manifest_class = 953ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski GenerateManifestClass(context_->GetDiagnostics(), manifest_xml); 95464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 955ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!manifest_class) { 956cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Something bad happened, but we already logged it, so exit. 957cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 95864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 95964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 960ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (manifest_class->empty()) { 961cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Empty Manifest class, no need to generate it. 962cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 963cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 96464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 965cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Add any JavaDoc annotations to the generated class. 966ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& annotation : options_.javadoc_annotations) { 967ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string proper_annotation = "@"; 968ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski proper_annotation += annotation; 969ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski manifest_class->GetCommentBuilder()->AppendComment(proper_annotation); 970cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 97164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 972ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const std::string& package_utf8 = context_->GetCompilationPackage(); 97364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 974ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string out_path = options_.generate_java_class_path.value(); 975ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file::AppendPath(&out_path, file::PackageToPath(package_utf8)); 97664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 977ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!file::mkdirs(out_path)) { 978d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed to create directory '" << out_path 979d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "'"); 980cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 981cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 98264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 983ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file::AppendPath(&out_path, "Manifest.java"); 98464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 985ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::ofstream fout(out_path, std::ofstream::binary); 986cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fout) { 987d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() 988d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed writing to '" << out_path 989d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "': " << android::base::SystemErrorCodeToString(errno)); 990cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 991cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 99264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 993d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8, true, &fout)) { 994d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() 995d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed writing to '" << out_path 996d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "': " << android::base::SystemErrorCodeToString(errno)); 997cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 998cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 999cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 1000cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 100164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 1002d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool WriteProguardFile(const Maybe<std::string>& out, const proguard::KeepSet& keep_set) { 1003cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!out) { 1004cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 1005fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski } 1006fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1007ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const std::string& out_path = out.value(); 1008ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::ofstream fout(out_path, std::ofstream::binary); 1009cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fout) { 1010d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() 1011d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed to open '" << out_path 1012d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "': " << android::base::SystemErrorCodeToString(errno)); 1013cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1014cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1015a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski 1016ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski proguard::WriteKeepSet(&fout, keep_set); 1017cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!fout) { 1018d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() 1019d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed writing to '" << out_path 1020d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "': " << android::base::SystemErrorCodeToString(errno)); 1021cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1022cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1023cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 1024cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1025fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1026ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<ResourceTable> LoadStaticLibrary(const std::string& input, 1027ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string* out_error) { 1028cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<io::ZipFileCollection> collection = 1029ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::ZipFileCollection::Create(input, out_error); 1030cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!collection) { 1031cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return {}; 1032cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1033ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return LoadTablePbFromCollection(collection.get()); 1034cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1035fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1036d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::unique_ptr<ResourceTable> LoadTablePbFromCollection(io::IFileCollection* collection) { 1037ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::IFile* file = collection->FindFile("resources.arsc.flat"); 1038cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!file) { 1039cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return {}; 1040fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski } 1041fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1042ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<io::IData> data = file->OpenAsData(); 1043ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return LoadTableFromPb(file->GetSource(), data->data(), data->size(), 1044ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()); 1045cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1046fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1047ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool MergeStaticLibrary(const std::string& input, bool override) { 1048ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 1049d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage() << "merging static library " << input); 1050cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1051fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1052ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string error_str; 1053cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<io::ZipFileCollection> collection = 1054ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::ZipFileCollection::Create(input, &error_str); 1055cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!collection) { 1056ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(input) << error_str); 1057cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1058cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1059fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1060b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski std::unique_ptr<ResourceTable> table = LoadTablePbFromCollection(collection.get()); 1061cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!table) { 1062b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(input) << "invalid static library"); 1063cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1064cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1065cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1066f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski ResourceTablePackage* pkg = table->FindPackageById(kAppPackageId); 1067cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!pkg) { 1068b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(input) << "static library has no package"); 1069cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1070cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1071cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1072cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool result; 1073ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.no_static_lib_packages) { 1074cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Merge all resources as if they were in the compilation package. This is 1075ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // the old behavior of aapt. 1076cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1077cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Add the package to the set of --extra-packages so we emit an R.java for 1078ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // each library package. 1079cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!pkg->name.empty()) { 1080ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options_.extra_java_packages.insert(pkg->name); 1081cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1082cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1083cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski pkg->name = ""; 1084cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (override) { 1085b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski result = table_merger_->MergeOverlay(Source(input), table.get(), collection.get()); 1086cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1087b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski result = table_merger_->Merge(Source(input), table.get(), collection.get()); 1088cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1089cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1090cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1091cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // This is the proper way to merge libraries, where the package name is 1092ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // preserved and resource names are mangled. 1093d0f492db038c6210c1138865d816bfb134376538Adam Lesinski result = 1094d0f492db038c6210c1138865d816bfb134376538Adam Lesinski table_merger_->MergeAndMangle(Source(input), pkg->name, table.get(), collection.get()); 1095cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1096cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1097cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!result) { 1098cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1099cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1100cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1101cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Make sure to move the collection into the set of IFileCollections. 1102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski collections_.push_back(std::move(collection)); 1103cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 1104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1105fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool MergeResourceTable(io::IFile* file, bool override) { 1107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 1108d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage() << "merging resource table " 1109d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << file->GetSource()); 1110cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1111fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<io::IData> data = file->OpenAsData(); 1113cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!data) { 1114d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << "failed to open file"); 1115cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1116cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1117fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1118cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<ResourceTable> table = 1119d0f492db038c6210c1138865d816bfb134376538Adam Lesinski LoadTableFromPb(file->GetSource(), data->data(), data->size(), context_->GetDiagnostics()); 1120cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!table) { 1121cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1122fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski } 1123fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1124cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool result = false; 1125cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (override) { 1126ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result = table_merger_->MergeOverlay(file->GetSource(), table.get()); 1127cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1128ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result = table_merger_->Merge(file->GetSource(), table.get()); 1129cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1130cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return result; 1131cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 113264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 1133d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool MergeCompiledFile(io::IFile* file, ResourceFile* file_desc, bool override) { 1134ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 1135d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage() << "merging '" << file_desc->name 1136d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "' from compiled file " 1137d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << file->GetSource()); 1138cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1139a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski 1140cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool result = false; 1141cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (override) { 1142ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result = table_merger_->MergeFileOverlay(*file_desc, file); 1143cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result = table_merger_->MergeFile(*file_desc, file); 1145cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1146a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski 1147cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!result) { 1148cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1149cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1150a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski 1151cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Add the exports of this file to the table. 1152ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (SourcedResourceName& exported_symbol : file_desc->exported_symbols) { 1153ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (exported_symbol.name.package.empty()) { 1154ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski exported_symbol.name.package = context_->GetCompilationPackage(); 1155cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1156a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski 1157ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceNameRef res_name = exported_symbol.name; 11585eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 1159ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<ResourceName> mangled_name = 1160ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetNameMangler()->MangleName(exported_symbol.name); 1161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (mangled_name) { 1162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski res_name = mangled_name.value(); 1163cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 116452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 1165cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<Id> id = util::make_unique<Id>(); 1166ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski id->SetSource(file_desc->source.WithLine(exported_symbol.line)); 1167ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool result = final_table_.AddResourceAllowMangled( 1168d0f492db038c6210c1138865d816bfb134376538Adam Lesinski res_name, ConfigDescription::DefaultConfig(), std::string(), std::move(id), 1169d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()); 1170cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!result) { 1171cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1172cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1173cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1174cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 1175cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1176cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1177cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 1178cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Takes a path to load as a ZIP file and merges the files within into the 1179cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * master ResourceTable. 1180cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * If override is true, conflicting resources are allowed to override each 1181ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski * other, in order of last seen. 1182cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * 1183cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * An io::IFileCollection is created from the ZIP file and added to the set of 1184cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * io::IFileCollections that are open. 1185cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 1186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool MergeArchive(const std::string& input, bool override) { 1187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 1188d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage() << "merging archive " << input); 1189fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski } 1190fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1191ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string error_str; 1192cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<io::ZipFileCollection> collection = 1193ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::ZipFileCollection::Create(input, &error_str); 1194cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!collection) { 1195ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(input) << error_str); 1196cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1197cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 119836c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1199cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool error = false; 1200ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto iter = collection->Iterator(); iter->HasNext();) { 1201ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!MergeFile(iter->Next(), override)) { 1202cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 1203cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1204cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 120536c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1206cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Make sure to move the collection into the set of IFileCollections. 1207ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski collections_.push_back(std::move(collection)); 1208cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return !error; 1209cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1210cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1211cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 1212cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Takes a path to load and merge into the master ResourceTable. If override 1213cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * is true, 1214cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * conflicting resources are allowed to override each other, in order of last 1215cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * seen. 1216cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * 1217cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * If the file path ends with .flata, .jar, .jack, or .zip the file is treated 1218cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * as ZIP archive 1219cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * and the files within are merged individually. 1220cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * 1221cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Otherwise the files is processed on its own. 1222cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 1223ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool MergePath(const std::string& path, bool override) { 1224ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (util::EndsWith(path, ".flata") || util::EndsWith(path, ".jar") || 1225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski util::EndsWith(path, ".jack") || util::EndsWith(path, ".zip")) { 1226ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return MergeArchive(path, override); 1227ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else if (util::EndsWith(path, ".apk")) { 1228ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return MergeStaticLibrary(path, override); 1229ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 1230ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 1231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::IFile* file = file_collection_->InsertFile(path); 1232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return MergeFile(file, override); 1233cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1234cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1235cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 1236cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Takes a file to load and merge into the master ResourceTable. If override 1237cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * is true, 1238cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * conflicting resources are allowed to override each other, in order of last 1239cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * seen. 1240cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * 1241cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * If the file ends with .arsc.flat, then it is loaded as a ResourceTable and 1242cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * merged into the 1243cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * master ResourceTable. If the file ends with .flat, then it is treated like 1244cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * a compiled file 1245cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * and the header data is read and merged into the final ResourceTable. 1246cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * 1247cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * All other file types are ignored. This is because these files could be 1248cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * coming from a zip, 1249cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * where we could have other files like classes.dex. 1250cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 1251ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool MergeFile(io::IFile* file, bool override) { 1252ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const Source& src = file->GetSource(); 1253ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (util::EndsWith(src.path, ".arsc.flat")) { 1254ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return MergeResourceTable(file, override); 1255cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1256ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else if (util::EndsWith(src.path, ".flat")) { 1257cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Try opening the file and looking for an Export header. 1258ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<io::IData> data = file->OpenAsData(); 1259cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!data) { 1260ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to open"); 1261cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1262cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 126336c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1264ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CompiledFileInputStream input_stream(data->data(), data->size()); 1265ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski uint32_t num_files = 0; 1266ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!input_stream.ReadLittleEndian32(&num_files)) { 1267d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(src) << "failed read num files"); 1268cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1269cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 127036c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1271ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (uint32_t i = 0; i < num_files; i++) { 1272ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski pb::CompiledFile compiled_file; 1273ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!input_stream.ReadCompiledFile(&compiled_file)) { 1274d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(src) 1275d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed to read compiled file header"); 1276cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 127736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski } 127836c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1279cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski uint64_t offset, len; 1280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!input_stream.ReadDataMetaData(&offset, &len)) { 1281d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to read data meta data"); 1282cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 128336c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski } 128436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1285d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::unique_ptr<ResourceFile> resource_file = DeserializeCompiledFileFromPb( 1286d0f492db038c6210c1138865d816bfb134376538Adam Lesinski compiled_file, file->GetSource(), context_->GetDiagnostics()); 1287ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!resource_file) { 1288cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 128936c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski } 129036c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1291d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!MergeCompiledFile(file->CreateFileSegment(offset, len), resource_file.get(), 1292d0f492db038c6210c1138865d816bfb134376538Adam Lesinski override)) { 1293cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 129436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski } 1295cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1296cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 1297d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } else if (util::EndsWith(src.path, ".xml") || util::EndsWith(src.path, ".png")) { 12986a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski // Since AAPT compiles these file types and appends .flat to them, seeing 12996a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski // their raw extensions is a sign that they weren't compiled. 1300d0f492db038c6210c1138865d816bfb134376538Adam Lesinski const StringPiece file_type = util::EndsWith(src.path, ".xml") ? "XML" : "PNG"; 1301d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(src) << "uncompiled " << file_type 1302d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << " file passed as argument. Must be " 1303d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "compiled first into .flat file."); 13046a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski return false; 130536c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski } 130636c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1307cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Ignore non .flat files. This could be classes.dex or something else that 1308cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // happens 1309cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // to be in an archive. 1310cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 1311cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1312cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1313b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski bool CopyAssetsDirsToApk(IArchiveWriter* writer) { 1314b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski std::map<std::string, std::unique_ptr<io::RegularFile>> merged_assets; 1315b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski for (const std::string& assets_dir : options_.assets_dirs) { 1316b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski Maybe<std::vector<std::string>> files = 1317b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski file::FindFiles(assets_dir, context_->GetDiagnostics(), nullptr); 1318b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski if (!files) { 1319b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski return false; 1320b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1321b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski 1322b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski for (const std::string& file : files.value()) { 1323b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski std::string full_key = "assets/" + file; 1324b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski std::string full_path = assets_dir; 1325b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski file::AppendPath(&full_path, file); 1326b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski 1327b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski auto iter = merged_assets.find(full_key); 1328b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski if (iter == merged_assets.end()) { 1329b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski merged_assets.emplace(std::move(full_key), 1330b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski util::make_unique<io::RegularFile>(Source(std::move(full_path)))); 1331b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } else if (context_->IsVerbose()) { 1332b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski context_->GetDiagnostics()->Warn(DiagMessage(iter->second->GetSource()) 1333b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski << "asset file overrides '" << full_path << "'"); 1334b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1335b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1336b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1337b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski 1338b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski for (auto& entry : merged_assets) { 1339b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski uint32_t compression_flags = ArchiveEntry::kCompress; 1340b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski std::string extension = file::GetExtension(entry.first).to_string(); 1341b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski if (options_.extensions_to_not_compress.count(extension) > 0) { 1342b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski compression_flags = 0u; 1343b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1344b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski 1345d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!io::CopyFileToArchive(context_, entry.second.get(), entry.first, compression_flags, 1346d0f492db038c6210c1138865d816bfb134376538Adam Lesinski writer)) { 1347b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski return false; 1348b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1349b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1350b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski return true; 1351b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1352b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski 1353cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 1354cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Writes the AndroidManifest, ResourceTable, and all XML files referenced by 1355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski * the ResourceTable to the IArchiveWriter. 1356cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 1357d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set, xml::XmlResource* manifest, 1358d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ResourceTable* table) { 1359b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski const bool keep_raw_values = context_->GetPackageType() == PackageType::kStaticLib; 1360d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool result = 1361d0f492db038c6210c1138865d816bfb134376538Adam Lesinski FlattenXml(manifest, "AndroidManifest.xml", {}, keep_raw_values, writer, context_); 1362cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!result) { 1363cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1364cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1365cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1366ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceFileFlattenerOptions file_flattener_options; 1367ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_flattener_options.keep_raw_values = keep_raw_values; 1368d0f492db038c6210c1138865d816bfb134376538Adam Lesinski file_flattener_options.do_not_compress_anything = options_.do_not_compress_anything; 1369d0f492db038c6210c1138865d816bfb134376538Adam Lesinski file_flattener_options.extensions_to_not_compress = options_.extensions_to_not_compress; 1370ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_flattener_options.no_auto_version = options_.no_auto_version; 1371ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_flattener_options.no_version_vectors = options_.no_version_vectors; 13724d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki file_flattener_options.no_version_transitions = options_.no_version_transitions; 1373ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_flattener_options.no_xml_namespaces = options_.no_xml_namespaces; 1374ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file_flattener_options.update_proguard_spec = 1375ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski static_cast<bool>(options_.generate_proguard_rules_path); 1376cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1377ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski ResourceFileFlattener file_flattener(file_flattener_options, context_, keep_set); 1378cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1379ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!file_flattener.Flatten(table, writer)) { 1380ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed linking file resources"); 1381cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1382cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1383cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1384b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski if (context_->GetPackageType() == PackageType::kStaticLib) { 1385ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!FlattenTableToPb(table, writer)) { 1386cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1387cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1388cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1389ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!FlattenTable(table, writer)) { 1390ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed to write resources.arsc"); 1391cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 1392cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1393cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1394cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 1395cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 13969ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 1397ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski int Run(const std::vector<std::string>& input_files) { 1398cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Load the AndroidManifest.xml 1399ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<xml::XmlResource> manifest_xml = 1400ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski LoadXml(options_.manifest_path, context_->GetDiagnostics()); 1401ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!manifest_xml) { 1402cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1403cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 14041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1405d0f492db038c6210c1138865d816bfb134376538Adam Lesinski // First extract the Package name without modifying it (via --rename-manifest-package). 1406d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (Maybe<AppInfo> maybe_app_info = 1407d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics())) { 1408ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const AppInfo& app_info = maybe_app_info.value(); 1409ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->SetCompilationPackage(app_info.package); 1410cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1411fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1412ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ManifestFixer manifest_fixer(options_.manifest_fixer_options); 1413ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!manifest_fixer.Consume(context_, manifest_xml.get())) { 1414cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1415cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 14161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1417d0f492db038c6210c1138865d816bfb134376538Adam Lesinski Maybe<AppInfo> maybe_app_info = 1418d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics()); 1419ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!maybe_app_info) { 1420cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1421cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 14221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1423ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const AppInfo& app_info = maybe_app_info.value(); 1424d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->SetMinSdkVersion(app_info.min_sdk_version.value_or_default(0)); 14251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1426d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->SetNameManglerPolicy(NameManglerPolicy{context_->GetCompilationPackage()}); 1427f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski 1428f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski // Override the package ID when it is "android". 1429f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (context_->GetCompilationPackage() == "android") { 1430ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->SetPackageId(0x01); 1431f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski 1432f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski // Verify we're building a regular app. 1433b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski if (context_->GetPackageType() != PackageType::kApp) { 1434f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context_->GetDiagnostics()->Error( 1435f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski DiagMessage() << "package 'android' can only be built as a regular app"); 1436f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski return 1; 1437f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } 1438cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 14391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1440ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!LoadSymbolsFromIncludePaths()) { 1441cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1442cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 14431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1444ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski TableMergerOptions table_merger_options; 1445ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_merger_options.auto_add_overlay = options_.auto_add_overlay; 1446d0f492db038c6210c1138865d816bfb134376538Adam Lesinski table_merger_ = util::make_unique<TableMerger>(context_, &final_table_, table_merger_options); 14471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1448ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 1449ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage() 1450f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski << StringPrintf("linking package '%s' using package ID %02x", 1451f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context_->GetCompilationPackage().data(), 1452f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context_->GetPackageId())); 1453cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1454bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 1455ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& input : input_files) { 1456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!MergePath(input, false)) { 1457d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed parsing input"); 1458cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1459cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1460cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 14611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1462ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& input : options_.overlay_files) { 1463ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!MergePath(input, true)) { 1464d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed parsing overlays"); 1465cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1466cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1467cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 146864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 1469ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!VerifyNoExternalPackages()) { 1470cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1471cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 14721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1473b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski if (context_->GetPackageType() != PackageType::kStaticLib) { 1474cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski PrivateAttributeMover mover; 1475ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!mover.Consume(context_, &final_table_)) { 1476d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed moving private attributes"); 1477cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1478cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 147936c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1480cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Assign IDs if we are building a regular app. 1481ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski IdAssigner id_assigner(&options_.stable_id_map); 1482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!id_assigner.Consume(context_, &final_table_)) { 1483ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed assigning IDs"); 1484cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1485cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 148636c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1487cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Now grab each ID and emit it as a file. 1488ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.resource_id_map_path) { 1489ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& package : final_table_.packages) { 1490cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (auto& type : package->types) { 1491cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (auto& entry : type->entries) { 1492cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceName name(package->name, type->type, entry->name); 1493cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The IDs are guaranteed to exist. 1494d0f492db038c6210c1138865d816bfb134376538Adam Lesinski options_.stable_id_map[std::move(name)] = 1495d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ResourceId(package->id.value(), type->id.value(), entry->id.value()); 14961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1497cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 149836c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski } 149936c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1500d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!WriteStableIdMapToPath(context_->GetDiagnostics(), options_.stable_id_map, 1501ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options_.resource_id_map_path.value())) { 1502cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 150336c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski } 1504cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1505cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1506cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Static libs are merged with other apps, and ID collisions are bad, so 1507cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // verify that 1508cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // no IDs have been set. 1509ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!VerifyNoIdsSet()) { 1510cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1511cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1512cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1513cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1514cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Add the names to mangle based on our source merge earlier. 1515d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->SetNameManglerPolicy( 1516d0f492db038c6210c1138865d816bfb134376538Adam Lesinski NameManglerPolicy{context_->GetCompilationPackage(), table_merger_->merged_packages()}); 1517cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1518cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Add our table to the symbol table. 1519ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetExternalSymbols()->PrependSource( 1520ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski util::make_unique<ResourceTableSymbolSource>(&final_table_)); 1521cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 15221e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski // Workaround for pre-O runtime that would treat negative resource IDs 15231e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski // (any ID with a package ID > 7f) as invalid. Intercept any ID (PPTTEEEE) with PP > 0x7f 15241e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski // and type == 'id', and return the ID 0x7fPPEEEE. IDs don't need to be real resources, they 15251e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski // are just identifiers. 15261e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski if (context_->GetMinSdkVersion() < SDK_O && context_->GetPackageType() == PackageType::kApp) { 15271e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski if (context_->IsVerbose()) { 15281e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski context_->GetDiagnostics()->Note(DiagMessage() 15291e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski << "enabling pre-O feature split ID rewriting"); 15301e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski } 15311e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski context_->GetExternalSymbols()->SetDelegate( 15321e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski util::make_unique<FeatureSplitSymbolTableDelegate>(context_)); 15331e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski } 15341e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski 1535cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ReferenceLinker linker; 1536ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!linker.Consume(context_, &final_table_)) { 1537d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed linking references"); 1538cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1539cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1540cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1541b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski if (context_->GetPackageType() == PackageType::kStaticLib) { 1542ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!options_.products.empty()) { 1543ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Warn(DiagMessage() 1544ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski << "can't select products when building static library"); 1545cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1546cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1547ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ProductFilter product_filter(options_.products); 1548ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!product_filter.Consume(context_, &final_table_)) { 1549ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed stripping products"); 1550cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1551cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1552cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 155336c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1554ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!options_.no_auto_version) { 1555cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AutoVersioner versioner; 1556ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!versioner.Consume(context_, &final_table_)) { 1557d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed versioning styles"); 1558cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1559cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1560cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 156177788eb4cf0c5dba0f7370192e40364fe853050aAlexandria Cornwall 1562b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski if (context_->GetPackageType() != PackageType::kStaticLib && context_->GetMinSdkVersion() > 0) { 1563ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 1564d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage() 1565d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "collapsing resource versions for minimum SDK " 1566d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << context_->GetMinSdkVersion()); 1567cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 156836c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1569cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski VersionCollapser collapser; 1570ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!collapser.Consume(context_, &final_table_)) { 1571cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1572cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1573cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1574355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 1575ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!options_.no_resource_deduping) { 1576cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceDeduper deduper; 1577ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!deduper.Consume(context_, &final_table_)) { 1578ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed deduping resources"); 1579cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1580cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1581cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1582cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1583ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski proguard::KeepSet proguard_keep_set; 1584ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski proguard::KeepSet proguard_main_dex_keep_set; 1585cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1586b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski if (context_->GetPackageType() == PackageType::kStaticLib) { 1587ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.table_splitter_options.config_filter != nullptr || 1588672384b41e1fc7195424533b7aa6753fb771a6cbPierre Lecesne !options_.table_splitter_options.preferred_densities.empty()) { 1589ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski context_->GetDiagnostics()->Warn(DiagMessage() 1590ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski << "can't strip resources when building static library"); 1591cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1592cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1593d0f492db038c6210c1138865d816bfb134376538Adam Lesinski // Adjust the SplitConstraints so that their SDK version is stripped if it is less than or 1594d0f492db038c6210c1138865d816bfb134376538Adam Lesinski // equal to the minSdk. 1595d0f492db038c6210c1138865d816bfb134376538Adam Lesinski options_.split_constraints = 1596d0f492db038c6210c1138865d816bfb134376538Adam Lesinski AdjustSplitConstraintsForMinSdk(context_->GetMinSdkVersion(), options_.split_constraints); 1597cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1598d0f492db038c6210c1138865d816bfb134376538Adam Lesinski TableSplitter table_splitter(options_.split_constraints, options_.table_splitter_options); 1599ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!table_splitter.VerifySplitConstraints(context_)) { 1600cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1601cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1602ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_splitter.SplitTable(&final_table_); 1603cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1604cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Now we need to write out the Split APKs. 1605ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto path_iter = options_.split_paths.begin(); 1606d0f492db038c6210c1138865d816bfb134376538Adam Lesinski auto split_constraints_iter = options_.split_constraints.begin(); 1607d0f492db038c6210c1138865d816bfb134376538Adam Lesinski for (std::unique_ptr<ResourceTable>& split_table : table_splitter.splits()) { 1608ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (context_->IsVerbose()) { 1609d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Note(DiagMessage(*path_iter) 1610d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "generating split with configurations '" 1611d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << util::Joiner(split_constraints_iter->configs, ", ") 1612d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "'"); 16131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 16141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1615d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::unique_ptr<IArchiveWriter> archive_writer = MakeArchiveWriter(*path_iter); 1616ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!archive_writer) { 1617d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed to create archive"); 1618cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 16191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 16201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1621cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Generate an AndroidManifest.xml for each split. 1622ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<xml::XmlResource> split_manifest = 1623ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski GenerateSplitManifest(app_info, *split_constraints_iter); 16241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1625cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski XmlReferenceLinker linker; 1626ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!linker.Consume(context_, split_manifest.get())) { 1627d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage() 1628d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed to create Split AndroidManifest.xml"); 1629cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1630467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 1631467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 1632d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!WriteApk(archive_writer.get(), &proguard_keep_set, split_manifest.get(), 1633d0f492db038c6210c1138865d816bfb134376538Adam Lesinski split_table.get())) { 1634cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1635637b4820dc1858dacbf562ca65c13b4be0249e0eAlexandria Cornwall } 1636637b4820dc1858dacbf562ca65c13b4be0249e0eAlexandria Cornwall 1637ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ++path_iter; 1638ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ++split_constraints_iter; 1639cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1640cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 16419e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski 1642cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Start writing the base APK. 1643b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski std::unique_ptr<IArchiveWriter> archive_writer = MakeArchiveWriter(options_.output_path); 1644ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!archive_writer) { 1645b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed to create archive"); 1646cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1647cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 16489e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski 1649cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool error = false; 1650cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski { 1651cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // AndroidManifest.xml has no resource name, but the CallSite is built 1652cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // from the name 1653cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // (aka, which package the AndroidManifest.xml is coming from). 1654cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // So we give it a package name so it can see local resources. 1655ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski manifest_xml->file.name.package = context_->GetCompilationPackage(); 1656ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 1657ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XmlReferenceLinker manifest_linker; 1658ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (manifest_linker.Consume(context_, manifest_xml.get())) { 1659ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.generate_proguard_rules_path && 1660b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski !proguard::CollectProguardRulesForManifest(Source(options_.manifest_path), 1661b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski manifest_xml.get(), &proguard_keep_set)) { 1662cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 16631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 16641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1665ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.generate_main_dex_proguard_rules_path && 1666b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski !proguard::CollectProguardRulesForManifest(Source(options_.manifest_path), 1667b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski manifest_xml.get(), 1668b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski &proguard_main_dex_keep_set, true)) { 1669cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 1670e49bb30dab4c37926962e8b408045e5a45f52c40Rohit Agrawal } 1671e49bb30dab4c37926962e8b408045e5a45f52c40Rohit Agrawal 1672ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.generate_java_class_path) { 1673ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!WriteManifestJavaFile(manifest_xml.get())) { 1674cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 1675cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 16761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 16771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1678ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.no_xml_namespaces) { 1679cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // PackageParser will fail if URIs are removed from 1680cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // AndroidManifest.xml. 1681ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XmlNamespaceRemover namespace_remover(true /* keepUris */); 1682ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!namespace_remover.Consume(context_, manifest_xml.get())) { 1683cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 1684cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 16851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1686cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1687cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski error = true; 1688cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 16891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1690fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1691cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (error) { 1692b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "failed processing manifest"); 1693cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1694cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1695a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 1696b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski if (!WriteApk(archive_writer.get(), &proguard_keep_set, manifest_xml.get(), &final_table_)) { 1697b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski return 1; 1698b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski } 1699b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski 1700b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski if (!CopyAssetsDirsToApk(archive_writer.get())) { 1701cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1702cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1703fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 1704ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.generate_java_class_path) { 1705b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski // The set of packages whose R class to call in the main classes 1706b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski // onResourcesLoaded callback. 1707b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski std::vector<std::string> packages_to_callback; 1708b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski 1709b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski JavaClassGeneratorOptions template_options; 1710b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski template_options.types = JavaClassGeneratorOptions::SymbolTypes::kAll; 1711b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski template_options.javadoc_annotations = options_.javadoc_annotations; 1712fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski 1713b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski if (context_->GetPackageType() == PackageType::kStaticLib || 1714b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski options_.generate_non_final_ids) { 1715b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski template_options.use_final = false; 1716ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski } 1717ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 1718b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski if (context_->GetPackageType() == PackageType::kSharedLib) { 1719b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski template_options.use_final = false; 1720b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski template_options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{}; 1721cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 172264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 1723ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece actual_package = context_->GetCompilationPackage(); 1724ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski StringPiece output_package = context_->GetCompilationPackage(); 1725ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.custom_java_package) { 1726cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Override the output java package to the custom one. 1727ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski output_package = options_.custom_java_package.value(); 1728cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 17291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1730b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski // Generate the private symbols if required. 1731ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (options_.private_symbols) { 1732b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski packages_to_callback.push_back(options_.private_symbols.value()); 1733b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski 1734cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // If we defined a private symbols package, we only emit Public symbols 1735cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // to the original package, and private and public symbols to the 1736cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // private package. 1737b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski JavaClassGeneratorOptions options = template_options; 1738b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate; 1739b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski if (!WriteJavaFile(&final_table_, actual_package, options_.private_symbols.value(), 1740b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski options)) { 1741b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski return 1; 1742b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski } 1743b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski } 17441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1745b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski // Generate all the symbols for all extra packages. 1746b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski for (const std::string& extra_package : options_.extra_java_packages) { 1747b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski packages_to_callback.push_back(extra_package); 1748b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski 1749b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski JavaClassGeneratorOptions options = template_options; 1750b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski options.types = JavaClassGeneratorOptions::SymbolTypes::kAll; 1751b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski if (!WriteJavaFile(&final_table_, actual_package, extra_package, options)) { 1752cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1753c51562cf5acda7849a34c4ae2a88077c068859c0Adam Lesinski } 1754b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski } 17551e21ff00b005110128245a4b0d13a7513a2d5e0cAdam Lesinski 1756b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski // Generate the main public R class. 1757b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski JavaClassGeneratorOptions options = template_options; 1758b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski 1759b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski // Only generate public symbols if we have a private package. 1760b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski if (options_.private_symbols) { 1761b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic; 1762cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1763c51562cf5acda7849a34c4ae2a88077c068859c0Adam Lesinski 1764b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski if (options.rewrite_callback_options) { 1765b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski options.rewrite_callback_options.value().packages_to_callback = 1766b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski std::move(packages_to_callback); 1767cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 176864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 1769418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski if (!WriteJavaFile(&final_table_, actual_package, output_package, options, 1770418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski options_.generate_text_symbols_path)) { 1771b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski return 1; 1772cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1773fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski } 1774fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski 1775b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski if (!WriteProguardFile(options_.generate_proguard_rules_path, proguard_keep_set)) { 1776cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1777e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 1778e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 1779ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!WriteProguardFile(options_.generate_main_dex_proguard_rules_path, 1780ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski proguard_main_dex_keep_set)) { 1781cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1782cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1783cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 0; 1784cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1785355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 1786cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private: 1787ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski LinkOptions options_; 1788ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski LinkContext* context_; 1789ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceTable final_table_; 1790355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 1791ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<TableMerger> table_merger_; 1792355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 1793cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // A pointer to the FileCollection representing the filesystem (not archives). 1794ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<io::FileCollection> file_collection_; 17956a008170cb18666e04c42856f992fc7a0afa1e1fAdam Lesinski 1796cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // A vector of IFileCollections. This is mainly here to keep ownership of the 1797cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // collections. 1798ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::unique_ptr<io::IFileCollection>> collections_; 1799bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski 1800cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // A vector of ResourceTables. This is here to retain ownership, so that the 1801ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski // SymbolTable can use these. 1802ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::unique_ptr<ResourceTable>> static_table_includes_; 1803ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 1804ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski // The set of shared libraries being used, mapping their assigned package ID to package name. 1805ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski std::map<size_t, std::string> shared_libs_; 1806cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}; 180736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski 1808ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiint Link(const std::vector<StringPiece>& args) { 1809cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski LinkContext context; 1810cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski LinkOptions options; 1811ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> overlay_arg_list; 1812ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> extra_java_packages; 1813f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski Maybe<std::string> package_id; 1814113ee097386380daa8f01d74916504a9a1338a63Adam Lesinski std::vector<std::string> configs; 1815ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> preferred_density; 1816ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> product_list; 1817ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool legacy_x_flag = false; 1818ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool require_localization = false; 1819cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool verbose = false; 1820ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski bool shared_lib = false; 1821ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski bool static_lib = false; 1822ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<std::string> stable_id_file_path; 1823ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> split_args; 1824cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Flags flags = 1825cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Flags() 1826d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .RequiredFlag("-o", "Output path.", &options.output_path) 1827d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .RequiredFlag("--manifest", "Path to the Android manifest to build.", 1828ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.manifest_path) 1829d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalFlagList("-I", "Adds an Android APK to link against.", &options.include_paths) 1830b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski .OptionalFlagList("-A", 1831b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski "An assets directory to include in the APK. These are unprocessed.", 1832b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski &options.assets_dirs) 1833c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlagList("-R", 1834c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski "Compilation unit to link, using `overlay` semantics.\n" 1835c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski "The last conflicting resource given takes precedence.", 1836c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &overlay_arg_list) 1837f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski .OptionalFlag("--package-id", 1838f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski "Specify the package ID to use for this app. Must be greater or equal to\n" 1839f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski "0x7f and can't be used with --static-lib or --shared-lib.", 1840f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski &package_id) 1841d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalFlag("--java", "Directory in which to generate R.java.", 1842ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.generate_java_class_path) 1843d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalFlag("--proguard", "Output file for generated Proguard rules.", 1844ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.generate_proguard_rules_path) 1845c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlag("--proguard-main-dex", 1846d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Output file for generated Proguard rules for the main dex.", 1847c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &options.generate_main_dex_proguard_rules_path) 1848d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalSwitch("--no-auto-version", 1849d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Disables automatic style and layout SDK versioning.", 1850ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.no_auto_version) 1851ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalSwitch("--no-version-vectors", 1852d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Disables automatic versioning of vector drawables. Use this only\n" 1853d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "when building with vector drawable support library.", 1854ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.no_version_vectors) 18554d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki .OptionalSwitch("--no-version-transitions", 1856d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Disables automatic versioning of transition resources. Use this only\n" 1857d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "when building with transition support library.", 18584d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki &options.no_version_transitions) 1859ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalSwitch("--no-resource-deduping", 1860cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "Disables automatic deduping of resources with\n" 1861cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "identical values across compatible configurations.", 1862ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.no_resource_deduping) 1863c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalSwitch("--enable-sparse-encoding", 1864c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski "Enables encoding sparse entries using a binary search tree.\n" 1865c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski "This decreases APK size at the cost of resource retrieval performance.", 1866c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &options.table_flattener_options.use_sparse_entries) 1867d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01.", 1868c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &legacy_x_flag) 1869d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalSwitch("-z", "Require localization of strings marked 'suggested'.", 1870ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &require_localization) 1871113ee097386380daa8f01d74916504a9a1338a63Adam Lesinski .OptionalFlagList("-c", 1872418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski "Comma separated list of configurations to include. The default\n" 1873418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski "is all configurations.", 1874418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski &configs) 1875c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlag("--preferred-density", 1876c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski "Selects the closest matching density and strips out all others.", 1877c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &preferred_density) 1878c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlag("--product", "Comma separated list of product names to keep", &product_list) 1879ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalSwitch("--output-to-dir", 1880d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Outputs the APK contents to a directory specified by -o.", 1881ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.output_to_directory) 1882ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalSwitch("--no-xml-namespaces", 1883d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Removes XML namespace prefix and URI information from\n" 1884d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "AndroidManifest.xml and XML binaries in res/*.", 1885ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.no_xml_namespaces) 1886ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalFlag("--min-sdk-version", 1887d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Default minimum SDK version to use for AndroidManifest.xml.", 1888ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.manifest_fixer_options.min_sdk_version_default) 1889c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlag("--target-sdk-version", 1890d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Default target SDK version to use for AndroidManifest.xml.", 1891c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &options.manifest_fixer_options.target_sdk_version_default) 1892ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalFlag("--version-code", 1893d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Version code (integer) to inject into the AndroidManifest.xml if none is\n" 1894d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "present.", 1895ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.manifest_fixer_options.version_code_default) 1896ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalFlag("--version-name", 1897d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Version name to inject into the AndroidManifest.xml if none is present.", 1898ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.manifest_fixer_options.version_name_default) 1899d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalSwitch("--shared-lib", "Generates a shared Android runtime library.", 1900d0f492db038c6210c1138865d816bfb134376538Adam Lesinski &shared_lib) 1901d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib) 1902ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalSwitch("--no-static-lib-packages", 1903d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Merge all library resources under the app's package.", 1904ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.no_static_lib_packages) 1905ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalSwitch("--non-final-ids", 1906d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Generates R.java without the final modifier. This is implied when\n" 1907d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "--static-lib is specified.", 1908ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.generate_non_final_ids) 1909c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlag("--stable-ids", "File containing a list of name to ID mapping.", 1910ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &stable_id_file_path) 1911c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlag("--emit-ids", 1912d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Emit a file at the given path with a list of name to ID mappings,\n" 1913d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "suitable for use with --stable-ids.", 1914c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &options.resource_id_map_path) 1915ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalFlag("--private-symbols", 1916d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Package name to use when generating R.java for private symbols.\n" 1917d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "If not specified, public and private symbols will use the application's\n" 1918d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "package name.", 1919ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.private_symbols) 1920d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalFlag("--custom-package", "Custom Java package under which to generate R.java.", 1921ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.custom_java_package) 1922ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalFlagList("--extra-packages", 1923d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Generate the same R.java but with different package names.", 1924ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &extra_java_packages) 1925ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalFlagList("--add-javadoc-annotation", 1926d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Adds a JavaDoc annotation to all generated Java classes.", 1927ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.javadoc_annotations) 1928418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski .OptionalFlag("--output-text-symbols", 1929418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski "Generates a text file containing the resource symbols of the R class in\n" 1930418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski "the specified folder.", 1931418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski &options.generate_text_symbols_path) 1932ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .OptionalSwitch("--auto-add-overlay", 1933d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Allows the addition of new resources in overlays without\n" 1934d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "<add-resource> tags.", 1935ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.auto_add_overlay) 1936d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml.", 1937ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.manifest_fixer_options.rename_manifest_package) 1938c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlag("--rename-instrumentation-target-package", 1939d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Changes the name of the target package for instrumentation. Most useful\n" 1940d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "when used in conjunction with --rename-manifest-package.", 1941c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &options.manifest_fixer_options.rename_instrumentation_target_package) 1942d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalFlagList("-0", "File extensions not to compress.", 1943ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.extensions_to_not_compress) 1944c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .OptionalFlagList("--split", 1945d0f492db038c6210c1138865d816bfb134376538Adam Lesinski "Split resources matching a set of configs out to a Split APK.\n" 1946db091577fff5bcddac703bc8ac4f932fd53e0621Adam Lesinski "Syntax: path/to/output.apk:<config>[,<config>[...]].\n" 1947db091577fff5bcddac703bc8ac4f932fd53e0621Adam Lesinski "On Windows, use a semicolon ';' separator instead.", 1948c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski &split_args) 1949d0f492db038c6210c1138865d816bfb134376538Adam Lesinski .OptionalSwitch("-v", "Enables verbose logging.", &verbose); 1950cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1951ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!flags.Parse("aapt2 link", args, &std::cerr)) { 1952cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1953cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1954cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1955d0f492db038c6210c1138865d816bfb134376538Adam Lesinski // Expand all argument-files passed into the command line. These start with '@'. 1956ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> arg_list; 1957ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& arg : flags.GetArgs()) { 1958ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (util::StartsWith(arg, "@")) { 1959cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const std::string path = arg.substr(1, arg.size() - 1); 1960cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string error; 1961ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!file::AppendArgsFromFile(path, &arg_list, &error)) { 1962ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context.GetDiagnostics()->Error(DiagMessage(path) << error); 1963cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1964cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1965cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1966ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski arg_list.push_back(arg); 1967cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1968cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1969cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1970cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Expand all argument-files passed to -R. 1971ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& arg : overlay_arg_list) { 1972ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (util::StartsWith(arg, "@")) { 1973cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const std::string path = arg.substr(1, arg.size() - 1); 1974cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string error; 1975ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!file::AppendArgsFromFile(path, &options.overlay_files, &error)) { 1976ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context.GetDiagnostics()->Error(DiagMessage(path) << error); 1977cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 1978cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1979cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 1980ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options.overlay_files.push_back(arg); 1981cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1982cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1983cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1984cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (verbose) { 1985ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context.SetVerbose(verbose); 1986cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1987cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1988f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (shared_lib && static_lib) { 1989f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.GetDiagnostics()->Error(DiagMessage() 1990f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski << "only one of --shared-lib and --static-lib can be defined"); 1991f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski return 1; 1992f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } 1993f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski 1994f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (shared_lib) { 1995b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski context.SetPackageType(PackageType::kSharedLib); 1996f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.SetPackageId(0x00); 1997f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } else if (static_lib) { 1998b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski context.SetPackageType(PackageType::kStaticLib); 1999f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.SetPackageId(kAppPackageId); 2000f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } else { 2001b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski context.SetPackageType(PackageType::kApp); 2002f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.SetPackageId(kAppPackageId); 2003f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } 2004f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski 2005f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (package_id) { 2006b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski if (context.GetPackageType() != PackageType::kApp) { 2007f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.GetDiagnostics()->Error( 2008f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski DiagMessage() << "can't specify --package-id when not building a regular app"); 2009f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski return 1; 2010f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } 2011f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski 2012f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski const Maybe<uint32_t> maybe_package_id_int = ResourceUtils::ParseInt(package_id.value()); 2013f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (!maybe_package_id_int) { 2014f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.GetDiagnostics()->Error(DiagMessage() << "package ID '" << package_id.value() 2015f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski << "' is not a valid integer"); 2016f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski return 1; 2017f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } 2018f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski 2019f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski const uint32_t package_id_int = maybe_package_id_int.value(); 2020f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski if (package_id_int < kAppPackageId || package_id_int > std::numeric_limits<uint8_t>::max()) { 2021f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.GetDiagnostics()->Error( 2022f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski DiagMessage() << StringPrintf( 2023f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski "invalid package ID 0x%02x. Must be in the range 0x7f-0xff.", package_id_int)); 2024f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski return 1; 2025f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } 2026f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski context.SetPackageId(static_cast<uint8_t>(package_id_int)); 2027f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski } 2028f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski 2029cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Populate the set of extra packages for which to generate R.java. 2030ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (std::string& extra_package : extra_java_packages) { 2031cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // A given package can actually be a colon separated list of packages. 2032ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (StringPiece package : util::Split(extra_package, ':')) { 2033d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski options.extra_java_packages.insert(package.to_string()); 2034cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2035cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2036cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 2037ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (product_list) { 2038ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (StringPiece product : util::Tokenize(product_list.value(), ',')) { 2039cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (product != "" && product != "default") { 2040d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski options.products.insert(product.to_string()); 2041cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2042cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2043cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2044cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 2045d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::unique_ptr<IConfigFilter> filter; 2046f4dacf29cc995fad4aea8e8f25811f9ee4685d91Mihai Nita if (!configs.empty()) { 2047d0f492db038c6210c1138865d816bfb134376538Adam Lesinski filter = ParseConfigFilterParameters(configs, context.GetDiagnostics()); 2048d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (filter == nullptr) { 2049d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return 1; 2050cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2051d0f492db038c6210c1138865d816bfb134376538Adam Lesinski options.table_splitter_options.config_filter = filter.get(); 2052cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2053cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 2054ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (preferred_density) { 2055d0f492db038c6210c1138865d816bfb134376538Adam Lesinski Maybe<uint16_t> density = 2056d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ParseTargetDensityParameter(preferred_density.value(), context.GetDiagnostics()); 2057d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!density) { 2058cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 2059cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2060d0f492db038c6210c1138865d816bfb134376538Adam Lesinski options.table_splitter_options.preferred_densities.push_back(density.value()); 2061d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 2062cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 2063d0f492db038c6210c1138865d816bfb134376538Adam Lesinski // Parse the split parameters. 2064d0f492db038c6210c1138865d816bfb134376538Adam Lesinski for (const std::string& split_arg : split_args) { 2065d0f492db038c6210c1138865d816bfb134376538Adam Lesinski options.split_paths.push_back({}); 2066d0f492db038c6210c1138865d816bfb134376538Adam Lesinski options.split_constraints.push_back({}); 2067d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!ParseSplitParameter(split_arg, context.GetDiagnostics(), &options.split_paths.back(), 2068d0f492db038c6210c1138865d816bfb134376538Adam Lesinski &options.split_constraints.back())) { 2069cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 2070cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2071cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2072cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 2073b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski if (context.GetPackageType() != PackageType::kStaticLib && stable_id_file_path) { 2074ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!LoadStableIdMap(context.GetDiagnostics(), stable_id_file_path.value(), 2075ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &options.stable_id_map)) { 2076cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 2077cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2078cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2079cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 2080cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Populate some default no-compress extensions that are already compressed. 2081ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options.extensions_to_not_compress.insert( 2082cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski {".jpg", ".jpeg", ".png", ".gif", ".wav", ".mp2", ".mp3", ".ogg", 2083cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ".aac", ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet", ".rtttl", 2084cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ".imy", ".xmf", ".mp4", ".m4a", ".m4v", ".3gp", ".3gpp", ".3g2", 2085cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ".3gpp2", ".amr", ".awb", ".wma", ".wmv", ".webm", ".mkv"}); 2086cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 2087cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Turn off auto versioning for static-libs. 2088b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski if (context.GetPackageType() == PackageType::kStaticLib) { 2089ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options.no_auto_version = true; 2090ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options.no_version_vectors = true; 20914d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki options.no_version_transitions = true; 2092cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2093cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 2094cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski LinkCommand cmd(&context, options); 2095ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return cmd.Run(arg_list); 20961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 20971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2098cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} // namespace aapt 2099