Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / tools / gn / command_desc.cc
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 <algorithm>
6 #include <set>
7 #include <sstream>
8
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/filesystem_utils.h"
14 #include "tools/gn/item.h"
15 #include "tools/gn/label.h"
16 #include "tools/gn/setup.h"
17 #include "tools/gn/standard_out.h"
18 #include "tools/gn/target.h"
19
20 namespace commands {
21
22 namespace {
23
24 // Prints the given directory in a nice way for the user to view.
25 std::string FormatSourceDir(const SourceDir& dir) {
26 #if defined(OS_WIN)
27   // On Windows we fix up system absolute paths to look like native ones.
28   // Internally, they'll look like "/C:\foo\bar/"
29   if (dir.is_system_absolute()) {
30     std::string buf = dir.value();
31     if (buf.size() > 3 && buf[2] == ':') {
32       buf.erase(buf.begin());  // Erase beginning slash.
33       return buf;
34     }
35   }
36 #endif
37   return dir.value();
38 }
39
40 void RecursiveCollectChildDeps(const Target* target, std::set<Label>* result);
41
42 void RecursiveCollectDeps(const Target* target, std::set<Label>* result) {
43   if (result->find(target->label()) != result->end())
44     return;  // Already did this target.
45   result->insert(target->label());
46
47   RecursiveCollectChildDeps(target, result);
48 }
49
50 void RecursiveCollectChildDeps(const Target* target, std::set<Label>* result) {
51   const LabelTargetVector& deps = target->deps();
52   for (size_t i = 0; i < deps.size(); i++)
53     RecursiveCollectDeps(deps[i].ptr, result);
54
55   const LabelTargetVector& datadeps = target->datadeps();
56   for (size_t i = 0; i < datadeps.size(); i++)
57     RecursiveCollectDeps(datadeps[i].ptr, result);
58 }
59
60 // Prints dependencies of the given target (not the target itself).
61 void RecursivePrintDeps(const Target* target,
62                         const Label& default_toolchain,
63                         int indent_level) {
64   LabelTargetVector sorted_deps = target->deps();
65   const LabelTargetVector& datadeps = target->datadeps();
66   sorted_deps.insert(sorted_deps.end(), datadeps.begin(), datadeps.end());
67   std::sort(sorted_deps.begin(), sorted_deps.end(),
68             LabelPtrLabelLess<Target>());
69
70   std::string indent(indent_level * 2, ' ');
71   for (size_t i = 0; i < sorted_deps.size(); i++) {
72     OutputString(indent +
73         sorted_deps[i].label.GetUserVisibleName(default_toolchain) + "\n");
74     RecursivePrintDeps(sorted_deps[i].ptr, default_toolchain, indent_level + 1);
75   }
76 }
77
78 void PrintDeps(const Target* target, bool display_header) {
79   const CommandLine* cmdline = CommandLine::ForCurrentProcess();
80   Label toolchain_label = target->label().GetToolchainLabel();
81
82   // Tree mode is separate.
83   if (cmdline->HasSwitch("tree")) {
84     if (display_header)
85       OutputString("\nDependency tree:\n");
86     RecursivePrintDeps(target, toolchain_label, 1);
87     return;
88   }
89
90   // Collect the deps to display.
91   std::vector<Label> deps;
92   if (cmdline->HasSwitch("all")) {
93     if (display_header)
94       OutputString("\nAll recursive dependencies:\n");
95
96     std::set<Label> all_deps;
97     RecursiveCollectChildDeps(target, &all_deps);
98     for (std::set<Label>::iterator i = all_deps.begin();
99          i != all_deps.end(); ++i)
100       deps.push_back(*i);
101   } else {
102     if (display_header) {
103       OutputString("\nDirect dependencies "
104                    "(try also \"--all\" and \"--tree\"):\n");
105     }
106
107     const LabelTargetVector& target_deps = target->deps();
108     for (size_t i = 0; i < target_deps.size(); i++)
109       deps.push_back(target_deps[i].label);
110
111     const LabelTargetVector& target_datadeps = target->datadeps();
112     for (size_t i = 0; i < target_datadeps.size(); i++)
113       deps.push_back(target_datadeps[i].label);
114   }
115
116   std::sort(deps.begin(), deps.end());
117   for (size_t i = 0; i < deps.size(); i++)
118     OutputString("  " + deps[i].GetUserVisibleName(toolchain_label) + "\n");
119 }
120
121 // libs and lib_dirs are special in that they're inherited. We don't currently
122 // implement a blame feature for this since the bottom-up inheritance makes
123 // this difficult.
124 void PrintLibDirs(const Target* target, bool display_header) {
125   const OrderedSet<SourceDir>& lib_dirs = target->all_lib_dirs();
126   if (lib_dirs.empty())
127     return;
128
129   if (display_header)
130     OutputString("\nlib_dirs\n");
131
132   for (size_t i = 0; i < lib_dirs.size(); i++)
133     OutputString("    " + FormatSourceDir(lib_dirs[i]) + "\n");
134 }
135
136 void PrintLibs(const Target* target, bool display_header) {
137   const OrderedSet<std::string>& libs = target->all_libs();
138   if (libs.empty())
139     return;
140
141   if (display_header)
142     OutputString("\nlibs\n");
143
144   for (size_t i = 0; i < libs.size(); i++)
145     OutputString("    " + libs[i] + "\n");
146 }
147
148 void PrintConfigs(const Target* target, bool display_header) {
149   // Configs (don't sort since the order determines how things are processed).
150   if (display_header)
151     OutputString("\nConfigs (in order applying):\n");
152
153   Label toolchain_label = target->label().GetToolchainLabel();
154   const LabelConfigVector& configs = target->configs();
155   for (size_t i = 0; i < configs.size(); i++) {
156     OutputString("  " +
157         configs[i].label.GetUserVisibleName(toolchain_label) + "\n");
158   }
159 }
160
161 void PrintSources(const Target* target, bool display_header) {
162   if (display_header)
163     OutputString("\nSources:\n");
164
165   Target::FileList sources = target->sources();
166   std::sort(sources.begin(), sources.end());
167   for (size_t i = 0; i < sources.size(); i++)
168     OutputString("  " + sources[i].value() + "\n");
169 }
170
171 // Attribute the origin for attributing from where a target came from. Does
172 // nothing if the input is null or it does not have a location.
173 void OutputSourceOfDep(const ParseNode* origin, std::ostream& out) {
174   if (!origin)
175     return;
176   Location location = origin->GetRange().begin();
177   out << "       (Added by " + location.file()->name().value() << ":"
178       << location.line_number() << ")\n";
179 }
180
181 // Templatized writer for writing out different config value types.
182 template<typename T> struct DescValueWriter {};
183 template<> struct DescValueWriter<std::string> {
184   void operator()(const std::string& str, std::ostream& out) const {
185     out << "    " << str << "\n";
186   }
187 };
188 template<> struct DescValueWriter<SourceDir> {
189   void operator()(const SourceDir& dir, std::ostream& out) const {
190     out << "    " << FormatSourceDir(dir) << "\n";
191   }
192 };
193
194 // Writes a given config value type to the string, optionally with attribution.
195 // This should match RecursiveTargetConfigToStream in the order it traverses.
196 template<typename T> void OutputRecursiveTargetConfig(
197     const Target* target,
198     const char* header_name,
199     const std::vector<T>& (ConfigValues::* getter)() const) {
200   bool display_blame = CommandLine::ForCurrentProcess()->HasSwitch("blame");
201
202   DescValueWriter<T> writer;
203   std::ostringstream out;
204
205   for (ConfigValuesIterator iter(target); !iter.done(); iter.Next()) {
206     if ((iter.cur().*getter)().empty())
207       continue;
208
209     // Optional blame sub-head.
210     if (display_blame) {
211       const Config* config = iter.GetCurrentConfig();
212       if (config) {
213         // Source of this value is a config.
214         out << "  From " << config->label().GetUserVisibleName(false) << "\n";
215         OutputSourceOfDep(iter.origin(), out);
216       } else {
217         // Source of this value is the target itself.
218         out << "  From " << target->label().GetUserVisibleName(false) << "\n";
219       }
220     }
221
222     // Actual values.
223     ConfigValuesToStream(iter.cur(), getter, writer, out);
224   }
225
226   std::string out_str = out.str();
227   if (!out_str.empty()) {
228     OutputString("\n" + std::string(header_name) + "\n");
229     OutputString(out_str);
230   }
231 }
232
233 }  // namespace
234
235 // desc ------------------------------------------------------------------------
236
237 const char kDesc[] = "desc";
238 const char kDesc_HelpShort[] =
239     "desc: Show lots of insightful information about a target.";
240 const char kDesc_Help[] =
241     "gn desc <target label> [<what to show>] [--blame] [--all | --tree]\n"
242     "  Displays information about a given labeled target.\n"
243     "\n"
244     "Possibilities for <what to show>:\n"
245     "  (If unspecified an overall summary will be displayed.)\n"
246     "\n"
247     "  sources\n"
248     "      Source files.\n"
249     "\n"
250     "  configs\n"
251     "      Shows configs applied to the given target, sorted in the order\n"
252     "      they're specified. This includes both configs specified in the\n"
253     "      \"configs\" variable, as well as configs pushed onto this target\n"
254     "      via dependencies specifying \"all\" or \"direct\" dependent\n"
255     "      configs.\n"
256     "\n"
257     "  deps [--all | --tree]\n"
258     "      Show immediate (or, when \"--all\" or \"--tree\" is specified,\n"
259     "      recursive) dependencies of the given target. \"--tree\" shows them\n"
260     "      in a tree format.  Otherwise, they will be sorted alphabetically.\n"
261     "      Both \"deps\" and \"datadeps\" will be included.\n"
262     "\n"
263     "  defines       [--blame]\n"
264     "  include_dirs  [--blame]\n"
265     "  cflags        [--blame]\n"
266     "  cflags_cc     [--blame]\n"
267     "  cflags_cxx    [--blame]\n"
268     "  ldflags       [--blame]\n"
269     "  lib_dirs\n"
270     "  libs\n"
271     "      Shows the given values taken from the target and all configs\n"
272     "      applying. See \"--blame\" below.\n"
273     "\n"
274     "  --blame\n"
275     "      Used with any value specified by a config, this will name\n"
276     "      the config that specified the value. This doesn't currently work\n"
277     "      for libs and lib_dirs because those are inherited and are more\n"
278     "      complicated to figure out the blame (patches welcome).\n"
279     "\n"
280     "Note:\n"
281     "  This command will show the full name of directories and source files,\n"
282     "  but when directories and source paths are written to the build file,\n"
283     "  they will be adjusted to be relative to the build directory. So the\n"
284     "  values for paths displayed by this command won't match (but should\n"
285     "  mean the same thing).\n"
286     "\n"
287     "Examples:\n"
288     "  gn desc //base:base\n"
289     "      Summarizes the given target.\n"
290     "\n"
291     "  gn desc :base_unittests deps --tree\n"
292     "      Shows a dependency tree of the \"base_unittests\" project in\n"
293     "      the current directory.\n"
294     "\n"
295     "  gn desc //base defines --blame\n"
296     "      Shows defines set for the //base:base target, annotated by where\n"
297     "      each one was set from.\n";
298
299 #define OUTPUT_CONFIG_VALUE(name, type) \
300     OutputRecursiveTargetConfig<type>(target, #name, &ConfigValues::name);
301
302 int RunDesc(const std::vector<std::string>& args) {
303   if (args.size() != 1 && args.size() != 2) {
304     Err(Location(), "You're holding it wrong.",
305         "Usage: \"gn desc <target_name> <what to display>\"").PrintToStdout();
306     return 1;
307   }
308
309   const Target* target = GetTargetForDesc(args);
310   if (!target)
311     return 1;
312
313 #define CONFIG_VALUE_HANDLER(name, type) \
314     } else if (what == #name) { OUTPUT_CONFIG_VALUE(name, type)
315
316   if (args.size() == 2) {
317     // User specified one thing to display.
318     const std::string& what = args[1];
319     if (what == "configs") {
320       PrintConfigs(target, false);
321     } else if (what == "sources") {
322       PrintSources(target, false);
323     } else if (what == "deps") {
324       PrintDeps(target, false);
325     } else if (what == "lib_dirs") {
326       PrintLibDirs(target, false);
327     } else if (what == "libs") {
328       PrintLibs(target, false);
329
330     CONFIG_VALUE_HANDLER(defines, std::string)
331     CONFIG_VALUE_HANDLER(include_dirs, SourceDir)
332     CONFIG_VALUE_HANDLER(cflags, std::string)
333     CONFIG_VALUE_HANDLER(cflags_c, std::string)
334     CONFIG_VALUE_HANDLER(cflags_cc, std::string)
335     CONFIG_VALUE_HANDLER(cflags_objc, std::string)
336     CONFIG_VALUE_HANDLER(cflags_objcc, std::string)
337     CONFIG_VALUE_HANDLER(ldflags, std::string)
338
339     } else {
340       OutputString("Don't know how to display \"" + what + "\".\n");
341       return 1;
342     }
343
344 #undef CONFIG_VALUE_HANDLER
345     return 0;
346   }
347
348   // Display summary.
349
350   // Generally we only want to display toolchains on labels when the toolchain
351   // is different than the default one for this target (which we always print
352   // in the header).
353   Label target_toolchain = target->label().GetToolchainLabel();
354
355   // Header.
356   OutputString("Target: ", DECORATION_YELLOW);
357   OutputString(target->label().GetUserVisibleName(false) + "\n");
358   OutputString("Type: ", DECORATION_YELLOW);
359   OutputString(std::string(
360       Target::GetStringForOutputType(target->output_type())) + "\n");
361   OutputString("Toolchain: ", DECORATION_YELLOW);
362   OutputString(target_toolchain.GetUserVisibleName(false) + "\n");
363
364   PrintSources(target, true);
365   PrintConfigs(target, true);
366
367   OUTPUT_CONFIG_VALUE(defines, std::string)
368   OUTPUT_CONFIG_VALUE(include_dirs, SourceDir)
369   OUTPUT_CONFIG_VALUE(cflags, std::string)
370   OUTPUT_CONFIG_VALUE(cflags_c, std::string)
371   OUTPUT_CONFIG_VALUE(cflags_cc, std::string)
372   OUTPUT_CONFIG_VALUE(cflags_objc, std::string)
373   OUTPUT_CONFIG_VALUE(cflags_objcc, std::string)
374   OUTPUT_CONFIG_VALUE(ldflags, std::string)
375   PrintLibs(target, true);
376   PrintLibDirs(target, true);
377
378   PrintDeps(target, true);
379
380   return 0;
381 }
382
383 }  // namespace commands