Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 833a1a6c authored by Ryan Mitchell's avatar Ryan Mitchell
Browse files

AAPT2: Refactor flags into commands

Refactors the flag based command invocation into classes that make using
subcommands easier.

Test: manual tests of printing
Change-Id: Ic8df6af0be30db552e32150afebecbfeec7e1075
parent 53208af2
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -15,6 +15,7 @@
//
//


toolSources = [
toolSources = [
    "cmd/Command.cpp",
    "cmd/Compile.cpp",
    "cmd/Compile.cpp",
    "cmd/Convert.cpp",
    "cmd/Convert.cpp",
    "cmd/Diff.cpp",
    "cmd/Diff.cpp",
@@ -124,7 +125,6 @@ cc_library_host_static {
        "ConfigDescription.cpp",
        "ConfigDescription.cpp",
        "Debug.cpp",
        "Debug.cpp",
        "DominatorTree.cpp",
        "DominatorTree.cpp",
        "Flags.cpp",
        "java/AnnotationProcessor.cpp",
        "java/AnnotationProcessor.cpp",
        "java/ClassDefinition.cpp",
        "java/ClassDefinition.cpp",
        "java/JavaClassGenerator.cpp",
        "java/JavaClassGenerator.cpp",
+97 −83
Original line number Original line Diff line number Diff line
@@ -29,6 +29,13 @@
#include "androidfw/StringPiece.h"
#include "androidfw/StringPiece.h"


#include "Diagnostics.h"
#include "Diagnostics.h"
#include "cmd/Command.h"
#include "cmd/Compile.h"
#include "cmd/Convert.h"
#include "cmd/Diff.h"
#include "cmd/Dump.h"
#include "cmd/Link.h"
#include "cmd/Optimize.h"
#include "util/Files.h"
#include "util/Files.h"
#include "util/Util.h"
#include "util/Util.h"


@@ -43,52 +50,66 @@ static const char* sMajorVersion = "2";
// Update minor version whenever a feature or flag is added.
// Update minor version whenever a feature or flag is added.
static const char* sMinorVersion = "19";
static const char* sMinorVersion = "19";


static void PrintVersion() {
/** Prints the version information of AAPT2. */
class VersionCommand : public Command {
 public:
  explicit VersionCommand() : Command("version") {
    SetDescription("Prints the version of aapt.");
  }

  int Action(const std::vector<std::string>& /* args */) override {
    std::cerr << StringPrintf("Android Asset Packaging Tool (aapt) %s:%s", sMajorVersion,
    std::cerr << StringPrintf("Android Asset Packaging Tool (aapt) %s:%s", sMajorVersion,
                              sMinorVersion)
                              sMinorVersion)
              << std::endl;
              << std::endl;
    return 0;
  }
  }
};


static void PrintUsage() {
/** The main entry point of AAPT. */
  std::cerr << "\nusage: aapt2 [compile|link|dump|diff|optimize|convert|version] ..." << std::endl;
class MainCommand : public Command {
}
 public:

  explicit MainCommand(IDiagnostics* diagnostics) : Command("aapt2"), diagnostics_(diagnostics) {
extern int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics);
    AddOptionalSubcommand(util::make_unique<CompileCommand>(diagnostics));
extern int Link(const std::vector<StringPiece>& args, IDiagnostics* diagnostics);
    AddOptionalSubcommand(util::make_unique<LinkCommand>(diagnostics));
extern int Dump(const std::vector<StringPiece>& args);
    AddOptionalSubcommand(util::make_unique<DumpCommand>());
extern int Diff(const std::vector<StringPiece>& args);
    AddOptionalSubcommand(util::make_unique<DiffCommand>());
extern int Optimize(const std::vector<StringPiece>& args);
    AddOptionalSubcommand(util::make_unique<OptimizeCommand>());
extern int Convert(const std::vector<StringPiece>& args);
    AddOptionalSubcommand(util::make_unique<ConvertCommand>());

    AddOptionalSubcommand(util::make_unique<VersionCommand>());
static int ExecuteCommand(const StringPiece& command, const std::vector<StringPiece>& args,
  }
                          IDiagnostics* diagnostics) {

  if (command == "compile" || command == "c") {
  int Action(const std::vector<std::string>& args) override {
    return Compile(args, diagnostics);
    if (args.size() == 0) {
  } else if (command == "link" || command == "l") {
      diagnostics_->Error(DiagMessage() << "no subcommand specified");
    return Link(args, diagnostics);
    } else {
  } else if (command == "dump" || command == "d") {
      diagnostics_->Error(DiagMessage() << "unknown subcommand '" << args[0] << "'");
    return Dump(args);
  } else if (command == "diff") {
    return Diff(args);
  } else if (command == "optimize") {
    return Optimize(args);
  } else if (command == "convert") {
    return Convert(args);
  } else if (command == "version") {
    PrintVersion();
    return 0;
    }
    }
  diagnostics->Error(DiagMessage() << "unknown command '" << command << "'");

    Usage(&std::cerr);
    return -1;
    return -1;
  }
  }


static void RunDaemon(IDiagnostics* diagnostics) {
 private:
  IDiagnostics* diagnostics_;
};

/*
 * Run in daemon mode. The first line of input is the command. This can be 'quit' which ends
 * the daemon mode. Each subsequent line is a single parameter to the command. The end of a
 * invocation is signaled by providing an empty line. At any point, an EOF signal or the
 * command 'quit' will end the daemon mode.
 */
class DaemonCommand : public Command {
 public:
  explicit DaemonCommand(IDiagnostics* diagnostics) : Command("daemon", "m"),
                                                      diagnostics_(diagnostics) {
    SetDescription("Runs aapt in daemon mode. Each subsequent line is a single parameter to the\n"
        "command. The end of an invocation is signaled by providing an empty line.");
  }

  int Action(const std::vector<std::string>& /* args */) override {
    std::cout << "Ready" << std::endl;
    std::cout << "Ready" << std::endl;


  // Run in daemon mode. The first line of input is the command. This can be 'quit' which ends
  // the daemon mode. Each subsequent line is a single parameter to the command. The end of a
  // invocation is signaled by providing an empty line. At any point, an EOF signal or the
  // command 'quit' will end the daemon mode.
    while (true) {
    while (true) {
      std::vector<std::string> raw_args;
      std::vector<std::string> raw_args;
      for (std::string line; std::getline(std::cin, line) && !line.empty();) {
      for (std::string line; std::getline(std::cin, line) && !line.empty();) {
@@ -104,53 +125,46 @@ static void RunDaemon(IDiagnostics* diagnostics) {
        continue;
        continue;
      }
      }


      // End the dameon
      if (raw_args[0] == "quit") {
      if (raw_args[0] == "quit") {
        break;
        break;
      }
      }


      std::vector<StringPiece> args;
      std::vector<StringPiece> args;
    args.insert(args.end(), ++raw_args.begin(), raw_args.end());
      args.insert(args.end(), raw_args.begin(), raw_args.end());
    int ret = ExecuteCommand(raw_args[0], args, diagnostics);
      if (MainCommand(diagnostics_).Execute(args, &std::cerr) != 0) {
    if (ret != 0) {
        std::cerr << "Error" << std::endl;
        std::cerr << "Error" << std::endl;
      }
      }
      std::cerr << "Done" << std::endl;
      std::cerr << "Done" << std::endl;
    }
    }
    std::cout << "Exiting daemon" << std::endl;
    std::cout << "Exiting daemon" << std::endl;

    return 0;
  }
  }


 private:
  IDiagnostics* diagnostics_;
};

}  // namespace aapt
}  // namespace aapt


int MainImpl(int argc, char** argv) {
int MainImpl(int argc, char** argv) {
  if (argc < 2) {
  if (argc < 1) {
    std::cerr << "no command specified\n";
    aapt::PrintUsage();
    return -1;
    return -1;
  }
  }


  argv += 1;
  argc -= 1;

  aapt::StdErrDiagnostics diagnostics;

  // Collect the arguments starting after the program name and command name.
  // Collect the arguments starting after the program name and command name.
  std::vector<StringPiece> args;
  std::vector<StringPiece> args;
  for (int i = 1; i < argc; i++) {
  for (int i = 1; i < argc; i++) {
    args.push_back(argv[i]);
    args.push_back(argv[i]);
  }
  }


  const StringPiece command(argv[0]);
  // Add the daemon subcommand here so it cannot be called while executing the daemon
  if (command != "daemon" && command != "m") {
  aapt::StdErrDiagnostics diagnostics;
    // Single execution.
  auto main_command = new aapt::MainCommand(&diagnostics);
    const int result = aapt::ExecuteCommand(command, args, &diagnostics);
  main_command->AddOptionalSubcommand(aapt::util::make_unique<aapt::DaemonCommand>(&diagnostics));
    if (result < 0) {
      aapt::PrintUsage();
    }
    return result;
  }


  aapt::RunDaemon(&diagnostics);
  return main_command->Execute(args, &std::cerr);
  return 0;
}
}


int main(int argc, char** argv) {
int main(int argc, char** argv) {
+78 −45
Original line number Original line Diff line number Diff line
/*
/*
 * Copyright (C) 2015 The Android Open Source Project
 * Copyright (C) 2018 The Android Open Source Project
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


#include "Flags.h"
#include "Command.h"


#include <iomanip>
#include <iomanip>
#include <iostream>
#include <iostream>
@@ -29,7 +29,7 @@ using android::StringPiece;


namespace aapt {
namespace aapt {


Flags& Flags::RequiredFlag(const StringPiece& name,
void Command::AddRequiredFlag(const StringPiece& name,
    const StringPiece& description, std::string* value) {
    const StringPiece& description, std::string* value) {
  auto func = [value](const StringPiece& arg) -> bool {
  auto func = [value](const StringPiece& arg) -> bool {
    *value = arg.to_string();
    *value = arg.to_string();
@@ -37,10 +37,9 @@ Flags& Flags::RequiredFlag(const StringPiece& name,
  };
  };


  flags_.push_back(Flag{name.to_string(), description.to_string(), func, true, 1, false});
  flags_.push_back(Flag{name.to_string(), description.to_string(), func, true, 1, false});
  return *this;
}
}


Flags& Flags::RequiredFlagList(const StringPiece& name,
void Command::AddRequiredFlagList(const StringPiece& name,
    const StringPiece& description,
    const StringPiece& description,
    std::vector<std::string>* value) {
    std::vector<std::string>* value) {
  auto func = [value](const StringPiece& arg) -> bool {
  auto func = [value](const StringPiece& arg) -> bool {
@@ -49,10 +48,9 @@ Flags& Flags::RequiredFlagList(const StringPiece& name,
  };
  };


  flags_.push_back(Flag{name.to_string(), description.to_string(), func, true, 1, false});
  flags_.push_back(Flag{name.to_string(), description.to_string(), func, true, 1, false});
  return *this;
}
}


Flags& Flags::OptionalFlag(const StringPiece& name,
void Command::AddOptionalFlag(const StringPiece& name,
    const StringPiece& description,
    const StringPiece& description,
    Maybe<std::string>* value) {
    Maybe<std::string>* value) {
  auto func = [value](const StringPiece& arg) -> bool {
  auto func = [value](const StringPiece& arg) -> bool {
@@ -61,10 +59,9 @@ Flags& Flags::OptionalFlag(const StringPiece& name,
  };
  };


  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
  return *this;
}
}


Flags& Flags::OptionalFlagList(const StringPiece& name,
void Command::AddOptionalFlagList(const StringPiece& name,
    const StringPiece& description,
    const StringPiece& description,
    std::vector<std::string>* value) {
    std::vector<std::string>* value) {
  auto func = [value](const StringPiece& arg) -> bool {
  auto func = [value](const StringPiece& arg) -> bool {
@@ -73,10 +70,9 @@ Flags& Flags::OptionalFlagList(const StringPiece& name,
  };
  };


  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
  return *this;
}
}


Flags& Flags::OptionalFlagList(const StringPiece& name,
void Command::AddOptionalFlagList(const StringPiece& name,
    const StringPiece& description,
    const StringPiece& description,
    std::unordered_set<std::string>* value) {
    std::unordered_set<std::string>* value) {
  auto func = [value](const StringPiece& arg) -> bool {
  auto func = [value](const StringPiece& arg) -> bool {
@@ -85,10 +81,9 @@ Flags& Flags::OptionalFlagList(const StringPiece& name,
  };
  };


  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
  return *this;
}
}


Flags& Flags::OptionalSwitch(const StringPiece& name,
void Command::AddOptionalSwitch(const StringPiece& name,
    const StringPiece& description, bool* value) {
    const StringPiece& description, bool* value) {
  auto func = [value](const StringPiece& arg) -> bool {
  auto func = [value](const StringPiece& arg) -> bool {
    *value = true;
    *value = true;
@@ -96,20 +91,51 @@ Flags& Flags::OptionalSwitch(const StringPiece& name,
  };
  };


  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 0, false});
  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 0, false});
  return *this;
}
}


void Flags::Usage(const StringPiece& command, std::ostream* out) {
void Command::AddOptionalSubcommand(std::unique_ptr<Command>&& subcommand) {
  subcommand->fullname_ = name_ + " " + subcommand->name_;
  subcommands_.push_back(std::move(subcommand));
}

void Command::SetDescription(const android::StringPiece& description) {
  description_ = description.to_string();
}

void Command::Usage(std::ostream* out) {
  constexpr size_t kWidth = 50;
  constexpr size_t kWidth = 50;


  *out << command << " [options]";
  *out << fullname_;

  if (!subcommands_.empty()) {
    *out << " [subcommand]";
  }

  *out << " [options]";
  for (const Flag& flag : flags_) {
  for (const Flag& flag : flags_) {
    if (flag.required) {
    if (flag.required) {
      *out << " " << flag.name << " arg";
      *out << " " << flag.name << " arg";
    }
    }
  }
  }


  *out << " files...\n\nOptions:\n";
  *out << " files...\n";

  if (!subcommands_.empty()) {
    *out << "\nSubcommands:\n";
    for (auto& subcommand : subcommands_) {
      std::string argline = subcommand->name_;

      // Split the description by newlines and write out the argument (which is
      // empty after the first line) followed by the description line. This will make sure
      // that multiline descriptions are still right justified and aligned.
      for (StringPiece line : util::Tokenize(subcommand->description_, '\n')) {
        *out << " " << std::setw(kWidth) << std::left << argline << line << "\n";
        argline = " ";
      }
    }
  }

  *out << "\nOptions:\n";


  for (const Flag& flag : flags_) {
  for (const Flag& flag : flags_) {
    std::string argline = flag.name;
    std::string argline = flag.name;
@@ -118,10 +144,8 @@ void Flags::Usage(const StringPiece& command, std::ostream* out) {
    }
    }


    // Split the description by newlines and write out the argument (which is
    // Split the description by newlines and write out the argument (which is
    // empty after
    // empty after the first line) followed by the description line. This will make sure
    // the first line) followed by the description line. This will make sure
    // that multiline descriptions are still right justified and aligned.
    // that multiline
    // descriptions are still right justified and aligned.
    for (StringPiece line : util::Tokenize(flag.description, '\n')) {
    for (StringPiece line : util::Tokenize(flag.description, '\n')) {
      *out << " " << std::setw(kWidth) << std::left << argline << line << "\n";
      *out << " " << std::setw(kWidth) << std::left << argline << line << "\n";
      argline = " ";
      argline = " ";
@@ -132,19 +156,29 @@ void Flags::Usage(const StringPiece& command, std::ostream* out) {
  out->flush();
  out->flush();
}
}


bool Flags::Parse(const StringPiece& command,
int Command::Execute(const std::vector<android::StringPiece>& args, std::ostream* out_error) {
                  const std::vector<StringPiece>& args,
  std::vector<std::string> file_args;
                  std::ostream* out_error) {

  for (size_t i = 0; i < args.size(); i++) {
  for (size_t i = 0; i < args.size(); i++) {
    StringPiece arg = args[i];
    StringPiece arg = args[i];
    if (*(arg.data()) != '-') {
    if (*(arg.data()) != '-') {
      args_.push_back(arg.to_string());
      // Continue parsing as the sub command if the first argument matches one of the subcommands
      if (i == 0) {
        for (auto& subcommand : subcommands_) {
          if (arg == subcommand->name_ || arg==subcommand->short_name_) {
            return subcommand->Execute(
                std::vector<android::StringPiece>(args.begin() + 1, args.end()), out_error);
          }
        }
      }

      file_args.push_back(arg.to_string());
      continue;
      continue;
    }
    }


    if (arg == "-h" || arg == "--help") {
    if (arg == "-h" || arg == "--help") {
      Usage(command, out_error);
      Usage(out_error);
      return false;
      return 1;
    }
    }


    bool match = false;
    bool match = false;
@@ -154,7 +188,7 @@ bool Flags::Parse(const StringPiece& command,
          i++;
          i++;
          if (i >= args.size()) {
          if (i >= args.size()) {
            *out_error << flag.name << " missing argument.\n\n";
            *out_error << flag.name << " missing argument.\n\n";
            Usage(command, out_error);
            Usage(out_error);
            return false;
            return false;
          }
          }
          flag.action(args[i]);
          flag.action(args[i]);
@@ -169,21 +203,20 @@ bool Flags::Parse(const StringPiece& command,


    if (!match) {
    if (!match) {
      *out_error << "unknown option '" << arg << "'.\n\n";
      *out_error << "unknown option '" << arg << "'.\n\n";
      Usage(command, out_error);
      Usage(out_error);
      return false;
      return 1;
    }
    }
  }
  }


  for (const Flag& flag : flags_) {
  for (const Flag& flag : flags_) {
    if (flag.required && !flag.parsed) {
    if (flag.required && !flag.parsed) {
      *out_error << "missing required flag " << flag.name << "\n\n";
      *out_error << "missing required flag " << flag.name << "\n\n";
      Usage(command, out_error);
      Usage(out_error);
      return false;
      return 1;
    }
    }
  }
  }
  return true;
}


const std::vector<std::string>& Flags::GetArgs() { return args_; }
  return Action(file_args);
}


}  // namespace aapt
}  // namespace aapt
+90 −0
Original line number Original line Diff line number Diff line
/*
/*
 * Copyright (C) 2015 The Android Open Source Project
 * Copyright (C) 2018 The Android Open Source Project
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * you may not use this file except in compliance with the License.
@@ -14,8 +14,8 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


#ifndef AAPT_FLAGS_H
#ifndef AAPT_COMMAND_H
#define AAPT_FLAGS_H
#define AAPT_COMMAND_H


#include <functional>
#include <functional>
#include <ostream>
#include <ostream>
@@ -29,27 +29,42 @@


namespace aapt {
namespace aapt {


class Flags {
class Command {
 public:
 public:
  Flags& RequiredFlag(const android::StringPiece& name, const android::StringPiece& description,
  explicit Command(const android::StringPiece& name) : name_(name.to_string()),
                                                       fullname_(name.to_string()) { }
  explicit Command(const android::StringPiece& name, const android::StringPiece& short_name)
      : name_(name.to_string()), short_name_(short_name.to_string()), fullname_(name.to_string()) {}
  virtual ~Command() = default;

  void AddRequiredFlag(const android::StringPiece& name, const android::StringPiece& description,
      std::string* value);
      std::string* value);
  Flags& RequiredFlagList(const android::StringPiece& name, const android::StringPiece& description,
  void AddRequiredFlagList(const android::StringPiece& name, const android::StringPiece&
                          std::vector<std::string>* value);
      description, std::vector<std::string>* value);
  Flags& OptionalFlag(const android::StringPiece& name, const android::StringPiece& description,
  void AddOptionalFlag(const android::StringPiece& name, const android::StringPiece& description,
      Maybe<std::string>* value);
      Maybe<std::string>* value);
  Flags& OptionalFlagList(const android::StringPiece& name, const android::StringPiece& description,
  void AddOptionalFlagList(const android::StringPiece& name,
                          std::vector<std::string>* value);
      const android::StringPiece& description, std::vector<std::string>* value);
  Flags& OptionalFlagList(const android::StringPiece& name, const android::StringPiece& description,
  void AddOptionalFlagList(const android::StringPiece& name,
                          std::unordered_set<std::string>* value);
      const android::StringPiece& description, std::unordered_set<std::string>* value);
  Flags& OptionalSwitch(const android::StringPiece& name, const android::StringPiece& description,
  void AddOptionalSwitch(const android::StringPiece& name, const android::StringPiece& description,
      bool* value);
      bool* value);
  void AddOptionalSubcommand(std::unique_ptr<Command>&& subcommand);

  void SetDescription(const android::StringPiece& name);


  void Usage(const android::StringPiece& command, std::ostream* out);
  /** Prints the help menu of the command. */
  void Usage(std::ostream* out);


  bool Parse(const android::StringPiece& command, const std::vector<android::StringPiece>& args,
  /**
             std::ostream* outError);
   * Parses the command line arguments, sets the flag variable values, and runs the action of
   * the command. If the arguments fail to parse to the command and its subcommands, then the action
   * will not be run and the usage will be printed instead.
   **/
  int Execute(const std::vector<android::StringPiece>& args, std::ostream* outError);


  const std::vector<std::string>& GetArgs();
  /** The action to preform when the command is executed. */
  virtual int Action(const std::vector<std::string>& args) = 0;


 private:
 private:
  struct Flag {
  struct Flag {
@@ -62,10 +77,14 @@ class Flags {
    bool parsed;
    bool parsed;
  };
  };


  std::string description_;
  std::string name_;
  std::string short_name_;
  std::string fullname_;
  std::vector<Flag> flags_;
  std::vector<Flag> flags_;
  std::vector<std::string> args_;
  std::vector<std::unique_ptr<Command>> subcommands_;
};
};


}  // namespace aapt
}  // namespace aapt


#endif  // AAPT_FLAGS_H
#endif  // AAPT_COMMAND_H
+27 −67
Original line number Original line Diff line number Diff line
@@ -14,8 +14,9 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


#include <dirent.h>
#include "Compile.h"


#include <dirent.h>
#include <string>
#include <string>


#include "android-base/errors.h"
#include "android-base/errors.h"
@@ -27,7 +28,6 @@


#include "ConfigDescription.h"
#include "ConfigDescription.h"
#include "Diagnostics.h"
#include "Diagnostics.h"
#include "Flags.h"
#include "ResourceParser.h"
#include "ResourceParser.h"
#include "ResourceTable.h"
#include "ResourceTable.h"
#include "cmd/Util.h"
#include "cmd/Util.h"
@@ -121,17 +121,6 @@ static Maybe<ResourcePathData> ExtractResourcePathData(const std::string& path,
                          extension.to_string(), config_str.to_string(), config};
                          extension.to_string(), config_str.to_string(), config};
}
}


struct CompileOptions {
  std::string output_path;
  Maybe<std::string> res_dir;
  Maybe<std::string> generate_text_symbols_path;
  Maybe<Visibility::Level> visibility;
  bool pseudolocalize = false;
  bool no_png_crunch = false;
  bool legacy_mode = false;
  bool verbose = false;
};

static std::string BuildIntermediateContainerFilename(const ResourcePathData& data) {
static std::string BuildIntermediateContainerFilename(const ResourcePathData& data) {
  std::stringstream name;
  std::stringstream name;
  name << data.resource_dir;
  name << data.resource_dir;
@@ -712,50 +701,21 @@ class CompileContext : public IAaptContext {
  bool verbose_ = false;
  bool verbose_ = false;
};
};


// Entry point for compilation phase. Parses arguments and dispatches to the correct steps.
int CompileCommand::Action(const std::vector<std::string>& args) {
int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {
  CompileContext context(diagnostic_);
  CompileContext context(diagnostics);
  context.SetVerbose(options_.verbose);
  CompileOptions options;


  if (visibility_) {
  bool verbose = false;
    if (visibility_.value() == "public") {
  Maybe<std::string> visibility;
      options_.visibility = Visibility::Level::kPublic;
  Flags flags =
    } else if (visibility_.value() == "private") {
      Flags()
      options_.visibility = Visibility::Level::kPrivate;
          .RequiredFlag("-o", "Output path", &options.output_path)
    } else if (visibility_.value() == "default") {
          .OptionalFlag("--dir", "Directory to scan for resources", &options.res_dir)
      options_.visibility = Visibility::Level::kUndefined;
          .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)",
                          &options.pseudolocalize)
          .OptionalSwitch("--no-crunch", "Disables PNG processing", &options.no_png_crunch)
          .OptionalSwitch("--legacy", "Treat errors that used to be valid in AAPT as warnings",
                          &options.legacy_mode)
          .OptionalSwitch("-v", "Enables verbose logging", &verbose)
          .OptionalFlag("--visibility",
                        "Sets the visibility of the compiled resources to the specified\n"
                        "level. Accepted levels: public, private, default",
                        &visibility);
  if (!flags.Parse("aapt2 compile", args, &std::cerr)) {
    return 1;
  }

  context.SetVerbose(verbose);

  if (visibility) {
    if (visibility.value() == "public") {
      options.visibility = Visibility::Level::kPublic;
    } else if (visibility.value() == "private") {
      options.visibility = Visibility::Level::kPrivate;
    } else if (visibility.value() == "default") {
      options.visibility = Visibility::Level::kUndefined;
    } else {
    } else {
      context.GetDiagnostics()->Error(
      context.GetDiagnostics()->Error(
          DiagMessage() << "Unrecognized visibility level passes to --visibility: '"
          DiagMessage() << "Unrecognized visibility level passes to --visibility: '"
                        << visibility.value() << "'. Accepted levels: public, private, default");
                        << visibility_.value() << "'. Accepted levels: public, private, default");
      return 1;
      return 1;
    }
    }
  }
  }
@@ -763,25 +723,25 @@ int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {
  std::unique_ptr<IArchiveWriter> archive_writer;
  std::unique_ptr<IArchiveWriter> archive_writer;


  std::vector<ResourcePathData> input_data;
  std::vector<ResourcePathData> input_data;
  if (options.res_dir) {
  if (options_.res_dir) {
    if (!flags.GetArgs().empty()) {
    if (!args.empty()) {
      // Can't have both files and a resource directory.
      // Can't have both files and a resource directory.
      context.GetDiagnostics()->Error(DiagMessage() << "files given but --dir specified");
      context.GetDiagnostics()->Error(DiagMessage() << "files given but --dir specified");
      flags.Usage("aapt2 compile", &std::cerr);
      Usage(&std::cerr);
      return 1;
      return 1;
    }
    }


    if (!LoadInputFilesFromDir(&context, options, &input_data)) {
    if (!LoadInputFilesFromDir(&context, options_, &input_data)) {
      return 1;
      return 1;
    }
    }


    archive_writer = CreateZipFileArchiveWriter(context.GetDiagnostics(), options.output_path);
    archive_writer = CreateZipFileArchiveWriter(context.GetDiagnostics(), options_.output_path);


  } else {
  } else {
    input_data.reserve(flags.GetArgs().size());
    input_data.reserve(args.size());


    // Collect data from the path for each input file.
    // Collect data from the path for each input file.
    for (const std::string& arg : flags.GetArgs()) {
    for (const std::string& arg : args) {
      std::string error_str;
      std::string error_str;
      if (Maybe<ResourcePathData> path_data = ExtractResourcePathData(arg, &error_str)) {
      if (Maybe<ResourcePathData> path_data = ExtractResourcePathData(arg, &error_str)) {
        input_data.push_back(std::move(path_data.value()));
        input_data.push_back(std::move(path_data.value()));
@@ -791,7 +751,7 @@ int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {
      }
      }
    }
    }


    archive_writer = CreateDirectoryArchiveWriter(context.GetDiagnostics(), options.output_path);
    archive_writer = CreateDirectoryArchiveWriter(context.GetDiagnostics(), options_.output_path);
  }
  }


  if (!archive_writer) {
  if (!archive_writer) {
@@ -800,7 +760,7 @@ int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {


  bool error = false;
  bool error = false;
  for (ResourcePathData& path_data : input_data) {
  for (ResourcePathData& path_data : input_data) {
    if (options.verbose) {
    if (options_.verbose) {
      context.GetDiagnostics()->Note(DiagMessage(path_data.source) << "processing");
      context.GetDiagnostics()->Note(DiagMessage(path_data.source) << "processing");
    }
    }


@@ -821,7 +781,7 @@ int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {
      if (*type != ResourceType::kRaw) {
      if (*type != ResourceType::kRaw) {
        if (path_data.extension == "xml") {
        if (path_data.extension == "xml") {
          compile_func = &CompileXml;
          compile_func = &CompileXml;
        } else if ((!options.no_png_crunch && path_data.extension == "png")
        } else if ((!options_.no_png_crunch && path_data.extension == "png")
            || path_data.extension == "9.png") {
            || path_data.extension == "9.png") {
          compile_func = &CompilePng;
          compile_func = &CompilePng;
        }
        }
@@ -835,7 +795,7 @@ int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {


    // Treat periods as a reserved character that should not be present in a file name
    // Treat periods as a reserved character that should not be present in a file name
    // Legacy support for AAPT which did not reserve periods
    // Legacy support for AAPT which did not reserve periods
    if (compile_func != &CompileFile && !options.legacy_mode
    if (compile_func != &CompileFile && !options_.legacy_mode
        && std::count(path_data.name.begin(), path_data.name.end(), '.') != 0) {
        && std::count(path_data.name.begin(), path_data.name.end(), '.') != 0) {
      error = true;
      error = true;
      context.GetDiagnostics()->Error(DiagMessage() << "resource file '" << path_data.source.path
      context.GetDiagnostics()->Error(DiagMessage() << "resource file '" << path_data.source.path
@@ -846,7 +806,7 @@ int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {


    // Compile the file.
    // Compile the file.
    const std::string out_path = BuildIntermediateContainerFilename(path_data);
    const std::string out_path = BuildIntermediateContainerFilename(path_data);
    error |= !compile_func(&context, options, path_data, archive_writer.get(), out_path);
    error |= !compile_func(&context, options_, path_data, archive_writer.get(), out_path);
  }
  }
  return error ? 1 : 0;
  return error ? 1 : 0;
}
}
Loading