diff options
Diffstat (limited to 'tools/aapt2/cmd/Compile.cpp')
-rw-r--r-- | tools/aapt2/cmd/Compile.cpp | 295 |
1 files changed, 163 insertions, 132 deletions
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp index 7f5bbf042766..101f74eafaf4 100644 --- a/tools/aapt2/cmd/Compile.cpp +++ b/tools/aapt2/cmd/Compile.cpp @@ -35,12 +35,13 @@ #include "compile/Png.h" #include "compile/PseudolocaleGenerator.h" #include "compile/XmlIdCollector.h" -#include "flatten/Archive.h" -#include "flatten/XmlFlattener.h" -#include "io/BigBufferOutputStream.h" -#include "io/FileInputStream.h" +#include "format/Archive.h" +#include "format/Container.h" +#include "format/proto/ProtoSerialize.h" +#include "io/BigBufferStream.h" +#include "io/FileStream.h" +#include "io/StringStream.h" #include "io/Util.h" -#include "proto/ProtoSerialize.h" #include "util/Files.h" #include "util/Maybe.h" #include "util/Util.h" @@ -48,7 +49,9 @@ #include "xml/XmlPullParser.h" using ::aapt::io::FileInputStream; +using ::aapt::text::Printer; using ::android::StringPiece; +using ::android::base::SystemErrorCodeToString; using ::google::protobuf::io::CopyingOutputStreamAdaptor; namespace aapt { @@ -110,13 +113,14 @@ static Maybe<ResourcePathData> ExtractResourcePathData(const std::string& path, struct CompileOptions { std::string output_path; Maybe<std::string> res_dir; + Maybe<std::string> generate_text_symbols_path; bool pseudolocalize = false; bool no_png_crunch = false; bool legacy_mode = false; bool verbose = false; }; -static std::string BuildIntermediateFilename(const ResourcePathData& data) { +static std::string BuildIntermediateContainerFilename(const ResourcePathData& data) { std::stringstream name; name << data.resource_dir; if (!data.config_str.empty()) { @@ -141,7 +145,7 @@ static bool LoadInputFilesFromDir(IAaptContext* context, const CompileOptions& o std::unique_ptr<DIR, decltype(closedir)*> d(opendir(root_dir.data()), closedir); if (!d) { context->GetDiagnostics()->Error(DiagMessage(root_dir) << "failed to open directory: " - << android::base::SystemErrorCodeToString(errno)); + << SystemErrorCodeToString(errno)); return false; } @@ -160,7 +164,7 @@ static bool LoadInputFilesFromDir(IAaptContext* context, const CompileOptions& o std::unique_ptr<DIR, decltype(closedir)*> subdir(opendir(prefix_path.data()), closedir); if (!subdir) { context->GetDiagnostics()->Error(DiagMessage(prefix_path) << "failed to open directory: " - << android::base::SystemErrorCodeToString(errno)); + << SystemErrorCodeToString(errno)); return false; } @@ -182,6 +186,12 @@ static bool LoadInputFilesFromDir(IAaptContext* context, const CompileOptions& o out_path_data->push_back(std::move(path_data.value())); } } + + // File-system directory enumeration order is platform-dependent. Sort the result to remove any + // inconsistencies between platforms. + std::sort( + out_path_data->begin(), out_path_data->end(), + [](const ResourcePathData& a, const ResourcePathData& b) { return a.source < b.source; }); return true; } @@ -241,15 +251,15 @@ static bool CompileTable(IAaptContext* context, const CompileOptions& options, return false; } - // Make sure CopyingOutputStreamAdaptor is deleted before we call - // writer->FinishEntry(). + // Make sure CopyingOutputStreamAdaptor is deleted before we call writer->FinishEntry(). { - // Wrap our IArchiveWriter with an adaptor that implements the - // ZeroCopyOutputStream interface. + // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream interface. CopyingOutputStreamAdaptor copying_adaptor(writer); + ContainerWriter container_writer(©ing_adaptor, 1u); - std::unique_ptr<pb::ResourceTable> pb_table = SerializeTableToPb(&table); - if (!pb_table->SerializeToZeroCopyStream(©ing_adaptor)) { + pb::ResourceTable pb_table; + SerializeTableToPb(table, &pb_table); + if (!container_writer.AddResTableEntry(pb_table)) { context->GetDiagnostics()->Error(DiagMessage(output_path) << "failed to write"); return false; } @@ -259,48 +269,63 @@ static bool CompileTable(IAaptContext* context, const CompileOptions& options, context->GetDiagnostics()->Error(DiagMessage(output_path) << "failed to finish entry"); return false; } - return true; -} - -static bool WriteHeaderAndBufferToWriter(const StringPiece& output_path, const ResourceFile& file, - const BigBuffer& buffer, IArchiveWriter* writer, - IDiagnostics* diag) { - // Start the entry so we can write the header. - if (!writer->StartEntry(output_path, 0)) { - diag->Error(DiagMessage(output_path) << "failed to open file"); - return false; - } - // Make sure CopyingOutputStreamAdaptor is deleted before we call - // writer->FinishEntry(). - { - // Wrap our IArchiveWriter with an adaptor that implements the - // ZeroCopyOutputStream interface. - CopyingOutputStreamAdaptor copying_adaptor(writer); - CompiledFileOutputStream output_stream(©ing_adaptor); + if (options.generate_text_symbols_path) { + io::FileOutputStream fout_text(options.generate_text_symbols_path.value()); - // Number of CompiledFiles. - output_stream.WriteLittleEndian32(1); + if (fout_text.HadError()) { + context->GetDiagnostics()->Error(DiagMessage() + << "failed writing to'" + << options.generate_text_symbols_path.value() + << "': " << fout_text.GetError()); + return false; + } - std::unique_ptr<pb::internal::CompiledFile> compiled_file = SerializeCompiledFileToPb(file); - output_stream.WriteCompiledFile(compiled_file.get()); - output_stream.WriteData(&buffer); + Printer r_txt_printer(&fout_text); + for (const auto& package : table.packages) { + for (const auto& type : package->types) { + for (const auto& entry : type->entries) { + // Check access modifiers. + switch(entry->visibility.level) { + case Visibility::Level::kUndefined : + r_txt_printer.Print("default "); + break; + case Visibility::Level::kPublic : + r_txt_printer.Print("public "); + break; + case Visibility::Level::kPrivate : + r_txt_printer.Print("private "); + } - if (output_stream.HadError()) { - diag->Error(DiagMessage(output_path) << "failed to write data"); - return false; + if (type->type != ResourceType::kStyleable) { + r_txt_printer.Print("int "); + r_txt_printer.Print(to_string(type->type)); + r_txt_printer.Print(" "); + r_txt_printer.Println(entry->name); + } else { + r_txt_printer.Print("int[] styleable "); + r_txt_printer.Println(entry->name); + + if (!entry->values.empty()) { + auto styleable = static_cast<const Styleable*>(entry->values.front()->value.get()); + for (const auto& attr : styleable->entries) { + r_txt_printer.Print("default int styleable "); + r_txt_printer.Print(entry->name); + r_txt_printer.Print("_"); + r_txt_printer.Println(attr.name.value().entry); + } + } + } + } + } } } - if (!writer->FinishEntry()) { - diag->Error(DiagMessage(output_path) << "failed to finish writing data"); - return false; - } return true; } -static bool WriteHeaderAndMmapToWriter(const StringPiece& output_path, const ResourceFile& file, - const android::FileMap& map, IArchiveWriter* writer, +static bool WriteHeaderAndDataToWriter(const StringPiece& output_path, const ResourceFile& file, + io::KnownSizeInputStream* in, IArchiveWriter* writer, IDiagnostics* diag) { // Start the entry so we can write the header. if (!writer->StartEntry(output_path, 0)) { @@ -308,23 +333,17 @@ static bool WriteHeaderAndMmapToWriter(const StringPiece& output_path, const Res return false; } - // Make sure CopyingOutputStreamAdaptor is deleted before we call - // writer->FinishEntry(). + // Make sure CopyingOutputStreamAdaptor is deleted before we call writer->FinishEntry(). { - // Wrap our IArchiveWriter with an adaptor that implements the - // ZeroCopyOutputStream interface. + // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream interface. CopyingOutputStreamAdaptor copying_adaptor(writer); - CompiledFileOutputStream output_stream(©ing_adaptor); + ContainerWriter container_writer(©ing_adaptor, 1u); - // Number of CompiledFiles. - output_stream.WriteLittleEndian32(1); + pb::internal::CompiledFile pb_compiled_file; + SerializeCompiledFileToPb(file, &pb_compiled_file); - std::unique_ptr<pb::internal::CompiledFile> compiled_file = SerializeCompiledFileToPb(file); - output_stream.WriteCompiledFile(compiled_file.get()); - output_stream.WriteData(map.getDataPtr(), map.getDataLength()); - - if (output_stream.HadError()) { - diag->Error(DiagMessage(output_path) << "failed to write data"); + if (!container_writer.AddResFileEntry(pb_compiled_file, in)) { + diag->Error(DiagMessage(output_path) << "failed to write entry data"); return false; } } @@ -336,23 +355,19 @@ static bool WriteHeaderAndMmapToWriter(const StringPiece& output_path, const Res return true; } -static bool FlattenXmlToOutStream(IAaptContext* context, const StringPiece& output_path, - xml::XmlResource* xmlres, CompiledFileOutputStream* out) { - BigBuffer buffer(1024); - XmlFlattenerOptions xml_flattener_options; - xml_flattener_options.keep_raw_values = true; - XmlFlattener flattener(&buffer, xml_flattener_options); - if (!flattener.Consume(context, xmlres)) { - return false; - } +static bool FlattenXmlToOutStream(const StringPiece& output_path, const xml::XmlResource& xmlres, + ContainerWriter* container_writer, IDiagnostics* diag) { + pb::internal::CompiledFile pb_compiled_file; + SerializeCompiledFileToPb(xmlres.file, &pb_compiled_file); + + pb::XmlNode pb_xml_node; + SerializeXmlToPb(*xmlres.root, &pb_xml_node); - std::unique_ptr<pb::internal::CompiledFile> pb_compiled_file = - SerializeCompiledFileToPb(xmlres->file); - out->WriteCompiledFile(pb_compiled_file.get()); - out->WriteData(&buffer); + std::string serialized_xml = pb_xml_node.SerializeAsString(); + io::StringInputStream serialized_in(serialized_xml); - if (out->HadError()) { - context->GetDiagnostics()->Error(DiagMessage(output_path) << "failed to write data"); + if (!container_writer->AddResFileEntry(pb_compiled_file, &serialized_in)) { + diag->Error(DiagMessage(output_path) << "failed to write entry data"); return false; } return true; @@ -401,6 +416,7 @@ static bool CompileXml(IAaptContext* context, const CompileOptions& options, xmlres->file.name = ResourceName({}, *ParseResourceType(path_data.resource_dir), path_data.name); xmlres->file.config = path_data.config; xmlres->file.source = path_data.source; + xmlres->file.type = ResourceFile::Type::kProtoXml; // Collect IDs that are defined here. XmlIdCollector collector; @@ -420,24 +436,23 @@ static bool CompileXml(IAaptContext* context, const CompileOptions& options, return false; } + std::vector<std::unique_ptr<xml::XmlResource>>& inline_documents = + inline_xml_format_parser.GetExtractedInlineXmlDocuments(); + // Make sure CopyingOutputStreamAdaptor is deleted before we call writer->FinishEntry(). { // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream interface. CopyingOutputStreamAdaptor copying_adaptor(writer); - CompiledFileOutputStream output_stream(©ing_adaptor); - - std::vector<std::unique_ptr<xml::XmlResource>>& inline_documents = - inline_xml_format_parser.GetExtractedInlineXmlDocuments(); + ContainerWriter container_writer(©ing_adaptor, 1u + inline_documents.size()); - // Number of CompiledFiles. - output_stream.WriteLittleEndian32(1 + inline_documents.size()); - - if (!FlattenXmlToOutStream(context, output_path, xmlres.get(), &output_stream)) { + if (!FlattenXmlToOutStream(output_path, *xmlres, &container_writer, + context->GetDiagnostics())) { return false; } - for (auto& inline_xml_doc : inline_documents) { - if (!FlattenXmlToOutStream(context, output_path, inline_xml_doc.get(), &output_stream)) { + for (const std::unique_ptr<xml::XmlResource>& inline_xml_doc : inline_documents) { + if (!FlattenXmlToOutStream(output_path, *inline_xml_doc, &container_writer, + context->GetDiagnostics())) { return false; } } @@ -447,6 +462,31 @@ static bool CompileXml(IAaptContext* context, const CompileOptions& options, context->GetDiagnostics()->Error(DiagMessage(output_path) << "failed to finish writing data"); return false; } + + if (options.generate_text_symbols_path) { + io::FileOutputStream fout_text(options.generate_text_symbols_path.value()); + + if (fout_text.HadError()) { + context->GetDiagnostics()->Error(DiagMessage() + << "failed writing to'" + << options.generate_text_symbols_path.value() + << "': " << fout_text.GetError()); + return false; + } + + Printer r_txt_printer(&fout_text); + for (const auto res : xmlres->file.exported_symbols) { + r_txt_printer.Print("default int id "); + r_txt_printer.Println(res.name.entry); + } + + // And print ourselves. + r_txt_printer.Print("default int "); + r_txt_printer.Print(path_data.resource_dir); + r_txt_printer.Print(" "); + r_txt_printer.Println(path_data.name); + } + return true; } @@ -462,6 +502,7 @@ static bool CompilePng(IAaptContext* context, const CompileOptions& options, res_file.name = ResourceName({}, *ParseResourceType(path_data.resource_dir), path_data.name); res_file.config = path_data.config; res_file.source = path_data.source; + res_file.type = ResourceFile::Type::kPng; { std::string content; @@ -469,7 +510,7 @@ static bool CompilePng(IAaptContext* context, const CompileOptions& options, true /*follow_symlinks*/)) { context->GetDiagnostics()->Error(DiagMessage(path_data.source) << "failed to open file: " - << android::base::SystemErrorCodeToString(errno)); + << SystemErrorCodeToString(errno)); return false; } @@ -553,8 +594,9 @@ static bool CompilePng(IAaptContext* context, const CompileOptions& options, } } - if (!WriteHeaderAndBufferToWriter(output_path, res_file, buffer, writer, - context->GetDiagnostics())) { + io::BigBufferInputStream buffer_in(&buffer); + if (!WriteHeaderAndDataToWriter(output_path, res_file, &buffer_in, writer, + context->GetDiagnostics())) { return false; } return true; @@ -572,6 +614,7 @@ static bool CompileFile(IAaptContext* context, const CompileOptions& options, res_file.name = ResourceName({}, *ParseResourceType(path_data.resource_dir), path_data.name); res_file.config = path_data.config; res_file.source = path_data.source; + res_file.type = ResourceFile::Type::kUnknown; std::string error_str; Maybe<android::FileMap> f = file::MmapPath(path_data.source.path, &error_str); @@ -581,7 +624,8 @@ static bool CompileFile(IAaptContext* context, const CompileOptions& options, return false; } - if (!WriteHeaderAndMmapToWriter(output_path, res_file, f.value(), writer, + io::MmappedData mmapped_in(std::move(f.value())); + if (!WriteHeaderAndDataToWriter(output_path, res_file, &mmapped_in, writer, context->GetDiagnostics())) { return false; } @@ -611,7 +655,7 @@ class CompileContext : public IAaptContext { } NameMangler* GetNameMangler() override { - abort(); + UNIMPLEMENTED(FATAL) << "No name mangling should be needed in compile phase"; return nullptr; } @@ -625,7 +669,7 @@ class CompileContext : public IAaptContext { } SymbolTable* GetExternalSymbols() override { - abort(); + UNIMPLEMENTED(FATAL) << "No symbols should be needed in compile phase"; return nullptr; } @@ -634,14 +678,13 @@ class CompileContext : public IAaptContext { } private: + DISALLOW_COPY_AND_ASSIGN(CompileContext); + IDiagnostics* diagnostics_; bool verbose_ = false; }; -/** - * Entry point for compilation phase. Parses arguments and dispatches to the - * correct steps. - */ +// Entry point for compilation phase. Parses arguments and dispatches to the correct steps. int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) { CompileContext context(diagnostics); CompileOptions options; @@ -651,6 +694,10 @@ int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) { Flags() .RequiredFlag("-o", "Output path", &options.output_path) .OptionalFlag("--dir", "Directory to scan for resources", &options.res_dir) + .OptionalFlag("--output-text-symbols", + "Generates a text file containing the resource symbols in the\n" + "specified file", + &options.generate_text_symbols_path) .OptionalSwitch("--pseudo-localize", "Generate resources for pseudo-locales " "(en-XA and ar-XB)", @@ -714,50 +761,34 @@ int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) { continue; } - if (path_data.resource_dir == "values") { - // Overwrite the extension. + // Determine how to compile the file based on its type. + auto compile_func = &CompileFile; + if (path_data.resource_dir == "values" && path_data.extension == "xml") { + compile_func = &CompileTable; + // We use a different extension (not necessary anymore, but avoids altering the existing + // build system logic). path_data.extension = "arsc"; - - const std::string output_filename = BuildIntermediateFilename(path_data); - if (!CompileTable(&context, options, path_data, archive_writer.get(), output_filename)) { - error = true; - } - - } else { - const std::string output_filename = BuildIntermediateFilename(path_data); - if (const ResourceType* type = ParseResourceType(path_data.resource_dir)) { - if (*type != ResourceType::kRaw) { - if (path_data.extension == "xml") { - if (!CompileXml(&context, options, path_data, archive_writer.get(), output_filename)) { - error = true; - } - } else if (!options.no_png_crunch && - (path_data.extension == "png" || path_data.extension == "9.png")) { - if (!CompilePng(&context, options, path_data, archive_writer.get(), output_filename)) { - error = true; - } - } else { - if (!CompileFile(&context, options, path_data, archive_writer.get(), output_filename)) { - error = true; - } - } - } else { - if (!CompileFile(&context, options, path_data, archive_writer.get(), output_filename)) { - error = true; - } + } else if (const ResourceType* type = ParseResourceType(path_data.resource_dir)) { + if (*type != ResourceType::kRaw) { + if (path_data.extension == "xml") { + compile_func = &CompileXml; + } else if ((!options.no_png_crunch && path_data.extension == "png") || + path_data.extension == "9.png") { + compile_func = &CompilePng; } - } else { - context.GetDiagnostics()->Error(DiagMessage() << "invalid file path '" << path_data.source - << "'"); - error = true; } + } else { + context.GetDiagnostics()->Error(DiagMessage() + << "invalid file path '" << path_data.source << "'"); + error = true; + continue; } - } - if (error) { - return 1; + // Compile the file. + const std::string out_path = BuildIntermediateContainerFilename(path_data); + error |= !compile_func(&context, options, path_data, archive_writer.get(), out_path); } - return 0; + return error ? 1 : 0; } } // namespace aapt |