• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016 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 <memory>
6 #include <set>
7 
8 #include "base/json/json_writer.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "gn/commands.h"
11 #include "gn/config.h"
12 #include "gn/config_values_extractors.h"
13 #include "gn/deps_iterator.h"
14 #include "gn/desc_builder.h"
15 #include "gn/input_file.h"
16 #include "gn/parse_tree.h"
17 #include "gn/resolved_target_data.h"
18 #include "gn/runtime_deps.h"
19 #include "gn/rust_variables.h"
20 #include "gn/scope.h"
21 #include "gn/settings.h"
22 #include "gn/standard_out.h"
23 #include "gn/substitution_writer.h"
24 #include "gn/swift_variables.h"
25 #include "gn/variables.h"
26 
27 // Example structure of Value for single target
28 // (not applicable or empty fields will be omitted depending on target type)
29 //
30 // target_properties = {
31 //   "type" : "output_type", // matching Target::GetStringForOutputType
32 //   "toolchain" : "toolchain_name",
33 //   "visibility" : [ list of visibility pattern descriptions ],
34 //   "test_only" : true or false,
35 //   "check_includes": true or false,
36 //   "allow_circular_includes_from": [ list of target names ],
37 //   "sources" : [ list of source files ],
38 //   "public" : either "*" or [ list of public headers],
39 //   "inputs" : [ list of inputs for target ],
40 //   "configs" : [ list of configs for this target ],
41 //   "public_configs" : [ list of public configs for this target],
42 //   "all_dependent_configs", [ list of all dependent configs for this target],
43 //   "script" : "script for action targets",
44 //   "args" : [ argument list for action targets ],
45 //   "depfile : "file name for action input dependencies",
46 //   "outputs" : [ list of target outputs ],
47 //   "arflags", "asmflags", "cflags", "cflags_c",
48 //   "cflags_cc", "cflags_objc", "cflags_objcc",
49 //   "rustflags" : [ list of flags],
50 //   "rustenv" : [ list of Rust environment variables ],
51 //   "defines" : [ list of preprocessor definitions ],
52 //   "include_dirs" : [ list of include directories ],
53 //   "precompiled_header" : "name of precompiled header file",
54 //   "precompiled_source" : "path to precompiled source",
55 //   "deps : [ list of target dependencies ],
56 //   "gen_deps : [ list of generate dependencies ],
57 //   "libs" : [ list of libraries ],
58 //   "lib_dirs" : [ list of library directories ]
59 //   "metadata" : [ dictionary of target metadata values ]
60 //   "data_keys" : [ list of target data keys ]
61 //   "walk_keys" : [ list of target walk keys ]
62 //   "crate_root" : "root file of a Rust target"
63 //   "crate_name" : "name of a Rust target"
64 //   "rebase" : true or false
65 //   "output_conversion" : "string for output conversion"
66 //   "response_file_contents": [ list of response file contents entries ]
67 // }
68 //
69 // Optionally, if "what" is specified while generating description, two other
70 // properties can be requested that are not included by default. First the
71 // runtime dependendencies (see "gn help runtime_deps"):
72 //
73 //   "runtime_deps" : [list of computed runtime dependencies]
74 //
75 // Second, for targets whose sources map to outputs (binary targets,
76 // action_foreach, and copies with non-constant outputs), the "source_outputs"
77 // indicates the mapping from source to output file(s):
78 //
79 //   "source_outputs" : {
80 //      "source_file x" : [ list of outputs for source file x ]
81 //      "source_file y" : [ list of outputs for source file y ]
82 //      ...
83 //   }
84 
85 namespace {
86 
FormatSourceDir(const SourceDir & dir)87 std::string FormatSourceDir(const SourceDir& dir) {
88 #if defined(OS_WIN)
89   // On Windows we fix up system absolute paths to look like native ones.
90   // Internally, they'll look like "/C:\foo\bar/"
91   if (dir.is_system_absolute()) {
92     std::string buf = dir.value();
93     if (buf.size() > 3 && buf[2] == ':') {
94       buf.erase(buf.begin());  // Erase beginning slash.
95       return buf;
96     }
97   }
98 #endif
99   return dir.value();
100 }
101 
102 void RecursiveCollectChildDeps(const Target* target, TargetSet* result);
103 
RecursiveCollectDeps(const Target * target,TargetSet * result)104 void RecursiveCollectDeps(const Target* target, TargetSet* result) {
105   if (!result->add(target))
106     return;  // Already did this target.
107 
108   RecursiveCollectChildDeps(target, result);
109 }
110 
RecursiveCollectChildDeps(const Target * target,TargetSet * result)111 void RecursiveCollectChildDeps(const Target* target, TargetSet* result) {
112   for (const auto& pair : target->GetDeps(Target::DEPS_ALL))
113     RecursiveCollectDeps(pair.ptr, result);
114 }
115 
116 // Common functionality for target and config description builder
117 class BaseDescBuilder {
118  public:
119   using ValuePtr = std::unique_ptr<base::Value>;
120 
BaseDescBuilder(const std::set<std::string> & what,bool all,bool tree,bool blame)121   BaseDescBuilder(const std::set<std::string>& what,
122                   bool all,
123                   bool tree,
124                   bool blame)
125       : what_(what), all_(all), tree_(tree), blame_(blame) {}
126 
127  protected:
128   virtual Label GetToolchainLabel() const = 0;
129 
what(const std::string & w) const130   bool what(const std::string& w) const {
131     return what_.empty() || what_.find(w) != what_.end();
132   }
133 
134   template <typename T>
RenderValue(const std::vector<T> & vector)135   ValuePtr RenderValue(const std::vector<T>& vector) {
136     auto res = std::make_unique<base::ListValue>();
137     for (const auto& v : vector)
138       res->Append(RenderValue(v));
139 
140     return res;
141   }
142 
RenderValue(const std::string & s,bool optional=false)143   ValuePtr RenderValue(const std::string& s, bool optional = false) {
144     return (s.empty() && optional) ? std::make_unique<base::Value>()
145                                    : ValuePtr(new base::Value(s));
146   }
147 
RenderValue(const SourceDir & d)148   ValuePtr RenderValue(const SourceDir& d) {
149     return d.is_null() ? std::make_unique<base::Value>()
150                        : ValuePtr(new base::Value(FormatSourceDir(d)));
151   }
152 
RenderValue(const SourceFile & f)153   ValuePtr RenderValue(const SourceFile& f) {
154     return f.is_null() ? std::make_unique<base::Value>()
155                        : ValuePtr(new base::Value(f.value()));
156   }
157 
RenderValue(const SourceFile * f)158   ValuePtr RenderValue(const SourceFile* f) { return RenderValue(*f); }
159 
RenderValue(const LibFile & lib)160   ValuePtr RenderValue(const LibFile& lib) {
161     if (lib.is_source_file())
162       return RenderValue(lib.source_file());
163     return RenderValue(lib.value());
164   }
165 
166   template <typename T>
ToBaseValue(const std::vector<T> & vector)167   base::Value ToBaseValue(const std::vector<T>& vector) {
168     base::ListValue res;
169     for (const auto& v : vector)
170       res.GetList().emplace_back(ToBaseValue(v));
171     return std::move(res);
172   }
173 
ToBaseValue(const Scope * scope)174   base::Value ToBaseValue(const Scope* scope) {
175     base::DictionaryValue res;
176     Scope::KeyValueMap map;
177     scope->GetCurrentScopeValues(&map);
178     for (const auto& v : map)
179       res.SetKey(v.first, ToBaseValue(v.second));
180     return std::move(res);
181   }
182 
ToBaseValue(const Value & val)183   base::Value ToBaseValue(const Value& val) {
184     switch (val.type()) {
185       case Value::STRING:
186         return base::Value(val.string_value());
187       case Value::INTEGER:
188         return base::Value(int(val.int_value()));
189       case Value::BOOLEAN:
190         return base::Value(val.boolean_value());
191       case Value::SCOPE:
192         return ToBaseValue(val.scope_value());
193       case Value::LIST:
194         return ToBaseValue(val.list_value());
195       case Value::NONE:
196         return base::Value();
197     }
198     NOTREACHED();
199     return base::Value();
200   }
201 
202   template <class VectorType>
FillInConfigVector(base::ListValue * out,const VectorType & configs,int indent=0)203   void FillInConfigVector(base::ListValue* out,
204                           const VectorType& configs,
205                           int indent = 0) {
206     for (const auto& config : configs) {
207       std::string name(indent * 2, ' ');
208       name.append(config.label.GetUserVisibleName(GetToolchainLabel()));
209       out->AppendString(name);
210       if (tree_)
211         FillInConfigVector(out, config.ptr->configs(), indent + 1);
212     }
213   }
214 
FillInPrecompiledHeader(base::DictionaryValue * out,const ConfigValues & values)215   void FillInPrecompiledHeader(base::DictionaryValue* out,
216                                const ConfigValues& values) {
217     if (what(variables::kPrecompiledHeader) &&
218         !values.precompiled_header().empty()) {
219       out->SetWithoutPathExpansion(
220           variables::kPrecompiledHeader,
221           RenderValue(values.precompiled_header(), true));
222     }
223     if (what(variables::kPrecompiledSource) &&
224         !values.precompiled_source().is_null()) {
225       out->SetWithoutPathExpansion(variables::kPrecompiledSource,
226                                    RenderValue(values.precompiled_source()));
227     }
228   }
229 
230   std::set<std::string> what_;
231   bool all_;
232   bool tree_;
233   bool blame_;
234 };
235 
236 class ConfigDescBuilder : public BaseDescBuilder {
237  public:
ConfigDescBuilder(const Config * config,const std::set<std::string> & what)238   ConfigDescBuilder(const Config* config, const std::set<std::string>& what)
239       : BaseDescBuilder(what, false, false, false), config_(config) {}
240 
BuildDescription()241   std::unique_ptr<base::DictionaryValue> BuildDescription() {
242     auto res = std::make_unique<base::DictionaryValue>();
243     const ConfigValues& values = config_->resolved_values();
244 
245     if (what_.empty())
246       res->SetKey(
247           "toolchain",
248           base::Value(
249               config_->label().GetToolchainLabel().GetUserVisibleName(false)));
250 
251     if (what(variables::kConfigs) && !config_->configs().empty()) {
252       auto configs = std::make_unique<base::ListValue>();
253       FillInConfigVector(configs.get(), config_->configs().vector());
254       res->SetWithoutPathExpansion(variables::kConfigs, std::move(configs));
255     }
256 
257     if (what(variables::kVisibility)) {
258       res->SetWithoutPathExpansion(variables::kVisibility,
259                                    config_->visibility().AsValue());
260     }
261 
262 #define CONFIG_VALUE_ARRAY_HANDLER(name, type)                        \
263   if (what(#name)) {                                                  \
264     ValuePtr ptr =                                                    \
265         render_config_value_array<type>(values, &ConfigValues::name); \
266     if (ptr) {                                                        \
267       res->SetWithoutPathExpansion(#name, std::move(ptr));            \
268     }                                                                 \
269   }
270     CONFIG_VALUE_ARRAY_HANDLER(arflags, std::string)
271     CONFIG_VALUE_ARRAY_HANDLER(asmflags, std::string)
272     CONFIG_VALUE_ARRAY_HANDLER(cflags, std::string)
273     CONFIG_VALUE_ARRAY_HANDLER(cflags_c, std::string)
274     CONFIG_VALUE_ARRAY_HANDLER(cflags_cc, std::string)
275     CONFIG_VALUE_ARRAY_HANDLER(cflags_objc, std::string)
276     CONFIG_VALUE_ARRAY_HANDLER(cflags_objcc, std::string)
277     CONFIG_VALUE_ARRAY_HANDLER(defines, std::string)
278     CONFIG_VALUE_ARRAY_HANDLER(frameworks, std::string)
279     CONFIG_VALUE_ARRAY_HANDLER(framework_dirs, SourceDir)
280     CONFIG_VALUE_ARRAY_HANDLER(include_dirs, SourceDir)
281     CONFIG_VALUE_ARRAY_HANDLER(inputs, SourceFile)
282     CONFIG_VALUE_ARRAY_HANDLER(ldflags, std::string)
283     CONFIG_VALUE_ARRAY_HANDLER(lib_dirs, SourceDir)
284     CONFIG_VALUE_ARRAY_HANDLER(libs, LibFile)
285     CONFIG_VALUE_ARRAY_HANDLER(rustflags, std::string)
286     CONFIG_VALUE_ARRAY_HANDLER(swiftflags, std::string)
287 
288 #undef CONFIG_VALUE_ARRAY_HANDLER
289 
290     FillInPrecompiledHeader(res.get(), values);
291 
292     return res;
293   }
294 
295  protected:
GetToolchainLabel() const296   Label GetToolchainLabel() const override {
297     return config_->label().GetToolchainLabel();
298   }
299 
300  private:
301   template <typename T>
render_config_value_array(const ConfigValues & values,const std::vector<T> & (ConfigValues::* getter)()const)302   ValuePtr render_config_value_array(
303       const ConfigValues& values,
304       const std::vector<T>& (ConfigValues::*getter)() const) {
305     auto res = std::make_unique<base::ListValue>();
306 
307     for (const T& cur : (values.*getter)())
308       res->Append(RenderValue(cur));
309 
310     return res->empty() ? nullptr : std::move(res);
311   }
312 
313   const Config* config_;
314 };
315 
316 class TargetDescBuilder : public BaseDescBuilder {
317  public:
TargetDescBuilder(const Target * target,const std::set<std::string> & what,bool all,bool tree,bool blame)318   TargetDescBuilder(const Target* target,
319                     const std::set<std::string>& what,
320                     bool all,
321                     bool tree,
322                     bool blame)
323       : BaseDescBuilder(what, all, tree, blame), target_(target) {}
324 
BuildDescription()325   std::unique_ptr<base::DictionaryValue> BuildDescription() {
326     auto res = std::make_unique<base::DictionaryValue>();
327     bool is_binary_output = target_->IsBinary();
328 
329     if (what_.empty()) {
330       res->SetKey(
331           "type",
332           base::Value(Target::GetStringForOutputType(target_->output_type())));
333       res->SetKey(
334           "toolchain",
335           base::Value(
336               target_->label().GetToolchainLabel().GetUserVisibleName(false)));
337     }
338 
339     if (target_->source_types_used().RustSourceUsed()) {
340       if (what(variables::kRustCrateRoot)) {
341         res->SetWithoutPathExpansion(
342             variables::kRustCrateRoot,
343             RenderValue(target_->rust_values().crate_root()));
344       }
345       if (what(variables::kRustCrateName)) {
346         res->SetKey(variables::kRustCrateName,
347                     base::Value(target_->rust_values().crate_name()));
348       }
349     }
350 
351     if (target_->source_types_used().SwiftSourceUsed()) {
352       if (what(variables::kSwiftBridgeHeader)) {
353         res->SetWithoutPathExpansion(
354             variables::kSwiftBridgeHeader,
355             RenderValue(target_->swift_values().bridge_header()));
356       }
357       if (what(variables::kSwiftModuleName)) {
358         res->SetKey(variables::kSwiftModuleName,
359                     base::Value(target_->swift_values().module_name()));
360       }
361     }
362 
363     // General target meta variables.
364 
365     if (what(variables::kMetadata)) {
366       base::DictionaryValue metadata;
367       for (const auto& v : target_->metadata().contents())
368         metadata.SetKey(v.first, ToBaseValue(v.second));
369       res->SetKey(variables::kMetadata, std::move(metadata));
370     }
371 
372     if (what(variables::kVisibility))
373       res->SetWithoutPathExpansion(variables::kVisibility,
374                                    target_->visibility().AsValue());
375 
376     if (what(variables::kTestonly))
377       res->SetKey(variables::kTestonly, base::Value(target_->testonly()));
378 
379     if (is_binary_output) {
380       if (what(variables::kCheckIncludes))
381         res->SetKey(variables::kCheckIncludes,
382                     base::Value(target_->check_includes()));
383 
384       if (what(variables::kAllowCircularIncludesFrom)) {
385         auto labels = std::make_unique<base::ListValue>();
386         for (const auto& cur : target_->allow_circular_includes_from())
387           labels->AppendString(cur.GetUserVisibleName(GetToolchainLabel()));
388 
389         res->SetWithoutPathExpansion(variables::kAllowCircularIncludesFrom,
390                                      std::move(labels));
391       }
392     }
393 
394     if (what(variables::kSources) && !target_->sources().empty())
395       res->SetWithoutPathExpansion(variables::kSources,
396                                    RenderValue(target_->sources()));
397 
398     if (what(variables::kOutputName) && !target_->output_name().empty())
399       res->SetKey(variables::kOutputName, base::Value(target_->output_name()));
400 
401     if (what(variables::kOutputDir) && !target_->output_dir().is_null())
402       res->SetWithoutPathExpansion(variables::kOutputDir,
403                                    RenderValue(target_->output_dir()));
404 
405     if (what(variables::kOutputExtension) && target_->output_extension_set())
406       res->SetKey(variables::kOutputExtension,
407                   base::Value(target_->output_extension()));
408 
409     if (what(variables::kPublic)) {
410       if (target_->all_headers_public())
411         res->SetKey(variables::kPublic, base::Value("*"));
412       else
413         res->SetWithoutPathExpansion(variables::kPublic,
414                                      RenderValue(target_->public_headers()));
415     }
416 
417     if (what(variables::kInputs)) {
418       std::vector<const SourceFile*> inputs;
419       for (ConfigValuesIterator iter(target_); !iter.done(); iter.Next()) {
420         for (const auto& input : iter.cur().inputs())
421           inputs.push_back(&input);
422       }
423       if (!inputs.empty())
424         res->SetWithoutPathExpansion(variables::kInputs, RenderValue(inputs));
425     }
426 
427     if (is_binary_output && what(variables::kConfigs) &&
428         !target_->configs().empty()) {
429       auto configs = std::make_unique<base::ListValue>();
430       FillInConfigVector(configs.get(), target_->configs().vector());
431       res->SetWithoutPathExpansion(variables::kConfigs, std::move(configs));
432     }
433 
434     if (what(variables::kPublicConfigs) && !target_->public_configs().empty()) {
435       auto configs = std::make_unique<base::ListValue>();
436       FillInConfigVector(configs.get(), target_->public_configs());
437       res->SetWithoutPathExpansion(variables::kPublicConfigs,
438                                    std::move(configs));
439     }
440 
441     if (what(variables::kAllDependentConfigs) &&
442         !target_->all_dependent_configs().empty()) {
443       auto configs = std::make_unique<base::ListValue>();
444       FillInConfigVector(configs.get(), target_->all_dependent_configs());
445       res->SetWithoutPathExpansion(variables::kAllDependentConfigs,
446                                    std::move(configs));
447     }
448 
449     // Action
450     if (target_->output_type() == Target::ACTION ||
451         target_->output_type() == Target::ACTION_FOREACH) {
452       if (what(variables::kScript))
453         res->SetKey(variables::kScript,
454                     base::Value(target_->action_values().script().value()));
455 
456       if (what(variables::kArgs)) {
457         auto args = std::make_unique<base::ListValue>();
458         for (const auto& elem : target_->action_values().args().list())
459           args->AppendString(elem.AsString());
460 
461         res->SetWithoutPathExpansion(variables::kArgs, std::move(args));
462       }
463       if (what(variables::kResponseFileContents) &&
464           !target_->action_values().rsp_file_contents().list().empty()) {
465         auto rsp_file_contents = std::make_unique<base::ListValue>();
466         for (const auto& elem :
467              target_->action_values().rsp_file_contents().list())
468           rsp_file_contents->AppendString(elem.AsString());
469 
470         res->SetWithoutPathExpansion(variables::kResponseFileContents,
471                                      std::move(rsp_file_contents));
472       }
473       if (what(variables::kDepfile) &&
474           !target_->action_values().depfile().empty()) {
475         res->SetKey(variables::kDepfile,
476                     base::Value(target_->action_values().depfile().AsString()));
477       }
478     }
479 
480     if (target_->output_type() != Target::SOURCE_SET &&
481         target_->output_type() != Target::GROUP &&
482         target_->output_type() != Target::BUNDLE_DATA) {
483       if (what(variables::kOutputs))
484         FillInOutputs(res.get());
485     }
486 
487     // Source outputs are only included when specifically asked for it
488     if (what_.find("source_outputs") != what_.end())
489       FillInSourceOutputs(res.get());
490 
491     if (target_->output_type() == Target::CREATE_BUNDLE && what("bundle_data"))
492       FillInBundle(res.get());
493 
494     if (is_binary_output) {
495 #define CONFIG_VALUE_ARRAY_HANDLER(name, type, config)                    \
496   if (what(#name)) {                                                      \
497     ValuePtr ptr = RenderConfigValues<type>(config, &ConfigValues::name); \
498     if (ptr) {                                                            \
499       res->SetWithoutPathExpansion(#name, std::move(ptr));                \
500     }                                                                     \
501   }
502       CONFIG_VALUE_ARRAY_HANDLER(arflags, std::string,
503                                  kRecursiveWriterKeepDuplicates)
504       CONFIG_VALUE_ARRAY_HANDLER(asmflags, std::string,
505                                  kRecursiveWriterKeepDuplicates)
506       CONFIG_VALUE_ARRAY_HANDLER(cflags, std::string,
507                                  kRecursiveWriterKeepDuplicates)
508       CONFIG_VALUE_ARRAY_HANDLER(cflags_c, std::string,
509                                  kRecursiveWriterKeepDuplicates)
510       CONFIG_VALUE_ARRAY_HANDLER(cflags_cc, std::string,
511                                  kRecursiveWriterKeepDuplicates)
512       CONFIG_VALUE_ARRAY_HANDLER(cflags_objc, std::string,
513                                  kRecursiveWriterKeepDuplicates)
514       CONFIG_VALUE_ARRAY_HANDLER(cflags_objcc, std::string,
515                                  kRecursiveWriterKeepDuplicates)
516       CONFIG_VALUE_ARRAY_HANDLER(rustflags, std::string,
517                                  kRecursiveWriterKeepDuplicates)
518       CONFIG_VALUE_ARRAY_HANDLER(rustenv, std::string,
519                                  kRecursiveWriterKeepDuplicates)
520       CONFIG_VALUE_ARRAY_HANDLER(defines, std::string,
521                                  kRecursiveWriterSkipDuplicates)
522       CONFIG_VALUE_ARRAY_HANDLER(include_dirs, SourceDir,
523                                  kRecursiveWriterSkipDuplicates)
524       CONFIG_VALUE_ARRAY_HANDLER(inputs, SourceFile,
525                                  kRecursiveWriterKeepDuplicates)
526       CONFIG_VALUE_ARRAY_HANDLER(ldflags, std::string,
527                                  kRecursiveWriterKeepDuplicates)
528       CONFIG_VALUE_ARRAY_HANDLER(swiftflags, std::string,
529                                  kRecursiveWriterKeepDuplicates)
530 #undef CONFIG_VALUE_ARRAY_HANDLER
531 
532       // Libs and lib_dirs are handled specially below.
533 
534       if (what(variables::kExterns)) {
535         base::DictionaryValue externs;
536         for (ConfigValuesIterator iter(target_); !iter.done(); iter.Next()) {
537           const ConfigValues& cur = iter.cur();
538           for (const auto& e : cur.externs()) {
539             externs.SetKey(e.first, base::Value(e.second.value()));
540           }
541         }
542         res->SetKey(variables::kExterns, std::move(externs));
543       }
544 
545       FillInPrecompiledHeader(res.get(), target_->config_values());
546     }
547 
548     // GeneratedFile vars.
549     if (target_->output_type() == Target::GENERATED_FILE) {
550       if (what(variables::kWriteOutputConversion)) {
551         res->SetKey(variables::kWriteOutputConversion,
552                     ToBaseValue(target_->output_conversion()));
553       }
554       if (what(variables::kDataKeys)) {
555         base::ListValue keys;
556         for (const auto& k : target_->data_keys())
557           keys.GetList().push_back(base::Value(k));
558         res->SetKey(variables::kDataKeys, std::move(keys));
559       }
560       if (what(variables::kRebase)) {
561         res->SetWithoutPathExpansion(variables::kRebase,
562                                      RenderValue(target_->rebase()));
563       }
564       if (what(variables::kWalkKeys)) {
565         base::ListValue keys;
566         for (const auto& k : target_->walk_keys())
567           keys.GetList().push_back(base::Value(k));
568         res->SetKey(variables::kWalkKeys, std::move(keys));
569       }
570     }
571 
572     if (what(variables::kDeps))
573       res->SetWithoutPathExpansion(variables::kDeps, RenderDeps());
574 
575     if (what(variables::kGenDeps) && !target_->gen_deps().empty())
576       res->SetWithoutPathExpansion(variables::kGenDeps, RenderGenDeps());
577 
578     // Runtime deps are special, print only when explicitly asked for and not in
579     // overview mode.
580     if (what_.find("runtime_deps") != what_.end())
581       res->SetWithoutPathExpansion("runtime_deps", RenderRuntimeDeps());
582 
583     // libs and lib_dirs are special in that they're inherited. We don't
584     // currently implement a blame feature for this since the bottom-up
585     // inheritance makes this difficult.
586 
587     ResolvedTargetData resolved;
588 
589     // Libs can be part of any target and get recursively pushed up the chain,
590     // so display them regardless of target type.
591     if (what(variables::kLibs)) {
592       const auto& all_libs = resolved.GetLinkedLibraries(target_);
593       if (!all_libs.empty()) {
594         auto libs = std::make_unique<base::ListValue>();
595         for (size_t i = 0; i < all_libs.size(); i++)
596           libs->AppendString(all_libs[i].value());
597         res->SetWithoutPathExpansion(variables::kLibs, std::move(libs));
598       }
599     }
600 
601     if (what(variables::kLibDirs)) {
602       const auto& all_lib_dirs = resolved.GetLinkedLibraryDirs(target_);
603       if (!all_lib_dirs.empty()) {
604         auto lib_dirs = std::make_unique<base::ListValue>();
605         for (size_t i = 0; i < all_lib_dirs.size(); i++)
606           lib_dirs->AppendString(FormatSourceDir(all_lib_dirs[i]));
607         res->SetWithoutPathExpansion(variables::kLibDirs, std::move(lib_dirs));
608       }
609     }
610 
611     if (what(variables::kFrameworks)) {
612       const auto& all_frameworks = resolved.GetLinkedFrameworks(target_);
613       if (!all_frameworks.empty()) {
614         auto frameworks = std::make_unique<base::ListValue>();
615         for (size_t i = 0; i < all_frameworks.size(); i++)
616           frameworks->AppendString(all_frameworks[i]);
617         res->SetWithoutPathExpansion(variables::kFrameworks,
618                                      std::move(frameworks));
619       }
620     }
621     if (what(variables::kWeakFrameworks)) {
622       const auto& weak_frameworks = resolved.GetLinkedWeakFrameworks(target_);
623       if (!weak_frameworks.empty()) {
624         auto frameworks = std::make_unique<base::ListValue>();
625         for (size_t i = 0; i < weak_frameworks.size(); i++)
626           frameworks->AppendString(weak_frameworks[i]);
627         res->SetWithoutPathExpansion(variables::kWeakFrameworks,
628                                      std::move(frameworks));
629       }
630     }
631 
632     if (what(variables::kFrameworkDirs)) {
633       const auto& all_framework_dirs = resolved.GetLinkedFrameworkDirs(target_);
634       if (!all_framework_dirs.empty()) {
635         auto framework_dirs = std::make_unique<base::ListValue>();
636         for (size_t i = 0; i < all_framework_dirs.size(); i++)
637           framework_dirs->AppendString(all_framework_dirs[i].value());
638         res->SetWithoutPathExpansion(variables::kFrameworkDirs,
639                                      std::move(framework_dirs));
640       }
641     }
642 
643     return res;
644   }
645 
646  private:
647   // Prints dependencies of the given target (not the target itself). If the
648   // set is non-null, new targets encountered will be added to the set, and if
649   // a dependency is in the set already, it will not be recused into. When the
650   // set is null, all dependencies will be printed.
RecursivePrintDeps(base::ListValue * out,const Target * target,TargetSet * seen_targets,int indent_level)651   void RecursivePrintDeps(base::ListValue* out,
652                           const Target* target,
653                           TargetSet* seen_targets,
654                           int indent_level) {
655     // Combine all deps into one sorted list.
656     std::vector<LabelTargetPair> sorted_deps;
657     for (const auto& pair : target->GetDeps(Target::DEPS_ALL))
658       sorted_deps.push_back(pair);
659     std::sort(sorted_deps.begin(), sorted_deps.end());
660 
661     std::string indent(indent_level * 2, ' ');
662 
663     for (const auto& pair : sorted_deps) {
664       const Target* cur_dep = pair.ptr;
665       std::string str =
666           indent + cur_dep->label().GetUserVisibleName(GetToolchainLabel());
667 
668       bool print_children = true;
669       if (seen_targets) {
670         if (!seen_targets->add(cur_dep)) {
671           // Already seen.
672           print_children = false;
673           // Only print "..." if something is actually elided, which means that
674           // the current target has children.
675           if (!cur_dep->public_deps().empty() ||
676               !cur_dep->private_deps().empty() || !cur_dep->data_deps().empty())
677             str += "...";
678         }
679       }
680 
681       out->AppendString(str);
682 
683       if (print_children)
684         RecursivePrintDeps(out, cur_dep, seen_targets, indent_level + 1);
685     }
686   }
687 
RenderDeps()688   ValuePtr RenderDeps() {
689     auto res = std::make_unique<base::ListValue>();
690 
691     // Tree mode is separate.
692     if (tree_) {
693       if (all_) {
694         // Show all tree deps with no eliding.
695         RecursivePrintDeps(res.get(), target_, nullptr, 0);
696       } else {
697         // Don't recurse into duplicates.
698         TargetSet seen_targets;
699         RecursivePrintDeps(res.get(), target_, &seen_targets, 0);
700       }
701     } else {  // not tree
702 
703       // Collect the deps to display.
704       if (all_) {
705         // Show all dependencies.
706         TargetSet all_deps;
707         RecursiveCollectChildDeps(target_, &all_deps);
708         commands::FilterAndPrintTargetSet(all_deps, res.get());
709       } else {
710         // Show direct dependencies only.
711         std::vector<const Target*> deps;
712         for (const auto& pair : target_->GetDeps(Target::DEPS_ALL))
713           deps.push_back(pair.ptr);
714         std::sort(deps.begin(), deps.end());
715         commands::FilterAndPrintTargets(&deps, res.get());
716       }
717     }
718 
719     return res;
720   }
721 
RenderGenDeps()722   ValuePtr RenderGenDeps() {
723     auto res = std::make_unique<base::ListValue>();
724     Label default_tc = target_->settings()->default_toolchain_label();
725     std::vector<std::string> gen_deps;
726     for (const auto& pair : target_->gen_deps())
727       gen_deps.push_back(pair.label.GetUserVisibleName(default_tc));
728     std::sort(gen_deps.begin(), gen_deps.end());
729     for (const auto& dep : gen_deps)
730       res->AppendString(dep);
731     return res;
732   }
733 
RenderRuntimeDeps()734   ValuePtr RenderRuntimeDeps() {
735     auto res = std::make_unique<base::ListValue>();
736 
737     const Target* previous_from = NULL;
738     for (const auto& pair : ComputeRuntimeDeps(target_)) {
739       std::string str;
740       if (blame_) {
741         // Generally a target's runtime deps will be listed sequentially, so
742         // group them and don't duplicate the "from" label for two in a row.
743         if (previous_from == pair.second) {
744           str = "  ";
745         } else {
746           previous_from = pair.second;
747           res->AppendString(
748               str + "From " +
749               pair.second->label().GetUserVisibleName(GetToolchainLabel()));
750           str = "  ";
751         }
752       }
753 
754       res->AppendString(str + pair.first.value());
755     }
756 
757     return res;
758   }
759 
FillInSourceOutputs(base::DictionaryValue * res)760   void FillInSourceOutputs(base::DictionaryValue* res) {
761     // Only include "source outputs" if there are sources that map to outputs.
762     // Things like actions have constant per-target outputs that don't depend on
763     // the list of sources. These don't need source outputs.
764     if (target_->output_type() != Target::ACTION_FOREACH &&
765         target_->output_type() != Target::COPY_FILES && !target_->IsBinary())
766       return;  // Everything else has constant outputs.
767 
768     // "copy" targets may have patterns or not. If there's only one file, the
769     // user can specify a constant output name.
770     if (target_->output_type() == Target::COPY_FILES &&
771         target_->action_values().outputs().required_types().empty())
772       return;  // Constant output.
773 
774     auto dict = std::make_unique<base::DictionaryValue>();
775     for (const auto& source : target_->sources()) {
776       std::vector<OutputFile> outputs;
777       const char* tool_name = Tool::kToolNone;
778       if (target_->GetOutputFilesForSource(source, &tool_name, &outputs)) {
779         auto list = std::make_unique<base::ListValue>();
780         for (const auto& output : outputs)
781           list->AppendString(output.value());
782 
783         dict->SetWithoutPathExpansion(source.value(), std::move(list));
784       }
785     }
786     res->SetWithoutPathExpansion("source_outputs", std::move(dict));
787   }
788 
FillInBundle(base::DictionaryValue * res)789   void FillInBundle(base::DictionaryValue* res) {
790     auto data = std::make_unique<base::DictionaryValue>();
791     const BundleData& bundle_data = target_->bundle_data();
792     const Settings* settings = target_->settings();
793     BundleData::SourceFiles sources;
794     bundle_data.GetSourceFiles(&sources);
795     data->SetWithoutPathExpansion("source_files", RenderValue(sources));
796     data->SetKey(
797         "root_dir_output",
798         base::Value(bundle_data.GetBundleRootDirOutput(settings).value()));
799     data->SetWithoutPathExpansion("root_dir",
800                                   RenderValue(bundle_data.root_dir()));
801     data->SetWithoutPathExpansion("resources_dir",
802                                   RenderValue(bundle_data.resources_dir()));
803     data->SetWithoutPathExpansion("executable_dir",
804                                   RenderValue(bundle_data.executable_dir()));
805     data->SetKey("product_type", base::Value(bundle_data.product_type()));
806     data->SetWithoutPathExpansion(
807         "partial_info_plist", RenderValue(bundle_data.partial_info_plist()));
808 
809     auto deps = std::make_unique<base::ListValue>();
810     for (const auto* dep : bundle_data.bundle_deps())
811       deps->AppendString(dep->label().GetUserVisibleName(GetToolchainLabel()));
812 
813     data->SetWithoutPathExpansion("deps", std::move(deps));
814     res->SetWithoutPathExpansion("bundle_data", std::move(data));
815   }
816 
FillInOutputs(base::DictionaryValue * res)817   void FillInOutputs(base::DictionaryValue* res) {
818     std::vector<SourceFile> output_files;
819     Err err;
820     if (!target_->GetOutputsAsSourceFiles(LocationRange(), true, &output_files,
821                                           &err)) {
822       err.PrintToStdout();
823       return;
824     }
825     res->SetWithoutPathExpansion(variables::kOutputs,
826                                  RenderValue(output_files));
827 
828     // Write some extra data for certain output types.
829     if (target_->output_type() == Target::ACTION_FOREACH ||
830         target_->output_type() == Target::COPY_FILES) {
831       const SubstitutionList& outputs = target_->action_values().outputs();
832       if (!outputs.required_types().empty()) {
833         // Write out the output patterns if there are any.
834         auto patterns = std::make_unique<base::ListValue>();
835         for (const auto& elem : outputs.list())
836           patterns->AppendString(elem.AsString());
837 
838         res->SetWithoutPathExpansion("output_patterns", std::move(patterns));
839       }
840     }
841   }
842 
843   // Writes a given config value type to the string, optionally with
844   // attribution.
845   // This should match RecursiveTargetConfigToStream in the order it traverses.
846   template <class T>
RenderConfigValues(RecursiveWriterConfig writer_config,const std::vector<T> & (ConfigValues::* getter)()const)847   ValuePtr RenderConfigValues(RecursiveWriterConfig writer_config,
848                               const std::vector<T>& (ConfigValues::*getter)()
849                                   const) {
850     std::set<T> seen;
851     auto res = std::make_unique<base::ListValue>();
852     for (ConfigValuesIterator iter(target_); !iter.done(); iter.Next()) {
853       const std::vector<T>& vec = (iter.cur().*getter)();
854 
855       if (vec.empty())
856         continue;
857 
858       if (blame_) {
859         const Config* config = iter.GetCurrentConfig();
860         if (config) {
861           // Source of this value is a config.
862           std::string from =
863               "From " + config->label().GetUserVisibleName(false);
864           res->AppendString(from);
865           if (iter.origin()) {
866             Location location = iter.origin()->GetRange().begin();
867             from = "     (Added by " + location.file()->name().value() + ":" +
868                    base::IntToString(location.line_number()) + ")";
869             res->AppendString(from);
870           }
871         } else {
872           // Source of this value is the target itself.
873           std::string from =
874               "From " + target_->label().GetUserVisibleName(false);
875           res->AppendString(from);
876         }
877       }
878 
879       // If blame is on, then do not de-dup across configs.
880       if (blame_)
881         seen.clear();
882 
883       for (const T& val : vec) {
884         switch (writer_config) {
885           case kRecursiveWriterKeepDuplicates:
886             break;
887 
888           case kRecursiveWriterSkipDuplicates: {
889             if (seen.find(val) != seen.end())
890               continue;
891 
892             seen.insert(val);
893             break;
894           }
895         }
896 
897         ValuePtr rendered = RenderValue(val);
898         std::string str;
899         // Indent string values in blame mode
900         if (blame_ && rendered->GetAsString(&str)) {
901           str = "  " + str;
902           rendered = std::make_unique<base::Value>(str);
903         }
904         res->Append(std::move(rendered));
905       }
906     }
907     return res->empty() ? nullptr : std::move(res);
908   }
909 
GetToolchainLabel() const910   Label GetToolchainLabel() const override {
911     return target_->label().GetToolchainLabel();
912   }
913 
914   const Target* target_;
915 };
916 
917 }  // namespace
918 
DescriptionForTarget(const Target * target,const std::string & what,bool all,bool tree,bool blame)919 std::unique_ptr<base::DictionaryValue> DescBuilder::DescriptionForTarget(
920     const Target* target,
921     const std::string& what,
922     bool all,
923     bool tree,
924     bool blame) {
925   std::set<std::string> w;
926   if (!what.empty())
927     w.insert(what);
928   TargetDescBuilder b(target, w, all, tree, blame);
929   return b.BuildDescription();
930 }
931 
DescriptionForConfig(const Config * config,const std::string & what)932 std::unique_ptr<base::DictionaryValue> DescBuilder::DescriptionForConfig(
933     const Config* config,
934     const std::string& what) {
935   std::set<std::string> w;
936   if (!what.empty())
937     w.insert(what);
938   ConfigDescBuilder b(config, w);
939   return b.BuildDescription();
940 }
941