16d528ed9Sopenharmony_ci// Copyright (c) 2013 The Chromium Authors. All rights reserved.
26d528ed9Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
36d528ed9Sopenharmony_ci// found in the LICENSE file.
46d528ed9Sopenharmony_ci
56d528ed9Sopenharmony_ci#include <stddef.h>
66d528ed9Sopenharmony_ci
76d528ed9Sopenharmony_ci#include <map>
86d528ed9Sopenharmony_ci#include <set>
96d528ed9Sopenharmony_ci
106d528ed9Sopenharmony_ci#include "base/command_line.h"
116d528ed9Sopenharmony_ci#include "base/files/file_util.h"
126d528ed9Sopenharmony_ci#include "base/strings/string_split.h"
136d528ed9Sopenharmony_ci#include "base/strings/string_util.h"
146d528ed9Sopenharmony_ci#include "gn/commands.h"
156d528ed9Sopenharmony_ci#include "gn/config_values_extractors.h"
166d528ed9Sopenharmony_ci#include "gn/deps_iterator.h"
176d528ed9Sopenharmony_ci#include "gn/filesystem_utils.h"
186d528ed9Sopenharmony_ci#include "gn/input_file.h"
196d528ed9Sopenharmony_ci#include "gn/item.h"
206d528ed9Sopenharmony_ci#include "gn/setup.h"
216d528ed9Sopenharmony_ci#include "gn/standard_out.h"
226d528ed9Sopenharmony_ci#include "gn/switches.h"
236d528ed9Sopenharmony_ci#include "gn/target.h"
246d528ed9Sopenharmony_ci
256d528ed9Sopenharmony_cinamespace commands {
266d528ed9Sopenharmony_ci
276d528ed9Sopenharmony_cinamespace {
286d528ed9Sopenharmony_ci
296d528ed9Sopenharmony_ciusing TargetSet = TargetSet;
306d528ed9Sopenharmony_ciusing TargetVector = std::vector<const Target*>;
316d528ed9Sopenharmony_ci
326d528ed9Sopenharmony_ci// Maps targets to the list of targets that depend on them.
336d528ed9Sopenharmony_ciusing DepMap = std::multimap<const Target*, const Target*>;
346d528ed9Sopenharmony_ci
356d528ed9Sopenharmony_ci// Populates the reverse dependency map for the targets in the Setup.
366d528ed9Sopenharmony_civoid FillDepMap(Setup* setup, DepMap* dep_map) {
376d528ed9Sopenharmony_ci  for (auto* target : setup->builder().GetAllResolvedTargets()) {
386d528ed9Sopenharmony_ci    for (const auto& dep_pair : target->GetDeps(Target::DEPS_ALL))
396d528ed9Sopenharmony_ci      dep_map->insert(std::make_pair(dep_pair.ptr, target));
406d528ed9Sopenharmony_ci  }
416d528ed9Sopenharmony_ci}
426d528ed9Sopenharmony_ci
436d528ed9Sopenharmony_ci// Forward declaration for function below.
446d528ed9Sopenharmony_cisize_t RecursivePrintTargetDeps(const DepMap& dep_map,
456d528ed9Sopenharmony_ci                                const Target* target,
466d528ed9Sopenharmony_ci                                TargetSet* seen_targets,
476d528ed9Sopenharmony_ci                                int indent_level);
486d528ed9Sopenharmony_ci
496d528ed9Sopenharmony_ci// Prints the target and its dependencies in tree form. If the set is non-null,
506d528ed9Sopenharmony_ci// new targets encountered will be added to the set, and if a ref is in the set
516d528ed9Sopenharmony_ci// already, it will not be recused into. When the set is null, all refs will be
526d528ed9Sopenharmony_ci// printed.
536d528ed9Sopenharmony_ci//
546d528ed9Sopenharmony_ci// Returns the number of items printed.
556d528ed9Sopenharmony_cisize_t RecursivePrintTarget(const DepMap& dep_map,
566d528ed9Sopenharmony_ci                            const Target* target,
576d528ed9Sopenharmony_ci                            TargetSet* seen_targets,
586d528ed9Sopenharmony_ci                            int indent_level) {
596d528ed9Sopenharmony_ci  std::string indent(indent_level * 2, ' ');
606d528ed9Sopenharmony_ci  size_t count = 1;
616d528ed9Sopenharmony_ci
626d528ed9Sopenharmony_ci  // Only print the toolchain for non-default-toolchain targets.
636d528ed9Sopenharmony_ci  OutputString(indent + target->label().GetUserVisibleName(
646d528ed9Sopenharmony_ci                            !target->settings()->is_default()));
656d528ed9Sopenharmony_ci
666d528ed9Sopenharmony_ci  bool print_children = true;
676d528ed9Sopenharmony_ci  if (seen_targets) {
686d528ed9Sopenharmony_ci    if (!seen_targets->add(target)) {
696d528ed9Sopenharmony_ci      // Already seen.
706d528ed9Sopenharmony_ci      print_children = false;
716d528ed9Sopenharmony_ci      // Only print "..." if something is actually elided, which means that
726d528ed9Sopenharmony_ci      // the current target has children.
736d528ed9Sopenharmony_ci      if (dep_map.lower_bound(target) != dep_map.upper_bound(target))
746d528ed9Sopenharmony_ci        OutputString("...");
756d528ed9Sopenharmony_ci    }
766d528ed9Sopenharmony_ci  }
776d528ed9Sopenharmony_ci
786d528ed9Sopenharmony_ci  OutputString("\n");
796d528ed9Sopenharmony_ci  if (print_children) {
806d528ed9Sopenharmony_ci    count += RecursivePrintTargetDeps(dep_map, target, seen_targets,
816d528ed9Sopenharmony_ci                                      indent_level + 1);
826d528ed9Sopenharmony_ci  }
836d528ed9Sopenharmony_ci  return count;
846d528ed9Sopenharmony_ci}
856d528ed9Sopenharmony_ci
866d528ed9Sopenharmony_ci// Prints refs of the given target (not the target itself). See
876d528ed9Sopenharmony_ci// RecursivePrintTarget.
886d528ed9Sopenharmony_cisize_t RecursivePrintTargetDeps(const DepMap& dep_map,
896d528ed9Sopenharmony_ci                                const Target* target,
906d528ed9Sopenharmony_ci                                TargetSet* seen_targets,
916d528ed9Sopenharmony_ci                                int indent_level) {
926d528ed9Sopenharmony_ci  DepMap::const_iterator dep_begin = dep_map.lower_bound(target);
936d528ed9Sopenharmony_ci  DepMap::const_iterator dep_end = dep_map.upper_bound(target);
946d528ed9Sopenharmony_ci  size_t count = 0;
956d528ed9Sopenharmony_ci  for (DepMap::const_iterator cur_dep = dep_begin; cur_dep != dep_end;
966d528ed9Sopenharmony_ci       cur_dep++) {
976d528ed9Sopenharmony_ci    count += RecursivePrintTarget(dep_map, cur_dep->second, seen_targets,
986d528ed9Sopenharmony_ci                                  indent_level);
996d528ed9Sopenharmony_ci  }
1006d528ed9Sopenharmony_ci  return count;
1016d528ed9Sopenharmony_ci}
1026d528ed9Sopenharmony_ci
1036d528ed9Sopenharmony_civoid RecursiveCollectChildRefs(const DepMap& dep_map,
1046d528ed9Sopenharmony_ci                               const Target* target,
1056d528ed9Sopenharmony_ci                               TargetSet* results);
1066d528ed9Sopenharmony_ci
1076d528ed9Sopenharmony_ci// Recursively finds all targets that reference the given one, and additionally
1086d528ed9Sopenharmony_ci// adds the current one to the list.
1096d528ed9Sopenharmony_civoid RecursiveCollectRefs(const DepMap& dep_map,
1106d528ed9Sopenharmony_ci                          const Target* target,
1116d528ed9Sopenharmony_ci                          TargetSet* results) {
1126d528ed9Sopenharmony_ci  if (!results->add(target))
1136d528ed9Sopenharmony_ci    return;  // Already found this target.
1146d528ed9Sopenharmony_ci  RecursiveCollectChildRefs(dep_map, target, results);
1156d528ed9Sopenharmony_ci}
1166d528ed9Sopenharmony_ci
1176d528ed9Sopenharmony_ci// Recursively finds all targets that reference the given one.
1186d528ed9Sopenharmony_civoid RecursiveCollectChildRefs(const DepMap& dep_map,
1196d528ed9Sopenharmony_ci                               const Target* target,
1206d528ed9Sopenharmony_ci                               TargetSet* results) {
1216d528ed9Sopenharmony_ci  DepMap::const_iterator dep_begin = dep_map.lower_bound(target);
1226d528ed9Sopenharmony_ci  DepMap::const_iterator dep_end = dep_map.upper_bound(target);
1236d528ed9Sopenharmony_ci  for (DepMap::const_iterator cur_dep = dep_begin; cur_dep != dep_end;
1246d528ed9Sopenharmony_ci       cur_dep++)
1256d528ed9Sopenharmony_ci    RecursiveCollectRefs(dep_map, cur_dep->second, results);
1266d528ed9Sopenharmony_ci}
1276d528ed9Sopenharmony_ci
1286d528ed9Sopenharmony_cibool TargetReferencesConfig(const Target* target, const Config* config) {
1296d528ed9Sopenharmony_ci  for (const LabelConfigPair& cur : target->configs()) {
1306d528ed9Sopenharmony_ci    if (cur.ptr == config)
1316d528ed9Sopenharmony_ci      return true;
1326d528ed9Sopenharmony_ci  }
1336d528ed9Sopenharmony_ci  for (const LabelConfigPair& cur : target->public_configs()) {
1346d528ed9Sopenharmony_ci    if (cur.ptr == config)
1356d528ed9Sopenharmony_ci      return true;
1366d528ed9Sopenharmony_ci  }
1376d528ed9Sopenharmony_ci  return false;
1386d528ed9Sopenharmony_ci}
1396d528ed9Sopenharmony_ci
1406d528ed9Sopenharmony_civoid GetTargetsReferencingConfig(Setup* setup,
1416d528ed9Sopenharmony_ci                                 const std::vector<const Target*>& all_targets,
1426d528ed9Sopenharmony_ci                                 const Config* config,
1436d528ed9Sopenharmony_ci                                 bool default_toolchain_only,
1446d528ed9Sopenharmony_ci                                 UniqueVector<const Target*>* matches) {
1456d528ed9Sopenharmony_ci  Label default_toolchain = setup->loader()->default_toolchain_label();
1466d528ed9Sopenharmony_ci  for (auto* target : all_targets) {
1476d528ed9Sopenharmony_ci    if (default_toolchain_only) {
1486d528ed9Sopenharmony_ci      // Only check targets in the default toolchain.
1496d528ed9Sopenharmony_ci      if (target->label().GetToolchainLabel() != default_toolchain)
1506d528ed9Sopenharmony_ci        continue;
1516d528ed9Sopenharmony_ci    }
1526d528ed9Sopenharmony_ci    if (TargetReferencesConfig(target, config))
1536d528ed9Sopenharmony_ci      matches->push_back(target);
1546d528ed9Sopenharmony_ci  }
1556d528ed9Sopenharmony_ci}
1566d528ed9Sopenharmony_ci
1576d528ed9Sopenharmony_ci// Returns the number of matches printed.
1586d528ed9Sopenharmony_cisize_t DoTreeOutput(const DepMap& dep_map,
1596d528ed9Sopenharmony_ci                    const UniqueVector<const Target*>& implicit_target_matches,
1606d528ed9Sopenharmony_ci                    const UniqueVector<const Target*>& explicit_target_matches,
1616d528ed9Sopenharmony_ci                    bool all) {
1626d528ed9Sopenharmony_ci  TargetSet seen_targets;
1636d528ed9Sopenharmony_ci  size_t count = 0;
1646d528ed9Sopenharmony_ci
1656d528ed9Sopenharmony_ci  // Implicit targets don't get printed themselves.
1666d528ed9Sopenharmony_ci  for (const Target* target : implicit_target_matches) {
1676d528ed9Sopenharmony_ci    if (all)
1686d528ed9Sopenharmony_ci      count += RecursivePrintTargetDeps(dep_map, target, nullptr, 0);
1696d528ed9Sopenharmony_ci    else
1706d528ed9Sopenharmony_ci      count += RecursivePrintTargetDeps(dep_map, target, &seen_targets, 0);
1716d528ed9Sopenharmony_ci  }
1726d528ed9Sopenharmony_ci
1736d528ed9Sopenharmony_ci  // Explicit targets appear in the output.
1746d528ed9Sopenharmony_ci  for (const Target* target : implicit_target_matches) {
1756d528ed9Sopenharmony_ci    if (all)
1766d528ed9Sopenharmony_ci      count += RecursivePrintTarget(dep_map, target, nullptr, 0);
1776d528ed9Sopenharmony_ci    else
1786d528ed9Sopenharmony_ci      count += RecursivePrintTarget(dep_map, target, &seen_targets, 0);
1796d528ed9Sopenharmony_ci  }
1806d528ed9Sopenharmony_ci
1816d528ed9Sopenharmony_ci  return count;
1826d528ed9Sopenharmony_ci}
1836d528ed9Sopenharmony_ci
1846d528ed9Sopenharmony_ci// Returns the number of matches printed.
1856d528ed9Sopenharmony_cisize_t DoAllListOutput(
1866d528ed9Sopenharmony_ci    const DepMap& dep_map,
1876d528ed9Sopenharmony_ci    const UniqueVector<const Target*>& implicit_target_matches,
1886d528ed9Sopenharmony_ci    const UniqueVector<const Target*>& explicit_target_matches) {
1896d528ed9Sopenharmony_ci  // Output recursive dependencies, uniquified and flattened.
1906d528ed9Sopenharmony_ci  TargetSet results;
1916d528ed9Sopenharmony_ci
1926d528ed9Sopenharmony_ci  for (const Target* target : implicit_target_matches)
1936d528ed9Sopenharmony_ci    RecursiveCollectChildRefs(dep_map, target, &results);
1946d528ed9Sopenharmony_ci  for (const Target* target : explicit_target_matches) {
1956d528ed9Sopenharmony_ci    // Explicit targets also get added to the output themselves.
1966d528ed9Sopenharmony_ci    results.insert(target);
1976d528ed9Sopenharmony_ci    RecursiveCollectChildRefs(dep_map, target, &results);
1986d528ed9Sopenharmony_ci  }
1996d528ed9Sopenharmony_ci
2006d528ed9Sopenharmony_ci  FilterAndPrintTargetSet(false, results);
2016d528ed9Sopenharmony_ci  return results.size();
2026d528ed9Sopenharmony_ci}
2036d528ed9Sopenharmony_ci
2046d528ed9Sopenharmony_ci// Returns the number of matches printed.
2056d528ed9Sopenharmony_cisize_t DoDirectListOutput(
2066d528ed9Sopenharmony_ci    const DepMap& dep_map,
2076d528ed9Sopenharmony_ci    const UniqueVector<const Target*>& implicit_target_matches,
2086d528ed9Sopenharmony_ci    const UniqueVector<const Target*>& explicit_target_matches) {
2096d528ed9Sopenharmony_ci  TargetSet results;
2106d528ed9Sopenharmony_ci
2116d528ed9Sopenharmony_ci  // Output everything that refers to the implicit ones.
2126d528ed9Sopenharmony_ci  for (const Target* target : implicit_target_matches) {
2136d528ed9Sopenharmony_ci    DepMap::const_iterator dep_begin = dep_map.lower_bound(target);
2146d528ed9Sopenharmony_ci    DepMap::const_iterator dep_end = dep_map.upper_bound(target);
2156d528ed9Sopenharmony_ci    for (DepMap::const_iterator cur_dep = dep_begin; cur_dep != dep_end;
2166d528ed9Sopenharmony_ci         cur_dep++)
2176d528ed9Sopenharmony_ci      results.insert(cur_dep->second);
2186d528ed9Sopenharmony_ci  }
2196d528ed9Sopenharmony_ci
2206d528ed9Sopenharmony_ci  // And just output the explicit ones directly (these are the target matches
2216d528ed9Sopenharmony_ci  // when referring to what references a file or config).
2226d528ed9Sopenharmony_ci  for (const Target* target : explicit_target_matches)
2236d528ed9Sopenharmony_ci    results.insert(target);
2246d528ed9Sopenharmony_ci
2256d528ed9Sopenharmony_ci  FilterAndPrintTargetSet(false, results);
2266d528ed9Sopenharmony_ci  return results.size();
2276d528ed9Sopenharmony_ci}
2286d528ed9Sopenharmony_ci
2296d528ed9Sopenharmony_ci}  // namespace
2306d528ed9Sopenharmony_ci
2316d528ed9Sopenharmony_ciconst char kRefs[] = "refs";
2326d528ed9Sopenharmony_ciconst char kRefs_HelpShort[] = "refs: Find stuff referencing a target or file.";
2336d528ed9Sopenharmony_ciconst char kRefs_Help[] =
2346d528ed9Sopenharmony_ci    R"(gn refs
2356d528ed9Sopenharmony_ci
2366d528ed9Sopenharmony_ci  gn refs <out_dir> (<label_pattern>|<label>|<file>|@<response_file>)* [--all]
2376d528ed9Sopenharmony_ci          [--default-toolchain] [--as=...] [--testonly=...] [--type=...]
2386d528ed9Sopenharmony_ci
2396d528ed9Sopenharmony_ci  Finds reverse dependencies (which targets reference something). The input is
2406d528ed9Sopenharmony_ci  a list containing:
2416d528ed9Sopenharmony_ci
2426d528ed9Sopenharmony_ci   - Target label: The result will be which targets depend on it.
2436d528ed9Sopenharmony_ci
2446d528ed9Sopenharmony_ci   - Config label: The result will be which targets list the given config in
2456d528ed9Sopenharmony_ci     its "configs" or "public_configs" list.
2466d528ed9Sopenharmony_ci
2476d528ed9Sopenharmony_ci   - Label pattern: The result will be which targets depend on any target
2486d528ed9Sopenharmony_ci     matching the given pattern. Patterns will not match configs. These are not
2496d528ed9Sopenharmony_ci     general regular expressions, see "gn help label_pattern" for details.
2506d528ed9Sopenharmony_ci
2516d528ed9Sopenharmony_ci   - File name: The result will be which targets list the given file in its
2526d528ed9Sopenharmony_ci     "inputs", "sources", "public", "data", or "outputs". Any input that does
2536d528ed9Sopenharmony_ci     not contain wildcards and does not match a target or a config will be
2546d528ed9Sopenharmony_ci     treated as a file.
2556d528ed9Sopenharmony_ci
2566d528ed9Sopenharmony_ci   - Response file: If the input starts with an "@", it will be interpreted as
2576d528ed9Sopenharmony_ci     a path to a file containing a list of labels or file names, one per line.
2586d528ed9Sopenharmony_ci     This allows us to handle long lists of inputs without worrying about
2596d528ed9Sopenharmony_ci     command line limits.
2606d528ed9Sopenharmony_ci
2616d528ed9Sopenharmony_ciOptions
2626d528ed9Sopenharmony_ci
2636d528ed9Sopenharmony_ci  --all
2646d528ed9Sopenharmony_ci      When used without --tree, will recurse and display all unique
2656d528ed9Sopenharmony_ci      dependencies of the given targets. For example, if the input is a target,
2666d528ed9Sopenharmony_ci      this will output all targets that depend directly or indirectly on the
2676d528ed9Sopenharmony_ci      input. If the input is a file, this will output all targets that depend
2686d528ed9Sopenharmony_ci      directly or indirectly on that file.
2696d528ed9Sopenharmony_ci
2706d528ed9Sopenharmony_ci      When used with --tree, turns off eliding to show a complete tree.
2716d528ed9Sopenharmony_ci
2726d528ed9Sopenharmony_ci)"
2736d528ed9Sopenharmony_ci
2746d528ed9Sopenharmony_ci    TARGET_PRINTING_MODE_COMMAND_LINE_HELP "\n" DEFAULT_TOOLCHAIN_SWITCH_HELP
2756d528ed9Sopenharmony_ci
2766d528ed9Sopenharmony_ci    R"(
2776d528ed9Sopenharmony_ci  -q
2786d528ed9Sopenharmony_ci     Quiet. If nothing matches, don't print any output. Without this option, if
2796d528ed9Sopenharmony_ci     there are no matches there will be an informational message printed which
2806d528ed9Sopenharmony_ci     might interfere with scripts processing the output.
2816d528ed9Sopenharmony_ci
2826d528ed9Sopenharmony_ci)"
2836d528ed9Sopenharmony_ci
2846d528ed9Sopenharmony_ci    TARGET_TESTONLY_FILTER_COMMAND_LINE_HELP
2856d528ed9Sopenharmony_ci
2866d528ed9Sopenharmony_ci    R"(
2876d528ed9Sopenharmony_ci  --tree
2886d528ed9Sopenharmony_ci      Outputs a reverse dependency tree from the given target. Duplicates will
2896d528ed9Sopenharmony_ci      be elided. Combine with --all to see a full dependency tree.
2906d528ed9Sopenharmony_ci
2916d528ed9Sopenharmony_ci      Tree output can not be used with the filtering or output flags: --as,
2926d528ed9Sopenharmony_ci      --type, --testonly.
2936d528ed9Sopenharmony_ci
2946d528ed9Sopenharmony_ci)"
2956d528ed9Sopenharmony_ci
2966d528ed9Sopenharmony_ci    TARGET_TYPE_FILTER_COMMAND_LINE_HELP
2976d528ed9Sopenharmony_ci
2986d528ed9Sopenharmony_ci    R"(
2996d528ed9Sopenharmony_ci
3006d528ed9Sopenharmony_ciExamples (target input)
3016d528ed9Sopenharmony_ci
3026d528ed9Sopenharmony_ci  gn refs out/Debug //gn:gn
3036d528ed9Sopenharmony_ci      Find all targets depending on the given exact target name.
3046d528ed9Sopenharmony_ci
3056d528ed9Sopenharmony_ci  gn refs out/Debug //base:i18n --as=buildfile | xargs gvim
3066d528ed9Sopenharmony_ci      Edit all .gn files containing references to //base:i18n
3076d528ed9Sopenharmony_ci
3086d528ed9Sopenharmony_ci  gn refs out/Debug //base --all
3096d528ed9Sopenharmony_ci      List all targets depending directly or indirectly on //base:base.
3106d528ed9Sopenharmony_ci
3116d528ed9Sopenharmony_ci  gn refs out/Debug "//base/*"
3126d528ed9Sopenharmony_ci      List all targets depending directly on any target in //base or
3136d528ed9Sopenharmony_ci      its subdirectories.
3146d528ed9Sopenharmony_ci
3156d528ed9Sopenharmony_ci  gn refs out/Debug "//base:*"
3166d528ed9Sopenharmony_ci      List all targets depending directly on any target in
3176d528ed9Sopenharmony_ci      //base/BUILD.gn.
3186d528ed9Sopenharmony_ci
3196d528ed9Sopenharmony_ci  gn refs out/Debug //base --tree
3206d528ed9Sopenharmony_ci      Print a reverse dependency tree of //base:base
3216d528ed9Sopenharmony_ci
3226d528ed9Sopenharmony_ciExamples (file input)
3236d528ed9Sopenharmony_ci
3246d528ed9Sopenharmony_ci  gn refs out/Debug //base/macros.h
3256d528ed9Sopenharmony_ci      Print target(s) listing //base/macros.h as a source.
3266d528ed9Sopenharmony_ci
3276d528ed9Sopenharmony_ci  gn refs out/Debug //base/macros.h --tree
3286d528ed9Sopenharmony_ci      Display a reverse dependency tree to get to the given file. This
3296d528ed9Sopenharmony_ci      will show how dependencies will reference that file.
3306d528ed9Sopenharmony_ci
3316d528ed9Sopenharmony_ci  gn refs out/Debug //base/macros.h //base/at_exit.h --all
3326d528ed9Sopenharmony_ci      Display all unique targets with some dependency path to a target
3336d528ed9Sopenharmony_ci      containing either of the given files as a source.
3346d528ed9Sopenharmony_ci
3356d528ed9Sopenharmony_ci  gn refs out/Debug //base/macros.h --testonly=true --type=executable
3366d528ed9Sopenharmony_ci          --all --as=output
3376d528ed9Sopenharmony_ci      Display the executable file names of all test executables
3386d528ed9Sopenharmony_ci      potentially affected by a change to the given file.
3396d528ed9Sopenharmony_ci)";
3406d528ed9Sopenharmony_ci
3416d528ed9Sopenharmony_ciint RunRefs(const std::vector<std::string>& args) {
3426d528ed9Sopenharmony_ci  if (args.size() <= 1) {
3436d528ed9Sopenharmony_ci    Err(Location(), "Unknown command format. See \"gn help refs\"",
3446d528ed9Sopenharmony_ci        "Usage: \"gn refs <out_dir> (<label_pattern>|<file>)*\"")
3456d528ed9Sopenharmony_ci        .PrintToStdout();
3466d528ed9Sopenharmony_ci    return 1;
3476d528ed9Sopenharmony_ci  }
3486d528ed9Sopenharmony_ci
3496d528ed9Sopenharmony_ci  const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
3506d528ed9Sopenharmony_ci  bool tree = cmdline->HasSwitch("tree");
3516d528ed9Sopenharmony_ci  bool all = cmdline->HasSwitch("all");
3526d528ed9Sopenharmony_ci  bool default_toolchain_only = cmdline->HasSwitch(switches::kDefaultToolchain);
3536d528ed9Sopenharmony_ci
3546d528ed9Sopenharmony_ci  // Deliberately leaked to avoid expensive process teardown.
3556d528ed9Sopenharmony_ci  Setup* setup = new Setup;
3566d528ed9Sopenharmony_ci  if (!setup->DoSetup(args[0], false) || !setup->Run())
3576d528ed9Sopenharmony_ci    return 1;
3586d528ed9Sopenharmony_ci
3596d528ed9Sopenharmony_ci  // The inputs are everything but the first arg (which is the build dir).
3606d528ed9Sopenharmony_ci  std::vector<std::string> inputs;
3616d528ed9Sopenharmony_ci  for (size_t i = 1; i < args.size(); i++) {
3626d528ed9Sopenharmony_ci    if (args[i][0] == '@') {
3636d528ed9Sopenharmony_ci      // The argument is as a path to a response file.
3646d528ed9Sopenharmony_ci      std::string contents;
3656d528ed9Sopenharmony_ci      bool ret =
3666d528ed9Sopenharmony_ci          base::ReadFileToString(UTF8ToFilePath(args[i].substr(1)), &contents);
3676d528ed9Sopenharmony_ci      if (!ret) {
3686d528ed9Sopenharmony_ci        Err(Location(), "Response file " + args[i].substr(1) + " not found.")
3696d528ed9Sopenharmony_ci            .PrintToStdout();
3706d528ed9Sopenharmony_ci        return 1;
3716d528ed9Sopenharmony_ci      }
3726d528ed9Sopenharmony_ci      for (const std::string& line : base::SplitString(
3736d528ed9Sopenharmony_ci               contents, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
3746d528ed9Sopenharmony_ci        if (!line.empty())
3756d528ed9Sopenharmony_ci          inputs.push_back(line);
3766d528ed9Sopenharmony_ci      }
3776d528ed9Sopenharmony_ci    } else {
3786d528ed9Sopenharmony_ci      // The argument is a label or a path.
3796d528ed9Sopenharmony_ci      inputs.push_back(args[i]);
3806d528ed9Sopenharmony_ci    }
3816d528ed9Sopenharmony_ci  }
3826d528ed9Sopenharmony_ci
3836d528ed9Sopenharmony_ci  // Get the matches for the command-line input.
3846d528ed9Sopenharmony_ci  UniqueVector<const Target*> target_matches;
3856d528ed9Sopenharmony_ci  UniqueVector<const Config*> config_matches;
3866d528ed9Sopenharmony_ci  UniqueVector<const Toolchain*> toolchain_matches;
3876d528ed9Sopenharmony_ci  UniqueVector<SourceFile> file_matches;
3886d528ed9Sopenharmony_ci  if (!ResolveFromCommandLineInput(setup, inputs, default_toolchain_only,
3896d528ed9Sopenharmony_ci                                   &target_matches, &config_matches,
3906d528ed9Sopenharmony_ci                                   &toolchain_matches, &file_matches))
3916d528ed9Sopenharmony_ci    return 1;
3926d528ed9Sopenharmony_ci
3936d528ed9Sopenharmony_ci  // When you give a file or config as an input, you want the targets that are
3946d528ed9Sopenharmony_ci  // associated with it. We don't want to just append this to the
3956d528ed9Sopenharmony_ci  // target_matches, however, since these targets should actually be listed in
3966d528ed9Sopenharmony_ci  // the output, while for normal targets you don't want to see the inputs,
3976d528ed9Sopenharmony_ci  // only what refers to them.
3986d528ed9Sopenharmony_ci  std::vector<const Target*> all_targets =
3996d528ed9Sopenharmony_ci      setup->builder().GetAllResolvedTargets();
4006d528ed9Sopenharmony_ci  UniqueVector<const Target*> explicit_target_matches;
4016d528ed9Sopenharmony_ci  for (const auto& file : file_matches) {
4026d528ed9Sopenharmony_ci    std::vector<TargetContainingFile> target_containing;
4036d528ed9Sopenharmony_ci    GetTargetsContainingFile(setup, all_targets, file, default_toolchain_only,
4046d528ed9Sopenharmony_ci                             &target_containing);
4056d528ed9Sopenharmony_ci
4066d528ed9Sopenharmony_ci    // Extract just the Target*.
4076d528ed9Sopenharmony_ci    for (const TargetContainingFile& pair : target_containing)
4086d528ed9Sopenharmony_ci      explicit_target_matches.push_back(pair.first);
4096d528ed9Sopenharmony_ci  }
4106d528ed9Sopenharmony_ci  for (auto* config : config_matches) {
4116d528ed9Sopenharmony_ci    GetTargetsReferencingConfig(setup, all_targets, config,
4126d528ed9Sopenharmony_ci                                default_toolchain_only,
4136d528ed9Sopenharmony_ci                                &explicit_target_matches);
4146d528ed9Sopenharmony_ci  }
4156d528ed9Sopenharmony_ci
4166d528ed9Sopenharmony_ci  // Tell the user if their input matches no files or labels. We need to check
4176d528ed9Sopenharmony_ci  // both that it matched no targets and no configs. File input will already
4186d528ed9Sopenharmony_ci  // have been converted to targets at this point. Configs will have been
4196d528ed9Sopenharmony_ci  // converted to targets also, but there could be no targets referencing the
4206d528ed9Sopenharmony_ci  // config, which is different than no config with that name.
4216d528ed9Sopenharmony_ci  bool quiet = cmdline->HasSwitch("q");
4226d528ed9Sopenharmony_ci  if (!quiet && config_matches.empty() && explicit_target_matches.empty() &&
4236d528ed9Sopenharmony_ci      target_matches.empty()) {
4246d528ed9Sopenharmony_ci    OutputString("The input matches no targets, configs, or files.\n",
4256d528ed9Sopenharmony_ci                 DECORATION_YELLOW);
4266d528ed9Sopenharmony_ci    return 1;
4276d528ed9Sopenharmony_ci  }
4286d528ed9Sopenharmony_ci
4296d528ed9Sopenharmony_ci  // Construct the reverse dependency tree.
4306d528ed9Sopenharmony_ci  DepMap dep_map;
4316d528ed9Sopenharmony_ci  FillDepMap(setup, &dep_map);
4326d528ed9Sopenharmony_ci
4336d528ed9Sopenharmony_ci  size_t cnt = 0;
4346d528ed9Sopenharmony_ci  if (tree)
4356d528ed9Sopenharmony_ci    cnt = DoTreeOutput(dep_map, target_matches, explicit_target_matches, all);
4366d528ed9Sopenharmony_ci  else if (all)
4376d528ed9Sopenharmony_ci    cnt = DoAllListOutput(dep_map, target_matches, explicit_target_matches);
4386d528ed9Sopenharmony_ci  else
4396d528ed9Sopenharmony_ci    cnt = DoDirectListOutput(dep_map, target_matches, explicit_target_matches);
4406d528ed9Sopenharmony_ci
4416d528ed9Sopenharmony_ci  // If you ask for the references of a valid target, but that target has
4426d528ed9Sopenharmony_ci  // nothing referencing it, we'll get here without having printed anything.
4436d528ed9Sopenharmony_ci  if (!quiet && cnt == 0)
4446d528ed9Sopenharmony_ci    OutputString("Nothing references this.\n", DECORATION_YELLOW);
4456d528ed9Sopenharmony_ci
4466d528ed9Sopenharmony_ci  return 0;
4476d528ed9Sopenharmony_ci}
4486d528ed9Sopenharmony_ci
4496d528ed9Sopenharmony_ci}  // namespace commands
450