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::kRustflags, DefaultHandler},
310 {variables::kSwiftModuleName, DefaultHandler},
311 {variables::kSwiftBridgeHeader, DefaultHandler},
312 {variables::kMnemonic, DefaultHandler},
313 {"runtime_deps", DefaultHandler}};
314 }
315
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)316 void HandleProperty(const std::string& what,
317 const std::map<std::string, DescHandlerFunc>& handler_map,
318 std::unique_ptr<base::Value>& v,
319 std::unique_ptr<base::DictionaryValue>& dict) {
320 if (dict->Remove(what, &v)) {
321 auto pair = handler_map.find(what);
322 if (pair != handler_map.end())
323 pair->second(what, v.get(), false);
324 }
325 }
326
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)327 bool PrintTarget(const Target* target,
328 const std::string& what,
329 bool single_target,
330 const std::map<std::string, DescHandlerFunc>& handler_map,
331 bool all,
332 bool tree,
333 bool blame) {
334 std::unique_ptr<base::DictionaryValue> dict =
335 DescBuilder::DescriptionForTarget(target, what, all, tree, blame);
336 if (!what.empty() && dict->empty()) {
337 OutputString("Don't know how to display \"" + what + "\" for \"" +
338 Target::GetStringForOutputType(target->output_type()) +
339 "\".\n");
340 return false;
341 }
342 // Print single value
343 if (!what.empty() && dict->size() == 1 && single_target) {
344 if (what == variables::kOutputs) {
345 ProcessOutputs(dict.get(), true);
346 return true;
347 }
348 base::DictionaryValue::Iterator iter(*dict);
349 auto pair = handler_map.find(what);
350 if (pair != handler_map.end())
351 pair->second(what, &iter.value(), true);
352 return true;
353 }
354
355 OutputString("Target ", DECORATION_YELLOW);
356 OutputString(target->label().GetUserVisibleName(false));
357 OutputString("\n");
358
359 std::unique_ptr<base::Value> v;
360 // Entries with DefaultHandler are present to enforce order
361 HandleProperty("type", handler_map, v, dict);
362 HandleProperty("toolchain", handler_map, v, dict);
363 HandleProperty(variables::kSwiftModuleName, handler_map, v, dict);
364 HandleProperty(variables::kRustCrateName, handler_map, v, dict);
365 HandleProperty(variables::kRustCrateRoot, handler_map, v, dict);
366 HandleProperty(variables::kVisibility, handler_map, v, dict);
367 HandleProperty(variables::kMetadata, handler_map, v, dict);
368 HandleProperty(variables::kTestonly, handler_map, v, dict);
369 HandleProperty(variables::kCheckIncludes, handler_map, v, dict);
370 HandleProperty(variables::kAllowCircularIncludesFrom, handler_map, v, dict);
371 HandleProperty(variables::kSources, handler_map, v, dict);
372 HandleProperty(variables::kSwiftBridgeHeader, handler_map, v, dict);
373 HandleProperty(variables::kPublic, handler_map, v, dict);
374 HandleProperty(variables::kInputs, handler_map, v, dict);
375 HandleProperty(variables::kConfigs, handler_map, v, dict);
376 HandleProperty(variables::kPublicConfigs, handler_map, v, dict);
377 HandleProperty(variables::kAllDependentConfigs, handler_map, v, dict);
378 HandleProperty(variables::kScript, handler_map, v, dict);
379 HandleProperty(variables::kArgs, handler_map, v, dict);
380 HandleProperty(variables::kDepfile, handler_map, v, dict);
381 ProcessOutputs(dict.get(), false);
382 HandleProperty("bundle_data", handler_map, v, dict);
383 HandleProperty(variables::kArflags, handler_map, v, dict);
384 HandleProperty(variables::kAsmflags, handler_map, v, dict);
385 HandleProperty(variables::kCflags, handler_map, v, dict);
386 HandleProperty(variables::kCflagsC, handler_map, v, dict);
387 HandleProperty(variables::kCflagsCC, handler_map, v, dict);
388 HandleProperty(variables::kCflagsObjC, handler_map, v, dict);
389 HandleProperty(variables::kCflagsObjCC, handler_map, v, dict);
390 HandleProperty(variables::kSwiftflags, handler_map, v, dict);
391 HandleProperty(variables::kDefines, handler_map, v, dict);
392 HandleProperty(variables::kFrameworkDirs, handler_map, v, dict);
393 HandleProperty(variables::kFrameworks, handler_map, v, dict);
394 HandleProperty(variables::kIncludeDirs, handler_map, v, dict);
395 HandleProperty(variables::kLdflags, handler_map, v, dict);
396 HandleProperty(variables::kPrecompiledHeader, handler_map, v, dict);
397 HandleProperty(variables::kPrecompiledSource, handler_map, v, dict);
398 HandleProperty(variables::kDeps, handler_map, v, dict);
399 HandleProperty(variables::kLibs, handler_map, v, dict);
400 HandleProperty(variables::kLibDirs, handler_map, v, dict);
401 HandleProperty(variables::kDataKeys, handler_map, v, dict);
402 HandleProperty(variables::kRebase, handler_map, v, dict);
403 HandleProperty(variables::kRustflags, handler_map, v, dict);
404 HandleProperty(variables::kWalkKeys, handler_map, v, dict);
405 HandleProperty(variables::kWeakFrameworks, handler_map, v, dict);
406 HandleProperty(variables::kWriteOutputConversion, handler_map, v, dict);
407
408 #undef HandleProperty
409
410 // Process the rest (if any)
411 base::DictionaryValue::Iterator iter(*dict);
412 while (!iter.IsAtEnd()) {
413 DefaultHandler(iter.key(), &iter.value(), false);
414 iter.Advance();
415 }
416
417 return true;
418 }
419
PrintConfig(const Config * config,const std::string & what,bool single_config,const std::map<std::string,DescHandlerFunc> & handler_map)420 bool PrintConfig(const Config* config,
421 const std::string& what,
422 bool single_config,
423 const std::map<std::string, DescHandlerFunc>& handler_map) {
424 std::unique_ptr<base::DictionaryValue> dict =
425 DescBuilder::DescriptionForConfig(config, what);
426 if (!what.empty() && dict->empty()) {
427 OutputString("Don't know how to display \"" + what + "\" for a config.\n");
428 return false;
429 }
430 // Print single value
431 if (!what.empty() && dict->size() == 1 && single_config) {
432 base::DictionaryValue::Iterator iter(*dict);
433 auto pair = handler_map.find(what);
434 if (pair != handler_map.end())
435 pair->second(what, &iter.value(), true);
436 return true;
437 }
438
439 OutputString("Config: ", DECORATION_YELLOW);
440 OutputString(config->label().GetUserVisibleName(false));
441 OutputString("\n");
442
443 std::unique_ptr<base::Value> v;
444 HandleProperty("toolchain", handler_map, v, dict);
445 if (!config->configs().empty()) {
446 OutputString(
447 "(This is a composite config, the values below are after the\n"
448 "expansion of the child configs.)\n");
449 }
450 HandleProperty(variables::kArflags, handler_map, v, dict);
451 HandleProperty(variables::kAsmflags, handler_map, v, dict);
452 HandleProperty(variables::kCflags, handler_map, v, dict);
453 HandleProperty(variables::kCflagsC, handler_map, v, dict);
454 HandleProperty(variables::kCflagsCC, handler_map, v, dict);
455 HandleProperty(variables::kCflagsObjC, handler_map, v, dict);
456 HandleProperty(variables::kCflagsObjCC, handler_map, v, dict);
457 HandleProperty(variables::kSwiftflags, handler_map, v, dict);
458 HandleProperty(variables::kDefines, handler_map, v, dict);
459 HandleProperty(variables::kFrameworkDirs, handler_map, v, dict);
460 HandleProperty(variables::kFrameworks, handler_map, v, dict);
461 HandleProperty(variables::kIncludeDirs, handler_map, v, dict);
462 HandleProperty(variables::kInputs, handler_map, v, dict);
463 HandleProperty(variables::kLdflags, handler_map, v, dict);
464 HandleProperty(variables::kLibs, handler_map, v, dict);
465 HandleProperty(variables::kLibDirs, handler_map, v, dict);
466 HandleProperty(variables::kPrecompiledHeader, handler_map, v, dict);
467 HandleProperty(variables::kPrecompiledSource, handler_map, v, dict);
468 HandleProperty(variables::kRustflags, handler_map, v, dict);
469 HandleProperty(variables::kWeakFrameworks, handler_map, v, dict);
470
471 #undef HandleProperty
472
473 return true;
474 }
475
476 } // namespace
477
478 // desc ------------------------------------------------------------------------
479
480 const char kDesc[] = "desc";
481 const char kDesc_HelpShort[] =
482 "desc: Show lots of insightful information about a target or config.";
483 const char kDesc_Help[] =
484 R"(gn desc
485
486 gn desc <out_dir> <label or pattern> [<what to show>] [--blame]
487 [--format=json]
488
489 Displays information about a given target or config. The build parameters
490 will be taken for the build in the given <out_dir>.
491
492 The <label or pattern> can be a target label, a config label, or a label
493 pattern (see "gn help label_pattern"). A label pattern will only match
494 targets.
495
496 Possibilities for <what to show>
497
498 (If unspecified an overall summary will be displayed.)
499
500 all_dependent_configs
501 allow_circular_includes_from
502 arflags [--blame]
503 args
504 cflags [--blame]
505 cflags_c [--blame]
506 cflags_cc [--blame]
507 check_includes
508 configs [--tree] (see below)
509 data_keys
510 defines [--blame]
511 depfile
512 deps [--all] [--tree] (see below)
513 framework_dirs
514 frameworks
515 include_dirs [--blame]
516 inputs
517 ldflags [--blame]
518 lib_dirs
519 libs
520 metadata
521 output_conversion
522 outputs
523 public_configs
524 public
525 rebase
526 script
527 sources
528 testonly
529 visibility
530 walk_keys
531 weak_frameworks
532
533 runtime_deps
534 Compute all runtime deps for the given target. This is a computed list
535 and does not correspond to any GN variable, unlike most other values
536 here.
537
538 The output is a list of file names relative to the build directory. See
539 "gn help runtime_deps" for how this is computed. This also works with
540 "--blame" to see the source of the dependency.
541
542 Shared flags
543
544 )"
545
546 DEFAULT_TOOLCHAIN_SWITCH_HELP
547
548 R"(
549 --format=json
550 Format the output as JSON instead of text.
551
552 Target flags
553
554 --blame
555 Used with any value specified on a config, this will name the config that
556 causes that target to get the flag. This doesn't currently work for libs,
557 lib_dirs, frameworks, weak_frameworks and framework_dirs because those are
558 inherited and are more complicated to figure out the blame (patches
559 welcome).
560
561 Configs
562
563 The "configs" section will list all configs that apply. For targets this will
564 include configs specified in the "configs" variable of the target, and also
565 configs pushed onto this target via public or "all dependent" configs.
566
567 Configs can have child configs. Specifying --tree will show the hierarchy.
568
569 Printing outputs
570
571 The "outputs" section will list all outputs that apply, including the outputs
572 computed from the tool definition (eg for "executable", "static_library", ...
573 targets).
574
575 Printing deps
576
577 Deps will include all public, private, and data deps (TODO this could be
578 clarified and enhanced) sorted in order applying. The following may be used:
579
580 --all
581 Collects all recursive dependencies and prints a sorted flat list. Also
582 usable with --tree (see below).
583
584 )"
585
586 TARGET_PRINTING_MODE_COMMAND_LINE_HELP
587 "\n" TARGET_TESTONLY_FILTER_COMMAND_LINE_HELP
588
589 R"(
590 --tree
591 Print a dependency tree. By default, duplicates will be elided with "..."
592 but when --all and -tree are used together, no eliding will be performed.
593
594 The "deps", "public_deps", and "data_deps" will all be included in the
595 tree.
596
597 Tree output can not be used with the filtering or output flags: --as,
598 --type, --testonly.
599
600 )"
601
602 TARGET_TYPE_FILTER_COMMAND_LINE_HELP
603
604 R"(
605 Note
606
607 This command will show the full name of directories and source files, but
608 when directories and source paths are written to the build file, they will be
609 adjusted to be relative to the build directory. So the values for paths
610 displayed by this command won't match (but should mean the same thing).
611
612 Examples
613
614 gn desc out/Debug //base:base
615 Summarizes the given target.
616
617 gn desc out/Foo :base_unittests deps --tree
618 Shows a dependency tree of the "base_unittests" project in
619 the current directory.
620
621 gn desc out/Debug //base defines --blame
622 Shows defines set for the //base:base target, annotated by where
623 each one was set from.
624 )";
625
RunDesc(const std::vector<std::string> & args)626 int RunDesc(const std::vector<std::string>& args) {
627 if (args.size() != 2 && args.size() != 3) {
628 Err(Location(), "Unknown command format. See \"gn help desc\"",
629 "Usage: \"gn desc <out_dir> <target_name> [<what to display>]\"")
630 .PrintToStdout();
631 return 1;
632 }
633 const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
634
635 // Deliberately leaked to avoid expensive process teardown.
636 Setup* setup = new Setup;
637 if (!setup->DoSetup(args[0], false))
638 return 1;
639 if (!setup->Run())
640 return 1;
641
642 // Resolve target(s) and config from inputs.
643 UniqueVector<const Target*> target_matches;
644 UniqueVector<const Config*> config_matches;
645 UniqueVector<const Toolchain*> toolchain_matches;
646 UniqueVector<SourceFile> file_matches;
647
648 std::vector<std::string> target_list;
649 target_list.push_back(args[1]);
650
651 if (!ResolveFromCommandLineInput(
652 setup, target_list, cmdline->HasSwitch(switches::kDefaultToolchain),
653 &target_matches, &config_matches, &toolchain_matches, &file_matches))
654 return 1;
655
656 std::string what_to_print;
657 if (args.size() == 3)
658 what_to_print = args[2];
659
660 bool json = cmdline->GetSwitchValueString("format") == "json";
661
662 if (target_matches.empty() && config_matches.empty()) {
663 OutputString(
664 "The input " + args[1] + " matches no targets, configs or files.\n",
665 DECORATION_YELLOW);
666 return 1;
667 }
668
669 if (json) {
670 // Convert all targets/configs to JSON, serialize and print them
671 auto res = std::make_unique<base::DictionaryValue>();
672 if (!target_matches.empty()) {
673 for (const auto* target : target_matches) {
674 res->SetWithoutPathExpansion(
675 target->label().GetUserVisibleName(
676 target->settings()->default_toolchain_label()),
677 DescBuilder::DescriptionForTarget(
678 target, what_to_print, cmdline->HasSwitch(kAll),
679 cmdline->HasSwitch(kTree), cmdline->HasSwitch(kBlame)));
680 }
681 } else if (!config_matches.empty()) {
682 for (const auto* config : config_matches) {
683 res->SetWithoutPathExpansion(
684 config->label().GetUserVisibleName(false),
685 DescBuilder::DescriptionForConfig(config, what_to_print));
686 }
687 }
688 std::string s;
689 base::JSONWriter::WriteWithOptions(
690 *res.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &s);
691 OutputString(s);
692 } else {
693 // Regular (non-json) formatted output
694 bool multiple_outputs = (target_matches.size() + config_matches.size()) > 1;
695 std::map<std::string, DescHandlerFunc> handlers = GetHandlers();
696
697 bool printed_output = false;
698 for (const Target* target : target_matches) {
699 if (printed_output)
700 OutputString("\n\n");
701 printed_output = true;
702
703 if (!PrintTarget(target, what_to_print, !multiple_outputs, handlers,
704 cmdline->HasSwitch(kAll), cmdline->HasSwitch(kTree),
705 cmdline->HasSwitch(kBlame)))
706 return 1;
707 }
708 for (const Config* config : config_matches) {
709 if (printed_output)
710 OutputString("\n\n");
711 printed_output = true;
712
713 if (!PrintConfig(config, what_to_print, !multiple_outputs, handlers))
714 return 1;
715 }
716 }
717
718 return 0;
719 }
720
721 } // namespace commands
722