• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stddef.h>
6 
7 #include <algorithm>
8 #include <memory>
9 #include <set>
10 #include <sstream>
11 
12 #include "base/command_line.h"
13 #include "base/json/json_writer.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "gn/commands.h"
17 #include "gn/config.h"
18 #include "gn/desc_builder.h"
19 #include "gn/rust_variables.h"
20 #include "gn/setup.h"
21 #include "gn/standard_out.h"
22 #include "gn/swift_variables.h"
23 #include "gn/switches.h"
24 #include "gn/target.h"
25 #include "gn/variables.h"
26 
27 namespace commands {
28 
29 namespace {
30 
31 // Desc-specific command line switches.
32 const char kBlame[] = "blame";
33 const char kTree[] = "tree";
34 const char kAll[] = "all";
35 
PrintDictValue(const base::Value * value,int indentLevel,bool use_first_indent)36 void PrintDictValue(const base::Value* value,
37                     int indentLevel,
38                     bool use_first_indent) {
39   std::string indent(indentLevel * 2, ' ');
40   const base::ListValue* list_value = nullptr;
41   const base::DictionaryValue* dict_value = nullptr;
42   std::string string_value;
43   bool bool_value = false;
44   int int_value = 0;
45   if (use_first_indent)
46     OutputString(indent);
47   if (value->GetAsList(&list_value)) {
48     OutputString("[\n");
49     bool first = true;
50     for (const auto& v : *list_value) {
51       if (!first)
52         OutputString(",\n");
53       PrintDictValue(&v, indentLevel + 1, true);
54       first = false;
55     }
56     OutputString("\n" + indent + "]");
57   } else if (value->GetAsString(&string_value)) {
58     OutputString("\"" + string_value + "\"");
59   } else if (value->GetAsBoolean(&bool_value)) {
60     OutputString(bool_value ? "true" : "false");
61   } else if (value->GetAsDictionary(&dict_value)) {
62     OutputString("{\n");
63     std::string indent_plus_one((indentLevel + 1) * 2, ' ');
64     base::DictionaryValue::Iterator iter(*dict_value);
65     bool first = true;
66     while (!iter.IsAtEnd()) {
67       if (!first)
68         OutputString(",\n");
69       OutputString(indent_plus_one + iter.key() + " = ");
70       PrintDictValue(&iter.value(), indentLevel + 1, false);
71       iter.Advance();
72       first = false;
73     }
74     OutputString("\n" + indent + "}");
75   } else if (value->GetAsInteger(&int_value)) {
76     OutputString(base::IntToString(int_value));
77   } else if (value->is_none()) {
78     OutputString("<null>");
79   }
80 }
81 
82 // Prints value with specified indentation level
PrintValue(const base::Value * value,int indentLevel)83 void PrintValue(const base::Value* value, int indentLevel) {
84   std::string indent(indentLevel * 2, ' ');
85   const base::ListValue* list_value = nullptr;
86   const base::DictionaryValue* dict_value = nullptr;
87   std::string string_value;
88   bool bool_value = false;
89   int int_value = 0;
90   if (value->GetAsList(&list_value)) {
91     for (const auto& v : *list_value) {
92       PrintValue(&v, indentLevel);
93     }
94   } else if (value->GetAsString(&string_value)) {
95     OutputString(indent);
96     OutputString(string_value);
97     OutputString("\n");
98   } else if (value->GetAsBoolean(&bool_value)) {
99     OutputString(indent);
100     OutputString(bool_value ? "true" : "false");
101     OutputString("\n");
102   } else if (value->GetAsDictionary(&dict_value)) {
103     base::DictionaryValue::Iterator iter(*dict_value);
104     while (!iter.IsAtEnd()) {
105       OutputString(indent + iter.key() + "\n");
106       PrintValue(&iter.value(), indentLevel + 1);
107       iter.Advance();
108     }
109   } else if (value->GetAsInteger(&int_value)) {
110     OutputString(indent);
111     OutputString(base::IntToString(int_value));
112     OutputString("\n");
113   } else if (value->is_none()) {
114     OutputString(indent + "<null>\n");
115   }
116 }
117 
118 // Default handler for property
DefaultHandler(const std::string & name,const base::Value * value,bool value_only)119 void DefaultHandler(const std::string& name,
120                     const base::Value* value,
121                     bool value_only) {
122   if (value_only) {
123     PrintValue(value, 0);
124     return;
125   }
126   OutputString("\n");
127   OutputString(name);
128   OutputString("\n");
129   PrintValue(value, 1);
130 }
131 
132 // Specific handler for properties that need different treatment
133 
134 // Prints the dict in GN scope-sytle.
MetadataHandler(const std::string & name,const base::Value * value,bool value_only)135 void MetadataHandler(const std::string& name,
136                      const base::Value* value,
137                      bool value_only) {
138   if (value_only) {
139     PrintDictValue(value, 0, true);
140     OutputString("\n");
141     return;
142   }
143   OutputString("\n");
144   OutputString(name);
145   OutputString("\n");
146   PrintDictValue(value, 1, true);
147   OutputString("\n");
148 }
149 
150 // Prints label and property value on one line, capitalizing the label.
LabelHandler(const std::string & name,const base::Value * value,bool value_only)151 void LabelHandler(const std::string& name,
152                   const base::Value* value,
153                   bool value_only) {
154   if (value_only) {
155     PrintValue(value, 0);
156     return;
157   }
158   std::string label = name;
159   label[0] = base::ToUpperASCII(label[0]);
160   std::string string_value;
161   if (value->GetAsString(&string_value)) {
162     OutputString(name + ": ", DECORATION_YELLOW);
163     OutputString(string_value + "\n");
164   }
165 }
166 
VisibilityHandler(const std::string & name,const base::Value * value,bool value_only)167 void VisibilityHandler(const std::string& name,
168                        const base::Value* value,
169                        bool value_only) {
170   if (value_only) {
171     PrintValue(value, 0);
172     return;
173   }
174   const base::ListValue* list;
175   if (value->GetAsList(&list)) {
176     if (list->empty()) {
177       base::Value str("(no visibility)");
178       DefaultHandler(name, &str, value_only);
179     } else {
180       DefaultHandler(name, value, value_only);
181     }
182   }
183 }
184 
PublicHandler(const std::string & name,const base::Value * value,bool value_only)185 void PublicHandler(const std::string& name,
186                    const base::Value* value,
187                    bool value_only) {
188   if (value_only) {
189     PrintValue(value, 0);
190     return;
191   }
192   std::string p;
193   if (value->GetAsString(&p)) {
194     if (p == "*") {
195       base::Value str("[All headers listed in the sources are public.]");
196       DefaultHandler(name, &str, value_only);
197       return;
198     }
199   }
200   DefaultHandler(name, value, value_only);
201 }
202 
ConfigsHandler(const std::string & name,const base::Value * value,bool value_only)203 void ConfigsHandler(const std::string& name,
204                     const base::Value* value,
205                     bool value_only) {
206   bool tree = base::CommandLine::ForCurrentProcess()->HasSwitch(kTree);
207   if (tree)
208     DefaultHandler(name + " tree (in order applying)", value, value_only);
209   else
210     DefaultHandler(name + " (in order applying, try also --tree)", value,
211                    value_only);
212 }
213 
DepsHandler(const std::string & name,const base::Value * value,bool value_only)214 void DepsHandler(const std::string& name,
215                  const base::Value* value,
216                  bool value_only) {
217   bool tree = base::CommandLine::ForCurrentProcess()->HasSwitch(kTree);
218   bool all = base::CommandLine::ForCurrentProcess()->HasSwitch(kTree);
219   if (tree) {
220     DefaultHandler("Dependency tree", value, value_only);
221   } else {
222     if (!all) {
223       DefaultHandler(
224           "Direct dependencies "
225           "(try also \"--all\", \"--tree\", or even \"--all --tree\")",
226           value, value_only);
227     } else {
228       DefaultHandler("All recursive dependencies", value, value_only);
229     }
230   }
231 }
232 
233 // Outputs need special processing when output patterns are present.
ProcessOutputs(base::DictionaryValue * target,bool files_only)234 void ProcessOutputs(base::DictionaryValue* target, bool files_only) {
235   base::ListValue* patterns = nullptr;
236   base::ListValue* outputs = nullptr;
237   target->GetList("output_patterns", &patterns);
238   target->GetList(variables::kOutputs, &outputs);
239 
240   int indent = 0;
241   if (outputs || patterns) {
242     if (!files_only) {
243       OutputString("\noutputs\n");
244       indent = 1;
245     }
246     if (patterns) {
247       if (!files_only) {
248         OutputString("  Output patterns\n");
249         indent = 2;
250       }
251       PrintValue(patterns, indent);
252       if (!files_only)
253         OutputString("\n  Resolved output file list\n");
254     }
255     if (outputs)
256       PrintValue(outputs, indent);
257 
258     target->Remove("output_patterns", nullptr);
259     target->Remove(variables::kOutputs, nullptr);
260   }
261 }
262 
263 using DescHandlerFunc = void (*)(const std::string& name,
264                                  const base::Value* value,
265                                  bool value_only);
GetHandlers()266 std::map<std::string, DescHandlerFunc> GetHandlers() {
267   return {{"type", LabelHandler},
268           {"toolchain", LabelHandler},
269           {variables::kVisibility, VisibilityHandler},
270           {variables::kMetadata, MetadataHandler},
271           {variables::kTestonly, DefaultHandler},
272           {variables::kCheckIncludes, DefaultHandler},
273           {variables::kAllowCircularIncludesFrom, DefaultHandler},
274           {variables::kSources, DefaultHandler},
275           {variables::kPublic, PublicHandler},
276           {variables::kInputs, DefaultHandler},
277           {variables::kConfigs, ConfigsHandler},
278           {variables::kPublicConfigs, ConfigsHandler},
279           {variables::kAllDependentConfigs, ConfigsHandler},
280           {variables::kScript, DefaultHandler},
281           {variables::kArgs, DefaultHandler},
282           {variables::kDepfile, DefaultHandler},
283           {"bundle_data", DefaultHandler},
284           {variables::kArflags, DefaultHandler},
285           {variables::kAsmflags, DefaultHandler},
286           {variables::kCflags, DefaultHandler},
287           {variables::kCflagsC, DefaultHandler},
288           {variables::kCflagsCC, DefaultHandler},
289           {variables::kCflagsObjC, DefaultHandler},
290           {variables::kCflagsObjCC, DefaultHandler},
291           {variables::kDefines, DefaultHandler},
292           {variables::kFrameworkDirs, DefaultHandler},
293           {variables::kFrameworks, DefaultHandler},
294           {variables::kIncludeDirs, DefaultHandler},
295           {variables::kLdflags, DefaultHandler},
296           {variables::kPrecompiledHeader, DefaultHandler},
297           {variables::kPrecompiledSource, DefaultHandler},
298           {variables::kDeps, DepsHandler},
299           {variables::kGenDeps, DefaultHandler},
300           {variables::kLibs, DefaultHandler},
301           {variables::kLibDirs, DefaultHandler},
302           {variables::kDataKeys, DefaultHandler},
303           {variables::kRebase, DefaultHandler},
304           {variables::kWalkKeys, DefaultHandler},
305           {variables::kWeakFrameworks, DefaultHandler},
306           {variables::kWriteOutputConversion, DefaultHandler},
307           {variables::kRustCrateName, DefaultHandler},
308           {variables::kRustCrateRoot, DefaultHandler},
309           {variables::kSwiftModuleName, DefaultHandler},
310           {variables::kSwiftBridgeHeader, DefaultHandler},
311           {"runtime_deps", DefaultHandler}};
312 }
313 
HandleProperty(const std::string & what,const std::map<std::string,DescHandlerFunc> & handler_map,std::unique_ptr<base::Value> & v,std::unique_ptr<base::DictionaryValue> & dict)314 void HandleProperty(const std::string& what,
315                     const std::map<std::string, DescHandlerFunc>& handler_map,
316                     std::unique_ptr<base::Value>& v,
317                     std::unique_ptr<base::DictionaryValue>& dict) {
318   if (dict->Remove(what, &v)) {
319     auto pair = handler_map.find(what);
320     if (pair != handler_map.end())
321       pair->second(what, v.get(), false);
322   }
323 }
324 
PrintTarget(const Target * target,const std::string & what,bool single_target,const std::map<std::string,DescHandlerFunc> & handler_map,bool all,bool tree,bool blame)325 bool PrintTarget(const Target* target,
326                  const std::string& what,
327                  bool single_target,
328                  const std::map<std::string, DescHandlerFunc>& handler_map,
329                  bool all,
330                  bool tree,
331                  bool blame) {
332   std::unique_ptr<base::DictionaryValue> dict =
333       DescBuilder::DescriptionForTarget(target, what, all, tree, blame);
334   if (!what.empty() && dict->empty()) {
335     OutputString("Don't know how to display \"" + what + "\" for \"" +
336                  Target::GetStringForOutputType(target->output_type()) +
337                  "\".\n");
338     return false;
339   }
340   // Print single value
341   if (!what.empty() && dict->size() == 1 && single_target) {
342     if (what == variables::kOutputs) {
343       ProcessOutputs(dict.get(), true);
344       return true;
345     }
346     base::DictionaryValue::Iterator iter(*dict);
347     auto pair = handler_map.find(what);
348     if (pair != handler_map.end())
349       pair->second(what, &iter.value(), true);
350     return true;
351   }
352 
353   OutputString("Target ", DECORATION_YELLOW);
354   OutputString(target->label().GetUserVisibleName(false));
355   OutputString("\n");
356 
357   std::unique_ptr<base::Value> v;
358   // Entries with DefaultHandler are present to enforce order
359   HandleProperty("type", handler_map, v, dict);
360   HandleProperty("toolchain", handler_map, v, dict);
361   HandleProperty(variables::kSwiftModuleName, handler_map, v, dict);
362   HandleProperty(variables::kRustCrateName, handler_map, v, dict);
363   HandleProperty(variables::kRustCrateRoot, handler_map, v, dict);
364   HandleProperty(variables::kVisibility, handler_map, v, dict);
365   HandleProperty(variables::kMetadata, handler_map, v, dict);
366   HandleProperty(variables::kTestonly, handler_map, v, dict);
367   HandleProperty(variables::kCheckIncludes, handler_map, v, dict);
368   HandleProperty(variables::kAllowCircularIncludesFrom, handler_map, v, dict);
369   HandleProperty(variables::kSources, handler_map, v, dict);
370   HandleProperty(variables::kSwiftBridgeHeader, handler_map, v, dict);
371   HandleProperty(variables::kPublic, handler_map, v, dict);
372   HandleProperty(variables::kInputs, handler_map, v, dict);
373   HandleProperty(variables::kConfigs, handler_map, v, dict);
374   HandleProperty(variables::kPublicConfigs, handler_map, v, dict);
375   HandleProperty(variables::kAllDependentConfigs, handler_map, v, dict);
376   HandleProperty(variables::kScript, handler_map, v, dict);
377   HandleProperty(variables::kArgs, handler_map, v, dict);
378   HandleProperty(variables::kDepfile, handler_map, v, dict);
379   ProcessOutputs(dict.get(), false);
380   HandleProperty("bundle_data", handler_map, v, dict);
381   HandleProperty(variables::kArflags, handler_map, v, dict);
382   HandleProperty(variables::kAsmflags, handler_map, v, dict);
383   HandleProperty(variables::kCflags, handler_map, v, dict);
384   HandleProperty(variables::kCflagsC, handler_map, v, dict);
385   HandleProperty(variables::kCflagsCC, handler_map, v, dict);
386   HandleProperty(variables::kCflagsObjC, handler_map, v, dict);
387   HandleProperty(variables::kCflagsObjCC, handler_map, v, dict);
388   HandleProperty(variables::kSwiftflags, handler_map, v, dict);
389   HandleProperty(variables::kDefines, handler_map, v, dict);
390   HandleProperty(variables::kFrameworkDirs, handler_map, v, dict);
391   HandleProperty(variables::kFrameworks, handler_map, v, dict);
392   HandleProperty(variables::kIncludeDirs, handler_map, v, dict);
393   HandleProperty(variables::kLdflags, handler_map, v, dict);
394   HandleProperty(variables::kPrecompiledHeader, handler_map, v, dict);
395   HandleProperty(variables::kPrecompiledSource, handler_map, v, dict);
396   HandleProperty(variables::kDeps, handler_map, v, dict);
397   HandleProperty(variables::kLibs, handler_map, v, dict);
398   HandleProperty(variables::kLibDirs, handler_map, v, dict);
399   HandleProperty(variables::kDataKeys, handler_map, v, dict);
400   HandleProperty(variables::kRebase, handler_map, v, dict);
401   HandleProperty(variables::kWalkKeys, handler_map, v, dict);
402   HandleProperty(variables::kWeakFrameworks, handler_map, v, dict);
403   HandleProperty(variables::kWriteOutputConversion, handler_map, v, dict);
404 
405 #undef HandleProperty
406 
407   // Process the rest (if any)
408   base::DictionaryValue::Iterator iter(*dict);
409   while (!iter.IsAtEnd()) {
410     DefaultHandler(iter.key(), &iter.value(), false);
411     iter.Advance();
412   }
413 
414   return true;
415 }
416 
PrintConfig(const Config * config,const std::string & what,bool single_config,const std::map<std::string,DescHandlerFunc> & handler_map)417 bool PrintConfig(const Config* config,
418                  const std::string& what,
419                  bool single_config,
420                  const std::map<std::string, DescHandlerFunc>& handler_map) {
421   std::unique_ptr<base::DictionaryValue> dict =
422       DescBuilder::DescriptionForConfig(config, what);
423   if (!what.empty() && dict->empty()) {
424     OutputString("Don't know how to display \"" + what + "\" for a config.\n");
425     return false;
426   }
427   // Print single value
428   if (!what.empty() && dict->size() == 1 && single_config) {
429     base::DictionaryValue::Iterator iter(*dict);
430     auto pair = handler_map.find(what);
431     if (pair != handler_map.end())
432       pair->second(what, &iter.value(), true);
433     return true;
434   }
435 
436   OutputString("Config: ", DECORATION_YELLOW);
437   OutputString(config->label().GetUserVisibleName(false));
438   OutputString("\n");
439 
440   std::unique_ptr<base::Value> v;
441   HandleProperty("toolchain", handler_map, v, dict);
442   if (!config->configs().empty()) {
443     OutputString(
444         "(This is a composite config, the values below are after the\n"
445         "expansion of the child configs.)\n");
446   }
447   HandleProperty(variables::kArflags, handler_map, v, dict);
448   HandleProperty(variables::kAsmflags, handler_map, v, dict);
449   HandleProperty(variables::kCflags, handler_map, v, dict);
450   HandleProperty(variables::kCflagsC, handler_map, v, dict);
451   HandleProperty(variables::kCflagsCC, handler_map, v, dict);
452   HandleProperty(variables::kCflagsObjC, handler_map, v, dict);
453   HandleProperty(variables::kCflagsObjCC, handler_map, v, dict);
454   HandleProperty(variables::kSwiftflags, handler_map, v, dict);
455   HandleProperty(variables::kDefines, handler_map, v, dict);
456   HandleProperty(variables::kFrameworkDirs, handler_map, v, dict);
457   HandleProperty(variables::kFrameworks, handler_map, v, dict);
458   HandleProperty(variables::kIncludeDirs, handler_map, v, dict);
459   HandleProperty(variables::kInputs, handler_map, v, dict);
460   HandleProperty(variables::kLdflags, handler_map, v, dict);
461   HandleProperty(variables::kLibs, handler_map, v, dict);
462   HandleProperty(variables::kLibDirs, handler_map, v, dict);
463   HandleProperty(variables::kPrecompiledHeader, handler_map, v, dict);
464   HandleProperty(variables::kPrecompiledSource, handler_map, v, dict);
465   HandleProperty(variables::kWeakFrameworks, handler_map, v, dict);
466 
467 #undef HandleProperty
468 
469   return true;
470 }
471 
472 }  // namespace
473 
474 // desc ------------------------------------------------------------------------
475 
476 const char kDesc[] = "desc";
477 const char kDesc_HelpShort[] =
478     "desc: Show lots of insightful information about a target or config.";
479 const char kDesc_Help[] =
480     R"(gn desc
481 
482   gn desc <out_dir> <label or pattern> [<what to show>] [--blame]
483           [--format=json]
484 
485   Displays information about a given target or config. The build parameters
486   will be taken for the build in the given <out_dir>.
487 
488   The <label or pattern> can be a target label, a config label, or a label
489   pattern (see "gn help label_pattern"). A label pattern will only match
490   targets.
491 
492 Possibilities for <what to show>
493 
494   (If unspecified an overall summary will be displayed.)
495 
496   all_dependent_configs
497   allow_circular_includes_from
498   arflags [--blame]
499   args
500   cflags [--blame]
501   cflags_c [--blame]
502   cflags_cc [--blame]
503   check_includes
504   configs [--tree] (see below)
505   data_keys
506   defines [--blame]
507   depfile
508   deps [--all] [--tree] (see below)
509   framework_dirs
510   frameworks
511   include_dirs [--blame]
512   inputs
513   ldflags [--blame]
514   lib_dirs
515   libs
516   metadata
517   output_conversion
518   outputs
519   public_configs
520   public
521   rebase
522   script
523   sources
524   testonly
525   visibility
526   walk_keys
527   weak_frameworks
528 
529   runtime_deps
530       Compute all runtime deps for the given target. This is a computed list
531       and does not correspond to any GN variable, unlike most other values
532       here.
533 
534       The output is a list of file names relative to the build directory. See
535       "gn help runtime_deps" for how this is computed. This also works with
536       "--blame" to see the source of the dependency.
537 
538 Shared flags
539 
540 )"
541 
542     DEFAULT_TOOLCHAIN_SWITCH_HELP
543 
544     R"(
545   --format=json
546       Format the output as JSON instead of text.
547 
548 Target flags
549 
550   --blame
551       Used with any value specified on a config, this will name the config that
552       causes that target to get the flag. This doesn't currently work for libs,
553       lib_dirs, frameworks, weak_frameworks and framework_dirs because those are
554       inherited and are more complicated to figure out the blame (patches
555       welcome).
556 
557 Configs
558 
559   The "configs" section will list all configs that apply. For targets this will
560   include configs specified in the "configs" variable of the target, and also
561   configs pushed onto this target via public or "all dependent" configs.
562 
563   Configs can have child configs. Specifying --tree will show the hierarchy.
564 
565 Printing outputs
566 
567   The "outputs" section will list all outputs that apply, including the outputs
568   computed from the tool definition (eg for "executable", "static_library", ...
569   targets).
570 
571 Printing deps
572 
573   Deps will include all public, private, and data deps (TODO this could be
574   clarified and enhanced) sorted in order applying. The following may be used:
575 
576   --all
577       Collects all recursive dependencies and prints a sorted flat list. Also
578       usable with --tree (see below).
579 
580 )"
581 
582     TARGET_PRINTING_MODE_COMMAND_LINE_HELP
583     "\n" TARGET_TESTONLY_FILTER_COMMAND_LINE_HELP
584 
585     R"(
586   --tree
587       Print a dependency tree. By default, duplicates will be elided with "..."
588       but when --all and -tree are used together, no eliding will be performed.
589 
590       The "deps", "public_deps", and "data_deps" will all be included in the
591       tree.
592 
593       Tree output can not be used with the filtering or output flags: --as,
594       --type, --testonly.
595 
596 )"
597 
598     TARGET_TYPE_FILTER_COMMAND_LINE_HELP
599 
600     R"(
601 Note
602 
603   This command will show the full name of directories and source files, but
604   when directories and source paths are written to the build file, they will be
605   adjusted to be relative to the build directory. So the values for paths
606   displayed by this command won't match (but should mean the same thing).
607 
608 Examples
609 
610   gn desc out/Debug //base:base
611       Summarizes the given target.
612 
613   gn desc out/Foo :base_unittests deps --tree
614       Shows a dependency tree of the "base_unittests" project in
615       the current directory.
616 
617   gn desc out/Debug //base defines --blame
618       Shows defines set for the //base:base target, annotated by where
619       each one was set from.
620 )";
621 
RunDesc(const std::vector<std::string> & args)622 int RunDesc(const std::vector<std::string>& args) {
623   if (args.size() != 2 && args.size() != 3) {
624     Err(Location(), "Unknown command format. See \"gn help desc\"",
625         "Usage: \"gn desc <out_dir> <target_name> [<what to display>]\"")
626         .PrintToStdout();
627     return 1;
628   }
629   const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
630 
631   // Deliberately leaked to avoid expensive process teardown.
632   Setup* setup = new Setup;
633   if (!setup->DoSetup(args[0], false))
634     return 1;
635   if (!setup->Run())
636     return 1;
637 
638   // Resolve target(s) and config from inputs.
639   UniqueVector<const Target*> target_matches;
640   UniqueVector<const Config*> config_matches;
641   UniqueVector<const Toolchain*> toolchain_matches;
642   UniqueVector<SourceFile> file_matches;
643 
644   std::vector<std::string> target_list;
645   target_list.push_back(args[1]);
646 
647   if (!ResolveFromCommandLineInput(
648           setup, target_list, cmdline->HasSwitch(switches::kDefaultToolchain),
649           &target_matches, &config_matches, &toolchain_matches, &file_matches))
650     return 1;
651 
652   std::string what_to_print;
653   if (args.size() == 3)
654     what_to_print = args[2];
655 
656   bool json = cmdline->GetSwitchValueASCII("format") == "json";
657 
658   if (target_matches.empty() && config_matches.empty()) {
659     OutputString(
660         "The input " + args[1] + " matches no targets, configs or files.\n",
661         DECORATION_YELLOW);
662     return 1;
663   }
664 
665   if (json) {
666     // Convert all targets/configs to JSON, serialize and print them
667     auto res = std::make_unique<base::DictionaryValue>();
668     if (!target_matches.empty()) {
669       for (const auto* target : target_matches) {
670         res->SetWithoutPathExpansion(
671             target->label().GetUserVisibleName(
672                 target->settings()->default_toolchain_label()),
673             DescBuilder::DescriptionForTarget(
674                 target, what_to_print, cmdline->HasSwitch(kAll),
675                 cmdline->HasSwitch(kTree), cmdline->HasSwitch(kBlame)));
676       }
677     } else if (!config_matches.empty()) {
678       for (const auto* config : config_matches) {
679         res->SetWithoutPathExpansion(
680             config->label().GetUserVisibleName(false),
681             DescBuilder::DescriptionForConfig(config, what_to_print));
682       }
683     }
684     std::string s;
685     base::JSONWriter::WriteWithOptions(
686         *res.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &s);
687     OutputString(s);
688   } else {
689     // Regular (non-json) formatted output
690     bool multiple_outputs = (target_matches.size() + config_matches.size()) > 1;
691     std::map<std::string, DescHandlerFunc> handlers = GetHandlers();
692 
693     bool printed_output = false;
694     for (const Target* target : target_matches) {
695       if (printed_output)
696         OutputString("\n\n");
697       printed_output = true;
698 
699       if (!PrintTarget(target, what_to_print, !multiple_outputs, handlers,
700                        cmdline->HasSwitch(kAll), cmdline->HasSwitch(kTree),
701                        cmdline->HasSwitch(kBlame)))
702         return 1;
703     }
704     for (const Config* config : config_matches) {
705       if (printed_output)
706         OutputString("\n\n");
707       printed_output = true;
708 
709       if (!PrintConfig(config, what_to_print, !multiple_outputs, handlers))
710         return 1;
711     }
712   }
713 
714   return 0;
715 }
716 
717 }  // namespace commands
718