13551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
23551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
33551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// found in the LICENSE file.
43551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <map>
63551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <set>
73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/command_line.h"
93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/commands.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "tools/gn/deps_iterator.h"
113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/filesystem_utils.h"
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/input_file.h"
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/item.h"
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/setup.h"
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/standard_out.h"
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/target.h"
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace commands {
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace {
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitypedef std::set<const Target*> TargetSet;
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitypedef std::vector<const Target*> TargetVector;
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Maps targets to the list of targets that depend on them.
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitypedef std::multimap<const Target*, const Target*> DepMap;
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Populates the reverse dependency map for the targets in the Setup.
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid FillDepMap(Setup* setup, DepMap* dep_map) {
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::vector<const Target*> targets =
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      setup->builder()->GetAllResolvedTargets();
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (size_t target_i = 0; target_i < targets.size(); target_i++) {
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (DepsIterator iter(targets[target_i]); !iter.done(); iter.Advance())
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      dep_map->insert(std::make_pair(iter.target(), targets[target_i]));
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Returns the file path generating this item.
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibase::FilePath FilePathForItem(const Item* item) {
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return item->defined_from()->GetRange().begin().file()->physical_name();
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Prints the targets which are the result of a query. This list is sorted
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// and, if as_files is set, the unique filenames matching those targets will
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// be used.
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid OutputResultSet(const TargetSet& results, bool as_files) {
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (results.empty())
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (as_files) {
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Output the set of unique source files.
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::set<std::string> unique_files;
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (TargetSet::const_iterator iter = results.begin();
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci         iter != results.end(); ++iter)
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      unique_files.insert(FilePathToUTF8(FilePathForItem(*iter)));
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (std::set<std::string>::const_iterator iter = unique_files.begin();
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci         iter != unique_files.end(); ++iter) {
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      OutputString(*iter + "\n");
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Output sorted and uniquified list of labels. The set will sort the
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // labels.
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::set<Label> unique_labels;
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (TargetSet::const_iterator iter = results.begin();
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci         iter != results.end(); ++iter)
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      unique_labels.insert((*iter)->label());
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Grab the label of the default toolchain from a random target.
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Label default_tc_label =
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        (*results.begin())->settings()->default_toolchain_label();
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (std::set<Label>::const_iterator iter = unique_labels.begin();
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci         iter != unique_labels.end(); ++iter) {
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Print toolchain only for ones not in the default toolchain.
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      OutputString(iter->GetUserVisibleName(
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          iter->GetToolchainLabel() != default_tc_label));
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      OutputString("\n");
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Prints refs of the given target (not the target itself). If the set is
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// non-null, new targets encountered will be added to the set, and if a ref is
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// in the set already, it will not be recused into. When the set is null, all
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// refs will be printed.
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid RecursivePrintTree(const DepMap& dep_map,
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        const Target* target,
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        TargetSet* seen_targets,
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        int indent_level) {
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string indent(indent_level * 2, ' ');
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DepMap::const_iterator dep_begin = dep_map.lower_bound(target);
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DepMap::const_iterator dep_end = dep_map.upper_bound(target);
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (DepMap::const_iterator cur_dep = dep_begin;
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       cur_dep != dep_end; cur_dep++) {
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const Target* cur_target = cur_dep->second;
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Only print the toolchain for non-default-toolchain targets.
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    OutputString(indent + cur_target->label().GetUserVisibleName(
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        !cur_target->settings()->is_default()));
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool print_children = true;
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (seen_targets) {
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (seen_targets->find(cur_target) == seen_targets->end()) {
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // New target, mark it visited.
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        seen_targets->insert(cur_target);
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      } else {
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // Already seen.
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        print_children = false;
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // Only print "..." if something is actually elided, which means that
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // the current target has children.
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (dep_map.lower_bound(cur_target) != dep_map.upper_bound(cur_target))
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          OutputString("...");
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    OutputString("\n");
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (print_children)
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      RecursivePrintTree(dep_map, cur_target, seen_targets, indent_level + 1);
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid RecursiveCollectChildRefs(const DepMap& dep_map,
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               const Target* target,
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               TargetSet* results);
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Recursively finds all targets that reference the given one, and additionally
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// adds the current one to the list.
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid RecursiveCollectRefs(const DepMap& dep_map,
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          const Target* target,
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          TargetSet* results) {
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (results->find(target) != results->end())
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;  // Already found this target.
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  results->insert(target);
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  RecursiveCollectChildRefs(dep_map, target, results);
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Recursively finds all targets that reference the given one.
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid RecursiveCollectChildRefs(const DepMap& dep_map,
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               const Target* target,
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               TargetSet* results) {
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DepMap::const_iterator dep_begin = dep_map.lower_bound(target);
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DepMap::const_iterator dep_end = dep_map.upper_bound(target);
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (DepMap::const_iterator cur_dep = dep_begin;
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       cur_dep != dep_end; cur_dep++)
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    RecursiveCollectRefs(dep_map, cur_dep->second, results);
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace
1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char kRefs[] = "refs";
1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char kRefs_HelpShort[] =
1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "refs: Find stuff referencing a target, directory, or config.";
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char kRefs_Help[] =
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "gn refs <build_dir> <label_pattern> [--files] [--tree] [--all]\n"
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "        [--all-toolchains]\n"
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  Finds which targets reference a given target or targets (reverse\n"
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  dependencies).\n"
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "\n"
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  The <label_pattern> can take exact labels or patterns that match more\n"
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  than one (although not general regular expressions).\n"
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  See \"gn help label_pattern\" for details.\n"
1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  --all\n"
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      When used without --tree, will recurse and display all unique\n"
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      dependencies of the given targets. When used with --tree, turns\n"
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      off eliding to show a complete tree.\n"
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  --all-toolchains\n"
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      Make the label pattern matche all toolchains. If the label pattern\n"
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      does not specify an explicit toolchain, labels from all toolchains\n"
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      will be matched (normally only the default toolchain is matched\n"
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      when no toolchain is specified).\n"
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  --files\n"
1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "      Output unique filenames referencing a matched target or config.\n"
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      These will be relative to the source root directory such that they\n"
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      are suitable for piping to other commands.\n"
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  --tree\n"
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      Outputs a reverse dependency tree from the given target. The label\n"
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      pattern must match one target exactly. Duplicates will be elided.\n"
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      Combine with --all to see a full dependency tree.\n"
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "Examples\n"
1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  gn refs out/Debug //tools/gn:gn\n"
1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "      Find all targets depending on the given exact target name.\n"
1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  gn refs out/Debug //base:i18n --files | xargs gvim\n"
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      Edit all files containing references to //base:i18n\n"
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  gn refs out/Debug //base --all\n"
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      List all targets depending directly or indirectly on //base:base.\n"
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  gn refs out/Debug \"//base/*\"\n"
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      List all targets depending directly on any target in //base or\n"
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      its subdirectories.\n"
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  gn refs out/Debug \"//base:*\"\n"
2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      List all targets depending directly on any target in\n"
2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      //base/BUILD.gn.\n"
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  gn refs out/Debug //base --tree\n"
2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      Print a reverse dependency tree of //base:base\n";
2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int RunRefs(const std::vector<std::string>& args) {
2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (args.size() != 2) {
2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    Err(Location(), "You're holding it wrong.",
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "Usage: \"gn refs <build_dir> <label_pattern>\"").PrintToStdout();
2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return 1;
2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const CommandLine* cmdline = CommandLine::ForCurrentProcess();
2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool tree = cmdline->HasSwitch("tree");
2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool all = cmdline->HasSwitch("all");
2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool all_toolchains = cmdline->HasSwitch("all-toolchains");
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool files = cmdline->HasSwitch("files");
2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Setup* setup = new Setup;
2243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  setup->set_check_for_bad_items(false);
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!setup->DoSetup(args[0], false) || !setup->Run())
2263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return 1;
2273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Figure out the target or targets that the user is querying.
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::vector<const Target*> query;
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!ResolveTargetsFromCommandLinePattern(setup, args[1], all_toolchains,
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                            &query))
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return 1;
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (query.empty()) {
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    OutputString("\"" + args[1] + "\" matches no targets.\n");
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return 0;
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Construct the reverse dependency tree.
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DepMap dep_map;
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  FillDepMap(setup, &dep_map);
2413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (tree) {
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Output dependency tree.
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (files) {
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      Err(NULL, "--files option can't be used with --tree option.")
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          .PrintToStdout();
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return 1;
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (query.size() != 1) {
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      Err(NULL, "Query matches more than one target.",
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          "--tree only supports a single target as input.").PrintToStdout();
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return 1;
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (all) {
2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Recursively print all targets.
2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      RecursivePrintTree(dep_map, query[0], NULL, 0);
2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    } else {
2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Recursively print unique targets.
2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      TargetSet seen_targets;
2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      RecursivePrintTree(dep_map, query[0], &seen_targets, 0);
2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else if (all) {
2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Output recursive dependencies, uniquified and flattened.
2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    TargetSet results;
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (size_t query_i = 0; query_i < query.size(); query_i++)
2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      RecursiveCollectChildRefs(dep_map, query[query_i], &results);
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    OutputResultSet(results, files);
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Output direct references of everything in the query.
2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    TargetSet results;
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (size_t query_i = 0; query_i < query.size(); query_i++) {
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      DepMap::const_iterator dep_begin = dep_map.lower_bound(query[query_i]);
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      DepMap::const_iterator dep_end = dep_map.upper_bound(query[query_i]);
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      for (DepMap::const_iterator cur_dep = dep_begin;
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci           cur_dep != dep_end; cur_dep++)
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        results.insert(cur_dep->second);
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    OutputResultSet(results, files);
2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace commands
285