static void dumpNinjaManifestText()

in lib/Commands/NinjaCommand.cpp [461:604]


static void dumpNinjaManifestText(StringRef file, ninja::Manifest* manifest) {
  // Dump the manifest.
  std::cout << "# Loaded Manifest: \"" << file.str() << "\"\n";
  std::cout << "\n";

  // Dump the top-level bindings.
  std::cout << "# Top-Level Bindings\n";
  assert(manifest->getRootScope().getParent() == nullptr);
  std::vector<std::pair<std::string, std::string>> bindings;
  for (const auto& entry: manifest->getRootScope().getBindings()) {
    bindings.push_back({ entry.getKey(), entry.getValue() });
  }
  std::sort(bindings.begin(), bindings.end());
  for (const auto& entry: bindings) {
    std::cout << entry.first << " = \""
              << util::escapedString(entry.second) << "\"\n";
  }
  std::cout << "\n";

  // Dump the pools, if present.
  if (!manifest->getPools().empty()) {
    std::cout << "# Pools\n";
    std::vector<ninja::Pool*> pools;
    for (const auto& entry: manifest->getPools()) {
      pools.push_back(entry.getValue());
    }
    std::sort(pools.begin(), pools.end(), [] (ninja::Pool* a, ninja::Pool* b) {
        return a->getName() < b->getName();
      });
    for (const auto& pool: pools) {
      // Write the rule entry.
      std::cout << "pool " << pool->getName() << "\n";
      if (uint32_t depth = pool->getDepth()) {
        std::cout << "  depth = " << depth << "\n";
      }
      std::cout << "\n";
    }
  }

  // Dump the rules.
  std::cout << "# Rules\n";
  std::vector<ninja::Rule*> rules;
  for (const auto& entry: manifest->getRootScope().getRules()) {
    rules.push_back(entry.getValue());
  }
  std::sort(rules.begin(), rules.end(), [] (ninja::Rule* a, ninja::Rule* b) {
      return a->getName() < b->getName();
    });
  for (const auto& rule: rules) {
    // Write the rule entry.
    std::cout << "rule " << rule->getName() << "\n";

    // Write the parameters.
    std::vector<std::pair<std::string, std::string>> parameters;
    for (const auto& entry: rule->getParameters()) {
        parameters.push_back({ entry.getKey(), entry.getValue() });
    }
    std::sort(parameters.begin(), parameters.end());
    for (const auto& entry: parameters) {
      std::cout << "  " << entry.first << " = \""
                << util::escapedString(entry.second) << "\"\n";
    }
    std::cout << "\n";
  }

  // Dump the commands.
  std::vector<ninja::Command*> commands(manifest->getCommands());
  std::sort(commands.begin(), commands.end(),
            [] (ninja::Command* a, ninja::Command* b) {
              // Commands can not have duplicate outputs, so comparing based
              // only on the first still provides a total ordering.
              return a->getOutputs()[0]->getScreenPath() <
                b->getOutputs()[0]->getScreenPath();
            });
  std::cout << "# Commands\n";
  for (const auto& command: commands) {
    // Write the command entry.
    std::cout << "build";
    for (const auto& node: command->getOutputs()) {
      std::cout << " \"" << util::escapedString(node->getScreenPath()) << "\"";
    }
    std::cout << ": " << command->getRule()->getName();
    unsigned count = 0;
    for (const auto& node: command->getInputs()) {
      std::cout << " ";
      if (count == (command->getNumExplicitInputs() +
                           command->getNumImplicitInputs())) {
        std::cout << "|| ";
      } else if (count == command->getNumExplicitInputs()) {
        std::cout << "| ";
      }
      std::cout << "\"" << util::escapedString(node->getScreenPath()) << "\"";
      ++count;
    }
    std::cout << "\n";

    // Write out the attributes.
    std::cout << "  command = \""
              << util::escapedString(command->getCommandString()) << "\"\n";
    std::cout << "  description = \""
              << util::escapedString(command->getDescription()) << "\"\n";

    switch (command->getDepsStyle()) {
    case ninja::Command::DepsStyleKind::None:
      break;
    case ninja::Command::DepsStyleKind::GCC:
      std::cout << "  deps = gcc\n";
      std::cout << "  depfile = \""
                << util::escapedString(command->getDepsFile()) << "\"\n";
      break;
    case ninja::Command::DepsStyleKind::MSVC:
      std::cout << "  deps = msvc\n";
      break;
    }
  
    if (command->hasGeneratorFlag())
      std::cout << "  generator = 1\n";
    if (command->hasRestatFlag())
      std::cout << "  restat = 1\n";

    if (const ninja::Pool* executionPool = command->getExecutionPool()) {
      std::cout << "  pool = " << executionPool->getName() << "\n";
    }

    std::cout << "\n";
  }

  // Dump the default targets, if specified.
  if (!manifest->getDefaultTargets().empty()) {
    std::cout << "# Default Targets\n";
    std::vector<ninja::Node*> defaultTargets = manifest->getDefaultTargets();
    std::sort(defaultTargets.begin(), defaultTargets.end(),
              [] (ninja::Node* a, ninja::Node* b) {
        return a->getScreenPath() < b->getScreenPath();
      });
    std::cout << "default ";
    for (const auto& node: defaultTargets) {
      if (node != defaultTargets[0])
        std::cout << " ";
      std::cout << "\"" << node->getScreenPath() << "\"";
    }
    std::cout << "\n\n";
  }
}