Remove the now unused TextButton code.
[chromium-blink-merge.git] / tools / gn / command_desc.cc
blob4491920da991faa78f61cf467a601b44f4e5cb83
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.
5 #include <algorithm>
6 #include <set>
7 #include <sstream>
9 #include "base/command_line.h"
10 #include "tools/gn/commands.h"
11 #include "tools/gn/config.h"
12 #include "tools/gn/config_values_extractors.h"
13 #include "tools/gn/file_template.h"
14 #include "tools/gn/filesystem_utils.h"
15 #include "tools/gn/item.h"
16 #include "tools/gn/label.h"
17 #include "tools/gn/setup.h"
18 #include "tools/gn/standard_out.h"
19 #include "tools/gn/target.h"
21 namespace commands {
23 namespace {
25 // Prints the given directory in a nice way for the user to view.
26 std::string FormatSourceDir(const SourceDir& dir) {
27 #if defined(OS_WIN)
28 // On Windows we fix up system absolute paths to look like native ones.
29 // Internally, they'll look like "/C:\foo\bar/"
30 if (dir.is_system_absolute()) {
31 std::string buf = dir.value();
32 if (buf.size() > 3 && buf[2] == ':') {
33 buf.erase(buf.begin()); // Erase beginning slash.
34 return buf;
37 #endif
38 return dir.value();
41 void RecursiveCollectChildDeps(const Target* target, std::set<Label>* result);
43 void RecursiveCollectDeps(const Target* target, std::set<Label>* result) {
44 if (result->find(target->label()) != result->end())
45 return; // Already did this target.
46 result->insert(target->label());
48 RecursiveCollectChildDeps(target, result);
51 void RecursiveCollectChildDeps(const Target* target, std::set<Label>* result) {
52 const LabelTargetVector& deps = target->deps();
53 for (size_t i = 0; i < deps.size(); i++)
54 RecursiveCollectDeps(deps[i].ptr, result);
56 const LabelTargetVector& datadeps = target->datadeps();
57 for (size_t i = 0; i < datadeps.size(); i++)
58 RecursiveCollectDeps(datadeps[i].ptr, result);
61 // Prints dependencies of the given target (not the target itself).
62 void RecursivePrintDeps(const Target* target,
63 const Label& default_toolchain,
64 int indent_level) {
65 LabelTargetVector sorted_deps = target->deps();
66 const LabelTargetVector& datadeps = target->datadeps();
67 sorted_deps.insert(sorted_deps.end(), datadeps.begin(), datadeps.end());
68 std::sort(sorted_deps.begin(), sorted_deps.end(),
69 LabelPtrLabelLess<Target>());
71 std::string indent(indent_level * 2, ' ');
72 for (size_t i = 0; i < sorted_deps.size(); i++) {
73 // Don't print groups. Groups are flattened such that the deps of the
74 // group are added directly to the target that depended on the group.
75 // Printing and recursing into groups here will cause such targets to be
76 // duplicated.
78 // It would be much more intuitive to do the opposite and not display the
79 // deps that were copied from the group to the target and instead display
80 // the group, but the source of those dependencies is not tracked.
81 if (sorted_deps[i].ptr->output_type() == Target::GROUP)
82 continue;
84 OutputString(indent +
85 sorted_deps[i].label.GetUserVisibleName(default_toolchain) + "\n");
86 RecursivePrintDeps(sorted_deps[i].ptr, default_toolchain, indent_level + 1);
90 void PrintDeps(const Target* target, bool display_header) {
91 const CommandLine* cmdline = CommandLine::ForCurrentProcess();
92 Label toolchain_label = target->label().GetToolchainLabel();
94 // Tree mode is separate.
95 if (cmdline->HasSwitch("tree")) {
96 if (display_header)
97 OutputString("\nDependency tree:\n");
98 RecursivePrintDeps(target, toolchain_label, 1);
99 return;
102 // Collect the deps to display.
103 std::vector<Label> deps;
104 if (cmdline->HasSwitch("all")) {
105 if (display_header)
106 OutputString("\nAll recursive dependencies:\n");
108 std::set<Label> all_deps;
109 RecursiveCollectChildDeps(target, &all_deps);
110 for (std::set<Label>::iterator i = all_deps.begin();
111 i != all_deps.end(); ++i)
112 deps.push_back(*i);
113 } else {
114 if (display_header) {
115 OutputString("\nDirect dependencies "
116 "(try also \"--all\" and \"--tree\"):\n");
119 const LabelTargetVector& target_deps = target->deps();
120 for (size_t i = 0; i < target_deps.size(); i++)
121 deps.push_back(target_deps[i].label);
123 const LabelTargetVector& target_datadeps = target->datadeps();
124 for (size_t i = 0; i < target_datadeps.size(); i++)
125 deps.push_back(target_datadeps[i].label);
128 std::sort(deps.begin(), deps.end());
129 for (size_t i = 0; i < deps.size(); i++)
130 OutputString(" " + deps[i].GetUserVisibleName(toolchain_label) + "\n");
133 void PrintForwardDependentConfigsFrom(const Target* target,
134 bool display_header) {
135 if (target->forward_dependent_configs().empty())
136 return;
138 if (display_header)
139 OutputString("\nforward_dependent_configs_from:\n");
141 // Collect the sorted list of deps.
142 std::vector<Label> forward;
143 for (size_t i = 0; i < target->forward_dependent_configs().size(); i++)
144 forward.push_back(target->forward_dependent_configs()[i].label);
145 std::sort(forward.begin(), forward.end());
147 Label toolchain_label = target->label().GetToolchainLabel();
148 for (size_t i = 0; i < forward.size(); i++)
149 OutputString(" " + forward[i].GetUserVisibleName(toolchain_label) + "\n");
152 // libs and lib_dirs are special in that they're inherited. We don't currently
153 // implement a blame feature for this since the bottom-up inheritance makes
154 // this difficult.
155 void PrintLibDirs(const Target* target, bool display_header) {
156 const OrderedSet<SourceDir>& lib_dirs = target->all_lib_dirs();
157 if (lib_dirs.empty())
158 return;
160 if (display_header)
161 OutputString("\nlib_dirs\n");
163 for (size_t i = 0; i < lib_dirs.size(); i++)
164 OutputString(" " + FormatSourceDir(lib_dirs[i]) + "\n");
167 void PrintLibs(const Target* target, bool display_header) {
168 const OrderedSet<std::string>& libs = target->all_libs();
169 if (libs.empty())
170 return;
172 if (display_header)
173 OutputString("\nlibs\n");
175 for (size_t i = 0; i < libs.size(); i++)
176 OutputString(" " + libs[i] + "\n");
179 void PrintPublic(const Target* target, bool display_header) {
180 if (display_header)
181 OutputString("\npublic:\n");
183 if (target->all_headers_public()) {
184 OutputString(" [All headers listed in the sources are public.]\n");
185 return;
188 Target::FileList public_headers = target->public_headers();
189 std::sort(public_headers.begin(), public_headers.end());
190 for (size_t i = 0; i < public_headers.size(); i++)
191 OutputString(" " + public_headers[i].value() + "\n");
194 void PrintVisibility(const Target* target, bool display_header) {
195 if (display_header)
196 OutputString("\nvisibility:\n");
198 OutputString(target->visibility().Describe(2, false));
201 void PrintConfigsVector(const Target* target,
202 const LabelConfigVector& configs,
203 const std::string& heading,
204 bool display_header) {
205 if (configs.empty())
206 return;
208 // Don't sort since the order determines how things are processed.
209 if (display_header)
210 OutputString("\n" + heading + " (in order applying):\n");
212 Label toolchain_label = target->label().GetToolchainLabel();
213 for (size_t i = 0; i < configs.size(); i++) {
214 OutputString(" " +
215 configs[i].label.GetUserVisibleName(toolchain_label) + "\n");
219 void PrintConfigs(const Target* target, bool display_header) {
220 PrintConfigsVector(target, target->configs(), "configs", display_header);
223 void PrintDirectDependentConfigs(const Target* target, bool display_header) {
224 PrintConfigsVector(target, target->direct_dependent_configs(),
225 "direct_dependent_configs", display_header);
228 void PrintAllDependentConfigs(const Target* target, bool display_header) {
229 PrintConfigsVector(target, target->all_dependent_configs(),
230 "all_dependent_configs", display_header);
233 void PrintFileList(const Target::FileList& files,
234 const std::string& header,
235 bool indent_extra,
236 bool display_header) {
237 if (files.empty())
238 return;
240 if (display_header)
241 OutputString("\n" + header + ":\n");
243 std::string indent = indent_extra ? " " : " ";
245 Target::FileList sorted = files;
246 std::sort(sorted.begin(), sorted.end());
247 for (size_t i = 0; i < sorted.size(); i++)
248 OutputString(indent + sorted[i].value() + "\n");
251 void PrintSources(const Target* target, bool display_header) {
252 PrintFileList(target->sources(), "sources", false, display_header);
255 void PrintInputs(const Target* target, bool display_header) {
256 PrintFileList(target->inputs(), "inputs", false, display_header);
259 void PrintOutputs(const Target* target, bool display_header) {
260 if (target->output_type() == Target::ACTION) {
261 // Just display the outputs directly.
262 PrintFileList(target->action_values().outputs(), "outputs", false,
263 display_header);
264 } else if (target->output_type() == Target::ACTION_FOREACH) {
265 // Display both the output pattern and resolved list.
266 if (display_header)
267 OutputString("\noutputs:\n");
269 // Display the pattern.
270 OutputString(" Output pattern:\n");
271 PrintFileList(target->action_values().outputs(), "", true, false);
273 // Now display what that resolves to given the sources.
274 OutputString("\n Resolved output file list:\n");
276 std::vector<std::string> output_strings;
277 FileTemplate file_template = FileTemplate::GetForTargetOutputs(target);
278 for (size_t i = 0; i < target->sources().size(); i++)
279 file_template.Apply(target->sources()[i], &output_strings);
281 std::sort(output_strings.begin(), output_strings.end());
282 for (size_t i = 0; i < output_strings.size(); i++) {
283 OutputString(" " + output_strings[i] + "\n");
288 void PrintScript(const Target* target, bool display_header) {
289 if (display_header)
290 OutputString("\nscript:\n");
291 OutputString(" " + target->action_values().script().value() + "\n");
294 void PrintArgs(const Target* target, bool display_header) {
295 if (display_header)
296 OutputString("\nargs:\n");
297 for (size_t i = 0; i < target->action_values().args().size(); i++)
298 OutputString(" " + target->action_values().args()[i] + "\n");
301 void PrintDepfile(const Target* target, bool display_header) {
302 if (target->action_values().depfile().value().empty())
303 return;
304 if (display_header)
305 OutputString("\ndepfile:\n");
306 OutputString(" " + target->action_values().depfile().value() + "\n");
309 // Attribute the origin for attributing from where a target came from. Does
310 // nothing if the input is null or it does not have a location.
311 void OutputSourceOfDep(const ParseNode* origin, std::ostream& out) {
312 if (!origin)
313 return;
314 Location location = origin->GetRange().begin();
315 out << " (Added by " + location.file()->name().value() << ":"
316 << location.line_number() << ")\n";
319 // Templatized writer for writing out different config value types.
320 template<typename T> struct DescValueWriter {};
321 template<> struct DescValueWriter<std::string> {
322 void operator()(const std::string& str, std::ostream& out) const {
323 out << " " << str << "\n";
326 template<> struct DescValueWriter<SourceDir> {
327 void operator()(const SourceDir& dir, std::ostream& out) const {
328 out << " " << FormatSourceDir(dir) << "\n";
332 // Writes a given config value type to the string, optionally with attribution.
333 // This should match RecursiveTargetConfigToStream in the order it traverses.
334 template<typename T> void OutputRecursiveTargetConfig(
335 const Target* target,
336 const char* header_name,
337 const std::vector<T>& (ConfigValues::* getter)() const) {
338 bool display_blame = CommandLine::ForCurrentProcess()->HasSwitch("blame");
340 DescValueWriter<T> writer;
341 std::ostringstream out;
343 for (ConfigValuesIterator iter(target); !iter.done(); iter.Next()) {
344 if ((iter.cur().*getter)().empty())
345 continue;
347 // Optional blame sub-head.
348 if (display_blame) {
349 const Config* config = iter.GetCurrentConfig();
350 if (config) {
351 // Source of this value is a config.
352 out << " From " << config->label().GetUserVisibleName(false) << "\n";
353 OutputSourceOfDep(iter.origin(), out);
354 } else {
355 // Source of this value is the target itself.
356 out << " From " << target->label().GetUserVisibleName(false) << "\n";
360 // Actual values.
361 ConfigValuesToStream(iter.cur(), getter, writer, out);
364 std::string out_str = out.str();
365 if (!out_str.empty()) {
366 OutputString("\n" + std::string(header_name) + "\n");
367 OutputString(out_str);
371 } // namespace
373 // desc ------------------------------------------------------------------------
375 const char kDesc[] = "desc";
376 const char kDesc_HelpShort[] =
377 "desc: Show lots of insightful information about a target.";
378 const char kDesc_Help[] =
379 "gn desc <target label> [<what to show>] [--blame] [--all | --tree]\n"
380 " Displays information about a given labeled target.\n"
381 "\n"
382 "Possibilities for <what to show>:\n"
383 " (If unspecified an overall summary will be displayed.)\n"
384 "\n"
385 " sources\n"
386 " Source files.\n"
387 "\n"
388 " inputs\n"
389 " Additional input dependencies.\n"
390 "\n"
391 " public\n"
392 " Public header files.\n"
393 "\n"
394 " visibility\n"
395 " Prints which targets can depend on this one.\n"
396 "\n"
397 " configs\n"
398 " Shows configs applied to the given target, sorted in the order\n"
399 " they're specified. This includes both configs specified in the\n"
400 " \"configs\" variable, as well as configs pushed onto this target\n"
401 " via dependencies specifying \"all\" or \"direct\" dependent\n"
402 " configs.\n"
403 "\n"
404 " deps [--all | --tree]\n"
405 " Show immediate (or, when \"--all\" or \"--tree\" is specified,\n"
406 " recursive) dependencies of the given target. \"--tree\" shows them\n"
407 " in a tree format. Otherwise, they will be sorted alphabetically.\n"
408 " Both \"deps\" and \"datadeps\" will be included.\n"
409 "\n"
410 " direct_dependent_configs\n"
411 " all_dependent_configs\n"
412 " Shows the labels of configs applied to targets that depend on this\n"
413 " one (either directly or all of them).\n"
414 "\n"
415 " forward_dependent_configs_from\n"
416 " Shows the labels of dependencies for which dependent configs will\n"
417 " be pushed to targets depending on the current one.\n"
418 "\n"
419 " script\n"
420 " args\n"
421 " depfile\n"
422 " Actions only. The script and related values.\n"
423 "\n"
424 " outputs\n"
425 " Outputs for script and copy target types.\n"
426 "\n"
427 " defines [--blame]\n"
428 " include_dirs [--blame]\n"
429 " cflags [--blame]\n"
430 " cflags_cc [--blame]\n"
431 " cflags_cxx [--blame]\n"
432 " ldflags [--blame]\n"
433 " lib_dirs\n"
434 " libs\n"
435 " Shows the given values taken from the target and all configs\n"
436 " applying. See \"--blame\" below.\n"
437 "\n"
438 " --blame\n"
439 " Used with any value specified by a config, this will name\n"
440 " the config that specified the value. This doesn't currently work\n"
441 " for libs and lib_dirs because those are inherited and are more\n"
442 " complicated to figure out the blame (patches welcome).\n"
443 "\n"
444 "Note:\n"
445 " This command will show the full name of directories and source files,\n"
446 " but when directories and source paths are written to the build file,\n"
447 " they will be adjusted to be relative to the build directory. So the\n"
448 " values for paths displayed by this command won't match (but should\n"
449 " mean the same thing).\n"
450 "\n"
451 "Examples:\n"
452 " gn desc //base:base\n"
453 " Summarizes the given target.\n"
454 "\n"
455 " gn desc :base_unittests deps --tree\n"
456 " Shows a dependency tree of the \"base_unittests\" project in\n"
457 " the current directory.\n"
458 "\n"
459 " gn desc //base defines --blame\n"
460 " Shows defines set for the //base:base target, annotated by where\n"
461 " each one was set from.\n";
463 #define OUTPUT_CONFIG_VALUE(name, type) \
464 OutputRecursiveTargetConfig<type>(target, #name, &ConfigValues::name);
466 int RunDesc(const std::vector<std::string>& args) {
467 if (args.size() != 1 && args.size() != 2) {
468 Err(Location(), "You're holding it wrong.",
469 "Usage: \"gn desc <target_name> <what to display>\"").PrintToStdout();
470 return 1;
473 const Target* target = GetTargetForDesc(args);
474 if (!target)
475 return 1;
477 #define CONFIG_VALUE_HANDLER(name, type) \
478 } else if (what == #name) { OUTPUT_CONFIG_VALUE(name, type)
480 if (args.size() == 2) {
481 // User specified one thing to display.
482 const std::string& what = args[1];
483 if (what == "configs") {
484 PrintConfigs(target, false);
485 } else if (what == "direct_dependent_configs") {
486 PrintDirectDependentConfigs(target, false);
487 } else if (what == "all_dependent_configs") {
488 PrintAllDependentConfigs(target, false);
489 } else if (what == "forward_dependent_configs_from") {
490 PrintForwardDependentConfigsFrom(target, false);
491 } else if (what == "sources") {
492 PrintSources(target, false);
493 } else if (what == "public") {
494 PrintPublic(target, false);
495 } else if (what == "visibility") {
496 PrintVisibility(target, false);
497 } else if (what == "inputs") {
498 PrintInputs(target, false);
499 } else if (what == "script") {
500 PrintScript(target, false);
501 } else if (what == "args") {
502 PrintArgs(target, false);
503 } else if (what == "depfile") {
504 PrintDepfile(target, false);
505 } else if (what == "outputs") {
506 PrintOutputs(target, false);
507 } else if (what == "deps") {
508 PrintDeps(target, false);
509 } else if (what == "lib_dirs") {
510 PrintLibDirs(target, false);
511 } else if (what == "libs") {
512 PrintLibs(target, false);
514 CONFIG_VALUE_HANDLER(defines, std::string)
515 CONFIG_VALUE_HANDLER(include_dirs, SourceDir)
516 CONFIG_VALUE_HANDLER(cflags, std::string)
517 CONFIG_VALUE_HANDLER(cflags_c, std::string)
518 CONFIG_VALUE_HANDLER(cflags_cc, std::string)
519 CONFIG_VALUE_HANDLER(cflags_objc, std::string)
520 CONFIG_VALUE_HANDLER(cflags_objcc, std::string)
521 CONFIG_VALUE_HANDLER(ldflags, std::string)
523 } else {
524 OutputString("Don't know how to display \"" + what + "\".\n");
525 return 1;
528 #undef CONFIG_VALUE_HANDLER
529 return 0;
532 // Display summary.
534 // Display this only applicable to binary targets.
535 bool is_binary_output =
536 target->output_type() != Target::GROUP &&
537 target->output_type() != Target::COPY_FILES &&
538 target->output_type() != Target::ACTION &&
539 target->output_type() != Target::ACTION_FOREACH;
541 // Generally we only want to display toolchains on labels when the toolchain
542 // is different than the default one for this target (which we always print
543 // in the header).
544 Label target_toolchain = target->label().GetToolchainLabel();
546 // Header.
547 OutputString("Target: ", DECORATION_YELLOW);
548 OutputString(target->label().GetUserVisibleName(false) + "\n");
549 OutputString("Type: ", DECORATION_YELLOW);
550 OutputString(std::string(
551 Target::GetStringForOutputType(target->output_type())) + "\n");
552 OutputString("Toolchain: ", DECORATION_YELLOW);
553 OutputString(target_toolchain.GetUserVisibleName(false) + "\n");
555 PrintSources(target, true);
556 if (is_binary_output)
557 PrintPublic(target, true);
558 PrintVisibility(target, true);
559 if (is_binary_output)
560 PrintConfigs(target, true);
562 PrintDirectDependentConfigs(target, true);
563 PrintAllDependentConfigs(target, true);
564 PrintForwardDependentConfigsFrom(target, true);
566 PrintInputs(target, true);
568 if (is_binary_output) {
569 OUTPUT_CONFIG_VALUE(defines, std::string)
570 OUTPUT_CONFIG_VALUE(include_dirs, SourceDir)
571 OUTPUT_CONFIG_VALUE(cflags, std::string)
572 OUTPUT_CONFIG_VALUE(cflags_c, std::string)
573 OUTPUT_CONFIG_VALUE(cflags_cc, std::string)
574 OUTPUT_CONFIG_VALUE(cflags_objc, std::string)
575 OUTPUT_CONFIG_VALUE(cflags_objcc, std::string)
576 OUTPUT_CONFIG_VALUE(ldflags, std::string)
579 if (target->output_type() == Target::ACTION ||
580 target->output_type() == Target::ACTION_FOREACH) {
581 PrintScript(target, true);
582 PrintArgs(target, true);
583 PrintDepfile(target, true);
586 if (target->output_type() == Target::ACTION ||
587 target->output_type() == Target::ACTION_FOREACH ||
588 target->output_type() == Target::COPY_FILES) {
589 PrintOutputs(target, true);
592 // Libs can be part of any target and get recursively pushed up the chain,
593 // so always display them, even for groups and such.
594 PrintLibs(target, true);
595 PrintLibDirs(target, true);
597 PrintDeps(target, true);
599 return 0;
602 } // namespace commands