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