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