| OLD | NEW | 
|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include <stddef.h> | 5 #include <stddef.h> | 
| 6 | 6 | 
| 7 #include <algorithm> | 7 #include <algorithm> | 
| 8 #include <set> | 8 #include <set> | 
| 9 #include <sstream> | 9 #include <sstream> | 
| 10 | 10 | 
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" | 
| 12 #include "build/build_config.h" | 12 #include "build/build_config.h" | 
| 13 #include "tools/gn/commands.h" | 13 #include "tools/gn/commands.h" | 
| 14 #include "tools/gn/config.h" | 14 #include "tools/gn/config.h" | 
| 15 #include "tools/gn/config_values_extractors.h" | 15 #include "tools/gn/config_values_extractors.h" | 
| 16 #include "tools/gn/deps_iterator.h" | 16 #include "tools/gn/deps_iterator.h" | 
| 17 #include "tools/gn/filesystem_utils.h" | 17 #include "tools/gn/filesystem_utils.h" | 
| 18 #include "tools/gn/item.h" | 18 #include "tools/gn/item.h" | 
| 19 #include "tools/gn/label.h" | 19 #include "tools/gn/label.h" | 
| 20 #include "tools/gn/runtime_deps.h" | 20 #include "tools/gn/runtime_deps.h" | 
| 21 #include "tools/gn/setup.h" | 21 #include "tools/gn/setup.h" | 
| 22 #include "tools/gn/standard_out.h" | 22 #include "tools/gn/standard_out.h" | 
| 23 #include "tools/gn/substitution_writer.h" | 23 #include "tools/gn/substitution_writer.h" | 
|  | 24 #include "tools/gn/switches.h" | 
| 24 #include "tools/gn/target.h" | 25 #include "tools/gn/target.h" | 
| 25 #include "tools/gn/variables.h" | 26 #include "tools/gn/variables.h" | 
| 26 | 27 | 
| 27 namespace commands { | 28 namespace commands { | 
| 28 | 29 | 
| 29 namespace { | 30 namespace { | 
| 30 | 31 | 
| 31 // Desc-specific command line switches. | 32 // Desc-specific command line switches. | 
| 32 const char kBlame[] = "blame"; | 33 const char kBlame[] = "blame"; | 
| 33 const char kTree[] = "tree"; | 34 const char kTree[] = "tree"; | 
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 112   } | 113   } | 
| 113 } | 114 } | 
| 114 | 115 | 
| 115 void PrintDeps(const Target* target, bool display_header) { | 116 void PrintDeps(const Target* target, bool display_header) { | 
| 116   const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); | 117   const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); | 
| 117   Label toolchain_label = target->label().GetToolchainLabel(); | 118   Label toolchain_label = target->label().GetToolchainLabel(); | 
| 118 | 119 | 
| 119   // Tree mode is separate. | 120   // Tree mode is separate. | 
| 120   if (cmdline->HasSwitch(kTree)) { | 121   if (cmdline->HasSwitch(kTree)) { | 
| 121     if (display_header) | 122     if (display_header) | 
| 122       OutputString("\nDependency tree:\n"); | 123       OutputString("\nDependency tree\n"); | 
| 123 | 124 | 
| 124     if (cmdline->HasSwitch("all")) { | 125     if (cmdline->HasSwitch("all")) { | 
| 125       // Show all tree deps with no eliding. | 126       // Show all tree deps with no eliding. | 
| 126       RecursivePrintDeps(target, toolchain_label, nullptr, 1); | 127       RecursivePrintDeps(target, toolchain_label, nullptr, 1); | 
| 127     } else { | 128     } else { | 
| 128       // Don't recurse into duplicates. | 129       // Don't recurse into duplicates. | 
| 129       std::set<const Target*> seen_targets; | 130       std::set<const Target*> seen_targets; | 
| 130       RecursivePrintDeps(target, toolchain_label, &seen_targets, 1); | 131       RecursivePrintDeps(target, toolchain_label, &seen_targets, 1); | 
| 131     } | 132     } | 
| 132     return; | 133     return; | 
| 133   } | 134   } | 
| 134 | 135 | 
| 135   // Collect the deps to display. | 136   // Collect the deps to display. | 
| 136   if (cmdline->HasSwitch("all")) { | 137   if (cmdline->HasSwitch("all")) { | 
| 137     // Show all dependencies. | 138     // Show all dependencies. | 
| 138     if (display_header) | 139     if (display_header) | 
| 139       OutputString("\nAll recursive dependencies:\n"); | 140       OutputString("\nAll recursive dependencies\n"); | 
| 140 | 141 | 
| 141     std::set<const Target*> all_deps; | 142     std::set<const Target*> all_deps; | 
| 142     RecursiveCollectChildDeps(target, &all_deps); | 143     RecursiveCollectChildDeps(target, &all_deps); | 
| 143     FilterAndPrintTargetSet(display_header, all_deps); | 144     FilterAndPrintTargetSet(display_header, all_deps); | 
| 144   } else { | 145   } else { | 
| 145     std::vector<const Target*> deps; | 146     std::vector<const Target*> deps; | 
| 146     // Show direct dependencies only. | 147     // Show direct dependencies only. | 
| 147     if (display_header) { | 148     if (display_header) { | 
| 148       OutputString( | 149       OutputString( | 
| 149           "\nDirect dependencies " | 150           "\nDirect dependencies " | 
| 150           "(try also \"--all\", \"--tree\", or even \"--all --tree\"):\n"); | 151           "(try also \"--all\", \"--tree\", or even \"--all --tree\")\n"); | 
| 151     } | 152     } | 
| 152     for (const auto& pair : target->GetDeps(Target::DEPS_ALL)) | 153     for (const auto& pair : target->GetDeps(Target::DEPS_ALL)) | 
| 153       deps.push_back(pair.ptr); | 154       deps.push_back(pair.ptr); | 
| 154     std::sort(deps.begin(), deps.end()); | 155     std::sort(deps.begin(), deps.end()); | 
| 155     FilterAndPrintTargets(display_header, &deps); | 156     FilterAndPrintTargets(display_header, &deps); | 
| 156   } | 157   } | 
| 157 } | 158 } | 
| 158 | 159 | 
| 159 // libs and lib_dirs are special in that they're inherited. We don't currently | 160 // libs and lib_dirs are special in that they're inherited. We don't currently | 
| 160 // implement a blame feature for this since the bottom-up inheritance makes | 161 // implement a blame feature for this since the bottom-up inheritance makes | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 178 | 179 | 
| 179   if (display_header) | 180   if (display_header) | 
| 180     OutputString("\nlibs\n"); | 181     OutputString("\nlibs\n"); | 
| 181 | 182 | 
| 182   for (size_t i = 0; i < libs.size(); i++) | 183   for (size_t i = 0; i < libs.size(); i++) | 
| 183     OutputString("    " + libs[i].value() + "\n"); | 184     OutputString("    " + libs[i].value() + "\n"); | 
| 184 } | 185 } | 
| 185 | 186 | 
| 186 void PrintPublic(const Target* target, bool display_header) { | 187 void PrintPublic(const Target* target, bool display_header) { | 
| 187   if (display_header) | 188   if (display_header) | 
| 188     OutputString("\npublic:\n"); | 189     OutputString("\npublic\n"); | 
| 189 | 190 | 
| 190   if (target->all_headers_public()) { | 191   if (target->all_headers_public()) { | 
| 191     OutputString("  [All headers listed in the sources are public.]\n"); | 192     OutputString("  [All headers listed in the sources are public.]\n"); | 
| 192     return; | 193     return; | 
| 193   } | 194   } | 
| 194 | 195 | 
| 195   Target::FileList public_headers = target->public_headers(); | 196   Target::FileList public_headers = target->public_headers(); | 
| 196   std::sort(public_headers.begin(), public_headers.end()); | 197   std::sort(public_headers.begin(), public_headers.end()); | 
| 197   for (const auto& hdr : public_headers) | 198   for (const auto& hdr : public_headers) | 
| 198     OutputString("  " + hdr.value() + "\n"); | 199     OutputString("  " + hdr.value() + "\n"); | 
| 199 } | 200 } | 
| 200 | 201 | 
| 201 void PrintCheckIncludes(const Target* target, bool display_header) { | 202 void PrintCheckIncludes(const Target* target, bool display_header) { | 
| 202   if (display_header) | 203   if (display_header) | 
| 203     OutputString("\ncheck_includes:\n"); | 204     OutputString("\ncheck_includes\n"); | 
| 204 | 205 | 
| 205   if (target->check_includes()) | 206   if (target->check_includes()) | 
| 206     OutputString("  true\n"); | 207     OutputString("  true\n"); | 
| 207   else | 208   else | 
| 208     OutputString("  false\n"); | 209     OutputString("  false\n"); | 
| 209 } | 210 } | 
| 210 | 211 | 
| 211 void PrintAllowCircularIncludesFrom(const Target* target, bool display_header) { | 212 void PrintAllowCircularIncludesFrom(const Target* target, bool display_header) { | 
| 212   if (display_header) | 213   if (display_header) | 
| 213     OutputString("\nallow_circular_includes_from:\n"); | 214     OutputString("\nallow_circular_includes_from\n"); | 
| 214 | 215 | 
| 215   Label toolchain_label = target->label().GetToolchainLabel(); | 216   Label toolchain_label = target->label().GetToolchainLabel(); | 
| 216   for (const auto& cur : target->allow_circular_includes_from()) | 217   for (const auto& cur : target->allow_circular_includes_from()) | 
| 217     OutputString("  " + cur.GetUserVisibleName(toolchain_label) + "\n"); | 218     OutputString("  " + cur.GetUserVisibleName(toolchain_label) + "\n"); | 
| 218 } | 219 } | 
| 219 | 220 | 
| 220 void PrintVisibility(const Target* target, bool display_header) { | 221 void PrintVisibility(const Target* target, bool display_header) { | 
| 221   if (display_header) | 222   if (display_header) | 
| 222     OutputString("\nvisibility:\n"); | 223     OutputString("\nvisibility\n"); | 
| 223 | 224 | 
| 224   OutputString(target->visibility().Describe(2, false)); | 225   OutputString(target->visibility().Describe(2, false)); | 
| 225 } | 226 } | 
| 226 | 227 | 
| 227 void PrintTestonly(const Target* target, bool display_header) { | 228 void PrintTestonly(const Target* target, bool display_header) { | 
| 228   if (display_header) | 229   if (display_header) | 
| 229     OutputString("\ntestonly:\n"); | 230     OutputString("\ntestonly\n"); | 
| 230 | 231 | 
| 231   if (target->testonly()) | 232   if (target->testonly()) | 
| 232     OutputString("  true\n"); | 233     OutputString("  true\n"); | 
| 233   else | 234   else | 
| 234     OutputString("  false\n"); | 235     OutputString("  false\n"); | 
| 235 } | 236 } | 
| 236 | 237 | 
| 237 // Recursively prints subconfigs of a config. | 238 // Recursively prints subconfigs of a config. | 
| 238 void PrintSubConfigs(const Config* config, int indent_level) { | 239 void PrintSubConfigs(const Config* config, int indent_level) { | 
| 239   if (config->configs().empty()) | 240   if (config->configs().empty()) | 
| 240     return; | 241     return; | 
| 241 | 242 | 
| 242   std::string indent(indent_level * 2, ' '); | 243   std::string indent(indent_level * 2, ' '); | 
| 243   Label toolchain_label = config->label().GetToolchainLabel(); | 244   Label toolchain_label = config->label().GetToolchainLabel(); | 
| 244   for (const auto& pair : config->configs()) { | 245   for (const auto& pair : config->configs()) { | 
| 245     OutputString( | 246     OutputString( | 
| 246         indent + pair.label.GetUserVisibleName(toolchain_label) + "\n"); | 247         indent + pair.label.GetUserVisibleName(toolchain_label) + "\n"); | 
| 247     PrintSubConfigs(pair.ptr, indent_level + 1); | 248     PrintSubConfigs(pair.ptr, indent_level + 1); | 
| 248   } | 249   } | 
| 249 } | 250 } | 
| 250 | 251 | 
| 251 // This allows configs stored as either std::vector<LabelConfigPair> or | 252 // This allows configs stored as either std::vector<LabelConfigPair> or | 
| 252 // UniqueVector<LabelConfigPair> to be printed. | 253 // UniqueVector<LabelConfigPair> to be printed. | 
| 253 template <class VectorType> | 254 template <class VectorType> | 
| 254 void PrintConfigsVector(const Target* target, | 255 void PrintConfigsVector(const Item* item, | 
| 255                         const VectorType& configs, | 256                         const VectorType& configs, | 
| 256                         const std::string& heading, | 257                         const std::string& heading, | 
| 257                         bool display_header) { | 258                         bool display_header) { | 
| 258   if (configs.empty()) | 259   if (configs.empty()) | 
| 259     return; | 260     return; | 
| 260 | 261 | 
| 261   bool tree = base::CommandLine::ForCurrentProcess()->HasSwitch(kTree); | 262   bool tree = base::CommandLine::ForCurrentProcess()->HasSwitch(kTree); | 
| 262 | 263 | 
| 263   // Don't sort since the order determines how things are processed. | 264   // Don't sort since the order determines how things are processed. | 
| 264   if (display_header) { | 265   if (display_header) { | 
| 265     if (tree) | 266     if (tree) | 
| 266       OutputString("\n" + heading + " tree (in order applying):\n"); | 267       OutputString("\n" + heading + " tree (in order applying)\n"); | 
| 267     else | 268     else | 
| 268       OutputString("\n" + heading + " (in order applying, try also --tree):\n"); | 269       OutputString("\n" + heading + " (in order applying, try also --tree)\n"); | 
| 269   } | 270   } | 
| 270 | 271 | 
| 271   Label toolchain_label = target->label().GetToolchainLabel(); | 272   Label toolchain_label = item->label().GetToolchainLabel(); | 
| 272   for (const auto& config : configs) { | 273   for (const auto& config : configs) { | 
| 273     OutputString("  " + config.label.GetUserVisibleName(toolchain_label) + | 274     OutputString("  " + config.label.GetUserVisibleName(toolchain_label) + | 
| 274                  "\n"); | 275                  "\n"); | 
| 275     if (tree) | 276     if (tree) | 
| 276       PrintSubConfigs(config.ptr, 2);  // 2 = start with double-indent. | 277       PrintSubConfigs(config.ptr, 2);  // 2 = start with double-indent. | 
| 277   } | 278   } | 
| 278 } | 279 } | 
| 279 | 280 | 
| 280 void PrintConfigs(const Target* target, bool display_header) { | 281 void PrintConfigs(const Target* target, bool display_header) { | 
| 281   PrintConfigsVector(target, target->configs().vector(), "configs", | 282   PrintConfigsVector(target, target->configs().vector(), "configs", | 
| 282                      display_header); | 283                      display_header); | 
| 283 } | 284 } | 
| 284 | 285 | 
|  | 286 void PrintConfigs(const Config* config, bool display_header) { | 
|  | 287   PrintConfigsVector(config, config->configs().vector(), "configs", | 
|  | 288                      display_header); | 
|  | 289 } | 
|  | 290 | 
| 285 void PrintPublicConfigs(const Target* target, bool display_header) { | 291 void PrintPublicConfigs(const Target* target, bool display_header) { | 
| 286   PrintConfigsVector(target, target->public_configs(), | 292   PrintConfigsVector(target, target->public_configs(), | 
| 287                      "public_configs", display_header); | 293                      "public_configs", display_header); | 
| 288 } | 294 } | 
| 289 | 295 | 
| 290 void PrintAllDependentConfigs(const Target* target, bool display_header) { | 296 void PrintAllDependentConfigs(const Target* target, bool display_header) { | 
| 291   PrintConfigsVector(target, target->all_dependent_configs(), | 297   PrintConfigsVector(target, target->all_dependent_configs(), | 
| 292                      "all_dependent_configs", display_header); | 298                      "all_dependent_configs", display_header); | 
| 293 } | 299 } | 
| 294 | 300 | 
| 295 void PrintFileList(const Target::FileList& files, | 301 void PrintFileList(const Target::FileList& files, | 
| 296                    const std::string& header, | 302                    const std::string& header, | 
| 297                    bool indent_extra, | 303                    bool indent_extra, | 
| 298                    bool display_header) { | 304                    bool display_header) { | 
| 299   if (files.empty()) | 305   if (files.empty()) | 
| 300     return; | 306     return; | 
| 301 | 307 | 
| 302   if (display_header) | 308   if (display_header) | 
| 303     OutputString("\n" + header + ":\n"); | 309     OutputString("\n" + header + "\n"); | 
| 304 | 310 | 
| 305   std::string indent = indent_extra ? "    " : "  "; | 311   std::string indent = indent_extra ? "    " : "  "; | 
| 306 | 312 | 
| 307   Target::FileList sorted = files; | 313   Target::FileList sorted = files; | 
| 308   std::sort(sorted.begin(), sorted.end()); | 314   std::sort(sorted.begin(), sorted.end()); | 
| 309   for (const auto& elem : sorted) | 315   for (const auto& elem : sorted) | 
| 310     OutputString(indent + elem.value() + "\n"); | 316     OutputString(indent + elem.value() + "\n"); | 
| 311 } | 317 } | 
| 312 | 318 | 
| 313 void PrintSources(const Target* target, bool display_header) { | 319 void PrintSources(const Target* target, bool display_header) { | 
| 314   PrintFileList(target->sources(), "sources", false, display_header); | 320   PrintFileList(target->sources(), "sources", false, display_header); | 
| 315 } | 321 } | 
| 316 | 322 | 
| 317 void PrintInputs(const Target* target, bool display_header) { | 323 void PrintInputs(const Target* target, bool display_header) { | 
| 318   PrintFileList(target->inputs(), "inputs", false, display_header); | 324   PrintFileList(target->inputs(), "inputs", false, display_header); | 
| 319 } | 325 } | 
| 320 | 326 | 
| 321 void PrintOutputs(const Target* target, bool display_header) { | 327 void PrintOutputs(const Target* target, bool display_header) { | 
| 322   if (display_header) | 328   if (display_header) | 
| 323     OutputString("\noutputs:\n"); | 329     OutputString("\noutputs\n"); | 
| 324 | 330 | 
| 325   if (target->output_type() == Target::ACTION) { | 331   if (target->output_type() == Target::ACTION) { | 
| 326     // Action, print out outputs, don't apply sources to it. | 332     // Action, print out outputs, don't apply sources to it. | 
| 327     for (const auto& elem : target->action_values().outputs().list()) { | 333     for (const auto& elem : target->action_values().outputs().list()) { | 
| 328       OutputString("  " + elem.AsString() + "\n"); | 334       OutputString("  " + elem.AsString() + "\n"); | 
| 329     } | 335     } | 
| 330   } else if (target->output_type() == Target::CREATE_BUNDLE) { | 336   } else if (target->output_type() == Target::CREATE_BUNDLE) { | 
| 331     std::vector<SourceFile> output_files; | 337     std::vector<SourceFile> output_files; | 
| 332     target->bundle_data().GetOutputsAsSourceFiles(target->settings(), | 338     target->bundle_data().GetOutputsAsSourceFiles(target->settings(), | 
| 333                                                   &output_files); | 339                                                   &output_files); | 
| 334     PrintFileList(output_files, "", true, false); | 340     PrintFileList(output_files, "", true, false); | 
| 335   } else { | 341   } else { | 
| 336     const SubstitutionList& outputs = target->action_values().outputs(); | 342     const SubstitutionList& outputs = target->action_values().outputs(); | 
| 337     if (!outputs.required_types().empty()) { | 343     if (!outputs.required_types().empty()) { | 
| 338       // Display the pattern and resolved pattern separately, since there are | 344       // Display the pattern and resolved pattern separately, since there are | 
| 339       // subtitutions used. | 345       // subtitutions used. | 
| 340       OutputString("  Output pattern:\n"); | 346       OutputString("  Output pattern\n"); | 
| 341       for (const auto& elem : outputs.list()) | 347       for (const auto& elem : outputs.list()) | 
| 342         OutputString("    " + elem.AsString() + "\n"); | 348         OutputString("    " + elem.AsString() + "\n"); | 
| 343 | 349 | 
| 344       // Now display what that resolves to given the sources. | 350       // Now display what that resolves to given the sources. | 
| 345       OutputString("\n  Resolved output file list:\n"); | 351       OutputString("\n  Resolved output file list\n"); | 
| 346     } | 352     } | 
| 347 | 353 | 
| 348     // Resolved output list. | 354     // Resolved output list. | 
| 349     std::vector<SourceFile> output_files; | 355     std::vector<SourceFile> output_files; | 
| 350     SubstitutionWriter::ApplyListToSources(target->settings(), outputs, | 356     SubstitutionWriter::ApplyListToSources(target->settings(), outputs, | 
| 351                                            target->sources(), &output_files); | 357                                            target->sources(), &output_files); | 
| 352     PrintFileList(output_files, "", true, false); | 358     PrintFileList(output_files, "", true, false); | 
| 353   } | 359   } | 
| 354 } | 360 } | 
| 355 | 361 | 
| 356 void PrintScript(const Target* target, bool display_header) { | 362 void PrintScript(const Target* target, bool display_header) { | 
| 357   if (display_header) | 363   if (display_header) | 
| 358     OutputString("\nscript:\n"); | 364     OutputString("\nscript\n"); | 
| 359   OutputString("  " + target->action_values().script().value() + "\n"); | 365   OutputString("  " + target->action_values().script().value() + "\n"); | 
| 360 } | 366 } | 
| 361 | 367 | 
| 362 void PrintArgs(const Target* target, bool display_header) { | 368 void PrintArgs(const Target* target, bool display_header) { | 
| 363   if (display_header) | 369   if (display_header) | 
| 364     OutputString("\nargs:\n"); | 370     OutputString("\nargs\n"); | 
| 365   for (const auto& elem : target->action_values().args().list()) { | 371   for (const auto& elem : target->action_values().args().list()) { | 
| 366     OutputString("  " + elem.AsString() + "\n"); | 372     OutputString("  " + elem.AsString() + "\n"); | 
| 367   } | 373   } | 
| 368 } | 374 } | 
| 369 | 375 | 
| 370 void PrintDepfile(const Target* target, bool display_header) { | 376 void PrintDepfile(const Target* target, bool display_header) { | 
| 371   if (target->action_values().depfile().empty()) | 377   if (target->action_values().depfile().empty()) | 
| 372     return; | 378     return; | 
| 373   if (display_header) | 379   if (display_header) | 
| 374     OutputString("\ndepfile:\n"); | 380     OutputString("\ndepfile\n"); | 
| 375   OutputString("  " + target->action_values().depfile().AsString() + "\n"); | 381   OutputString("  " + target->action_values().depfile().AsString() + "\n"); | 
| 376 } | 382 } | 
| 377 | 383 | 
| 378 // Attribute the origin for attributing from where a target came from. Does | 384 // Attribute the origin for attributing from where a target came from. Does | 
| 379 // nothing if the input is null or it does not have a location. | 385 // nothing if the input is null or it does not have a location. | 
| 380 void OutputSourceOfDep(const ParseNode* origin, std::ostream& out) { | 386 void OutputSourceOfDep(const ParseNode* origin, std::ostream& out) { | 
| 381   if (!origin) | 387   if (!origin) | 
| 382     return; | 388     return; | 
| 383   Location location = origin->GetRange().begin(); | 389   Location location = origin->GetRange().begin(); | 
| 384   out << "       (Added by " + location.file()->name().value() << ":" | 390   out << "       (Added by " + location.file()->name().value() << ":" | 
| 385       << location.line_number() << ")\n"; | 391       << location.line_number() << ")\n"; | 
| 386 } | 392 } | 
| 387 | 393 | 
| 388 // Templatized writer for writing out different config value types. | 394 // Templatized writer for writing out different config value types. | 
| 389 template<typename T> struct DescValueWriter {}; | 395 template<typename T> struct DescValueWriter {}; | 
| 390 template<> struct DescValueWriter<std::string> { | 396 template<> struct DescValueWriter<std::string> { | 
| 391   void operator()(const std::string& str, std::ostream& out) const { | 397   void operator()(const std::string& str, std::ostream& out) const { | 
| 392     out << "    " << str << "\n"; | 398     out << "    " << str << "\n"; | 
| 393   } | 399   } | 
| 394 }; | 400 }; | 
|  | 401 | 
| 395 template<> struct DescValueWriter<SourceDir> { | 402 template<> struct DescValueWriter<SourceDir> { | 
| 396   void operator()(const SourceDir& dir, std::ostream& out) const { | 403   void operator()(const SourceDir& dir, std::ostream& out) const { | 
| 397     out << "    " << FormatSourceDir(dir) << "\n"; | 404     out << "    " << FormatSourceDir(dir) << "\n"; | 
| 398   } | 405   } | 
| 399 }; | 406 }; | 
| 400 | 407 | 
|  | 408 template<> struct DescValueWriter<LibFile> { | 
|  | 409   void operator()(const LibFile& lib, std::ostream& out) const { | 
|  | 410     if (lib.is_source_file()) | 
|  | 411       out << "    " << lib.source_file().value() << "\n"; | 
|  | 412     else | 
|  | 413       out << "    " << lib.value() << "\n"; | 
|  | 414   } | 
|  | 415 }; | 
|  | 416 | 
| 401 // Writes a given config value type to the string, optionally with attribution. | 417 // Writes a given config value type to the string, optionally with attribution. | 
| 402 // This should match RecursiveTargetConfigToStream in the order it traverses. | 418 // This should match RecursiveTargetConfigToStream in the order it traverses. | 
| 403 template<typename T> void OutputRecursiveTargetConfig( | 419 template<typename T> void OutputRecursiveTargetConfig( | 
| 404     const Target* target, | 420     const Target* target, | 
| 405     const char* header_name, | 421     const char* header_name, | 
| 406     const std::vector<T>& (ConfigValues::* getter)() const) { | 422     const std::vector<T>& (ConfigValues::* getter)() const) { | 
| 407   bool display_blame = | 423   bool display_blame = | 
| 408       base::CommandLine::ForCurrentProcess()->HasSwitch(kBlame); | 424       base::CommandLine::ForCurrentProcess()->HasSwitch(kBlame); | 
| 409 | 425 | 
| 410   DescValueWriter<T> writer; | 426   DescValueWriter<T> writer; | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 426         out << "  From " << target->label().GetUserVisibleName(false) << "\n"; | 442         out << "  From " << target->label().GetUserVisibleName(false) << "\n"; | 
| 427       } | 443       } | 
| 428     } | 444     } | 
| 429 | 445 | 
| 430     // Actual values. | 446     // Actual values. | 
| 431     ConfigValuesToStream(iter.cur(), getter, writer, out); | 447     ConfigValuesToStream(iter.cur(), getter, writer, out); | 
| 432   } | 448   } | 
| 433 | 449 | 
| 434   std::string out_str = out.str(); | 450   std::string out_str = out.str(); | 
| 435   if (!out_str.empty()) { | 451   if (!out_str.empty()) { | 
| 436     OutputString("\n" + std::string(header_name) + "\n"); | 452     if (header_name) | 
|  | 453       OutputString("\n" + std::string(header_name) + "\n"); | 
| 437     OutputString(out_str); | 454     OutputString(out_str); | 
| 438   } | 455   } | 
| 439 } | 456 } | 
|  | 457 | 
|  | 458 template<typename T> void OutputConfigValueArray( | 
|  | 459     const ConfigValues& values, | 
|  | 460     const char* header_name, | 
|  | 461     const std::vector<T>& (ConfigValues::* getter)() const) { | 
|  | 462   std::ostringstream out; | 
|  | 463 | 
|  | 464   DescValueWriter<T> writer; | 
|  | 465   for (const T& cur : (values.*getter)()) | 
|  | 466     writer(cur, out); | 
|  | 467 | 
|  | 468   std::string out_str = out.str(); | 
|  | 469   if (!out_str.empty()) { | 
|  | 470     if (header_name) | 
|  | 471       OutputString("\n" + std::string(header_name) + "\n"); | 
|  | 472     OutputString(out_str); | 
|  | 473   } | 
|  | 474 } | 
| 440 | 475 | 
| 441 void PrintRuntimeDeps(const Target* target) { | 476 void PrintRuntimeDeps(const Target* target) { | 
| 442   bool display_blame = | 477   bool display_blame = | 
| 443       base::CommandLine::ForCurrentProcess()->HasSwitch(kBlame); | 478       base::CommandLine::ForCurrentProcess()->HasSwitch(kBlame); | 
| 444   Label toolchain = target->label().GetToolchainLabel(); | 479   Label toolchain = target->label().GetToolchainLabel(); | 
| 445 | 480 | 
| 446   const Target* previous_from = NULL; | 481   const Target* previous_from = NULL; | 
| 447   for (const auto& pair : ComputeRuntimeDeps(target)) { | 482   for (const auto& pair : ComputeRuntimeDeps(target)) { | 
| 448     if (display_blame) { | 483     if (display_blame) { | 
| 449       // Generally a target's runtime deps will be listed sequentially, so | 484       // Generally a target's runtime deps will be listed sequentially, so | 
| 450       // group them and don't duplicate the "from" label for two in a row. | 485       // group them and don't duplicate the "from" label for two in a row. | 
| 451       if (previous_from == pair.second) { | 486       if (previous_from == pair.second) { | 
| 452         OutputString("  ");  // Just indent. | 487         OutputString("  ");  // Just indent. | 
| 453       } else { | 488       } else { | 
| 454         previous_from = pair.second; | 489         previous_from = pair.second; | 
| 455         OutputString("From "); | 490         OutputString("From "); | 
| 456         OutputString(pair.second->label().GetUserVisibleName(toolchain)); | 491         OutputString(pair.second->label().GetUserVisibleName(toolchain)); | 
| 457         OutputString("\n  ");  // Make the file name indented. | 492         OutputString("\n  ");  // Make the file name indented. | 
| 458       } | 493       } | 
| 459     } | 494     } | 
| 460     OutputString(pair.first.value()); | 495     OutputString(pair.first.value()); | 
| 461     OutputString("\n"); | 496     OutputString("\n"); | 
| 462   } | 497   } | 
| 463 } | 498 } | 
| 464 | 499 | 
|  | 500 // If "what" is empty, prints all PCH info. If "what" is nonempty, prints only | 
|  | 501 // the things that match (if any). Returns true if anything was printed. | 
|  | 502 bool PrintPrecompiledHeaderInfo(const ConfigValues& values, | 
|  | 503                                 const std::string& what, | 
|  | 504                                 bool display_headers) { | 
|  | 505   bool found_match = false; | 
|  | 506   if (what == variables::kPrecompiledHeader || what.empty()) { | 
|  | 507     if (!values.precompiled_header().empty()) { | 
|  | 508       if (display_headers) | 
|  | 509         OutputString("\nprecompiled_header\n"); | 
|  | 510       OutputString(values.precompiled_header() + "\n"); | 
|  | 511     } | 
|  | 512     found_match = true; | 
|  | 513   } | 
|  | 514   if (what == variables::kPrecompiledSource || what.empty()) { | 
|  | 515     if (!values.precompiled_source().is_null()) { | 
|  | 516       if (display_headers) | 
|  | 517         OutputString("\nprecompiled_source\n"); | 
|  | 518       OutputString(values.precompiled_source().value() + "\n"); | 
|  | 519     } | 
|  | 520     found_match = true; | 
|  | 521   } | 
|  | 522   return found_match; | 
|  | 523 } | 
|  | 524 | 
|  | 525 bool PrintTarget(const Target* target, | 
|  | 526                  const std::string& what, | 
|  | 527                  bool display_target_header) { | 
|  | 528   if (display_target_header) { | 
|  | 529     OutputString("Target: ", DECORATION_YELLOW); | 
|  | 530     OutputString(target->label().GetUserVisibleName(false) + "\n"); | 
|  | 531     OutputString("Type: ", DECORATION_YELLOW); | 
|  | 532     OutputString(std::string( | 
|  | 533         Target::GetStringForOutputType(target->output_type())) + "\n"); | 
|  | 534     OutputString("Toolchain: ", DECORATION_YELLOW); | 
|  | 535     OutputString( | 
|  | 536         target->label().GetToolchainLabel().GetUserVisibleName(false) + "\n"); | 
|  | 537   } | 
|  | 538 | 
|  | 539   // Display headers when outputting everything. | 
|  | 540   bool display_headers = what.empty(); | 
|  | 541   bool is_binary_output = target->IsBinary(); | 
|  | 542 | 
|  | 543   bool found_match = false; | 
|  | 544 | 
|  | 545   // General target meta variables. | 
|  | 546   if (what.empty() || what == variables::kVisibility) { | 
|  | 547     PrintVisibility(target, display_headers); | 
|  | 548     found_match = true; | 
|  | 549   } | 
|  | 550   if (what.empty() || what == variables::kTestonly) { | 
|  | 551     PrintTestonly(target, display_headers); | 
|  | 552     found_match  = true; | 
|  | 553   } | 
|  | 554 | 
|  | 555   // Binary target meta variables. | 
|  | 556   if (is_binary_output) { | 
|  | 557     if (what.empty() || what == variables::kCheckIncludes) { | 
|  | 558       PrintCheckIncludes(target, display_headers); | 
|  | 559       found_match = true; | 
|  | 560     } | 
|  | 561     if (what.empty() || what == variables::kAllowCircularIncludesFrom) { | 
|  | 562       PrintAllowCircularIncludesFrom(target, display_headers); | 
|  | 563       found_match = true; | 
|  | 564     } | 
|  | 565   } | 
|  | 566 | 
|  | 567   // Sources and inputs. | 
|  | 568   if (what.empty() || what == variables::kSources) { | 
|  | 569     PrintSources(target, display_headers); | 
|  | 570     found_match = true; | 
|  | 571   } | 
|  | 572   if (what.empty() || what == variables::kPublic) { | 
|  | 573     PrintPublic(target, display_headers); | 
|  | 574     found_match = true; | 
|  | 575   } | 
|  | 576   if (what.empty() || what == variables::kInputs) { | 
|  | 577     PrintInputs(target, display_headers); | 
|  | 578     found_match = true; | 
|  | 579   } | 
|  | 580 | 
|  | 581   // Configs. Configs set directly on a target are only relevant for binary | 
|  | 582   // targets | 
|  | 583   if (is_binary_output && (what.empty() || what == variables::kConfigs)) { | 
|  | 584     PrintConfigs(target, display_headers); | 
|  | 585     found_match = true; | 
|  | 586   } | 
|  | 587 | 
|  | 588   // Dependent/public configs can be applied to anything. | 
|  | 589   if (what.empty() || what == variables::kPublicConfigs) { | 
|  | 590     PrintPublicConfigs(target, display_headers); | 
|  | 591     found_match = true; | 
|  | 592   } | 
|  | 593   if (what.empty() || what == variables::kAllDependentConfigs) { | 
|  | 594     PrintAllDependentConfigs(target, display_headers); | 
|  | 595     found_match = true; | 
|  | 596   } | 
|  | 597 | 
|  | 598   // Action values. | 
|  | 599   if (target->output_type() == Target::ACTION || | 
|  | 600       target->output_type() == Target::ACTION_FOREACH) { | 
|  | 601     if (what.empty() || what == variables::kScript) { | 
|  | 602       PrintScript(target, display_headers); | 
|  | 603       found_match = true; | 
|  | 604     } | 
|  | 605     if (what.empty() || what == variables::kArgs) { | 
|  | 606       PrintArgs(target, display_headers); | 
|  | 607       found_match = true; | 
|  | 608     } | 
|  | 609     if (what.empty() || what == variables::kDepfile) { | 
|  | 610       PrintDepfile(target, display_headers); | 
|  | 611       found_match = true; | 
|  | 612     } | 
|  | 613   } | 
|  | 614 | 
|  | 615   // Outputs. | 
|  | 616   if (target->output_type() == Target::ACTION || | 
|  | 617       target->output_type() == Target::ACTION_FOREACH || | 
|  | 618       target->output_type() == Target::COPY_FILES || | 
|  | 619       target->output_type() == Target::CREATE_BUNDLE) { | 
|  | 620     if (what.empty() || what == variables::kOutputs) { | 
|  | 621       PrintOutputs(target, display_headers); | 
|  | 622       found_match = true; | 
|  | 623     } | 
|  | 624   } | 
|  | 625 | 
|  | 626   // Values from configs only apply to binary targets. | 
|  | 627   if (is_binary_output) { | 
|  | 628     #define CONFIG_VALUE_ARRAY_HANDLER(name, type) \ | 
|  | 629       if (what.empty() || what == #name) { \ | 
|  | 630         OutputRecursiveTargetConfig<type>( \ | 
|  | 631             target, display_headers ? #name : nullptr, &ConfigValues::name); \ | 
|  | 632         found_match = true; \ | 
|  | 633       } | 
|  | 634 | 
|  | 635     CONFIG_VALUE_ARRAY_HANDLER(arflags, std::string) | 
|  | 636     CONFIG_VALUE_ARRAY_HANDLER(asmflags, std::string) | 
|  | 637     CONFIG_VALUE_ARRAY_HANDLER(cflags, std::string) | 
|  | 638     CONFIG_VALUE_ARRAY_HANDLER(cflags_c, std::string) | 
|  | 639     CONFIG_VALUE_ARRAY_HANDLER(cflags_cc, std::string) | 
|  | 640     CONFIG_VALUE_ARRAY_HANDLER(cflags_objc, std::string) | 
|  | 641     CONFIG_VALUE_ARRAY_HANDLER(cflags_objcc, std::string) | 
|  | 642     CONFIG_VALUE_ARRAY_HANDLER(defines, std::string) | 
|  | 643     CONFIG_VALUE_ARRAY_HANDLER(include_dirs, SourceDir) | 
|  | 644     CONFIG_VALUE_ARRAY_HANDLER(ldflags, std::string) | 
|  | 645     // Libs and lib_dirs are handled specially below. | 
|  | 646 | 
|  | 647     #undef CONFIG_VALUE_ARRAY_HANDLER | 
|  | 648 | 
|  | 649     found_match |= PrintPrecompiledHeaderInfo(target->config_values(), | 
|  | 650                                               what, display_headers); | 
|  | 651   } | 
|  | 652 | 
|  | 653   // Deps | 
|  | 654   if (what.empty() || what == "deps") { | 
|  | 655     PrintDeps(target, display_headers); | 
|  | 656     found_match = true; | 
|  | 657   } | 
|  | 658 | 
|  | 659   // Runtime deps are special, print only when explicitly asked for and not in | 
|  | 660   // overview mode. | 
|  | 661   if (what == "runtime_deps") { | 
|  | 662     PrintRuntimeDeps(target); | 
|  | 663     found_match = true; | 
|  | 664   } | 
|  | 665 | 
|  | 666   // Libs can be part of any target and get recursively pushed up the chain, | 
|  | 667   // so display them regardless of target type. | 
|  | 668   if (what.empty() || what == variables::kLibs) { | 
|  | 669     PrintLibs(target, display_headers); | 
|  | 670     found_match = true; | 
|  | 671   } | 
|  | 672   if (what.empty() || what == variables::kLibDirs) { | 
|  | 673     PrintLibDirs(target, display_headers); | 
|  | 674     found_match = true; | 
|  | 675   } | 
|  | 676 | 
|  | 677   if (!found_match) { | 
|  | 678     OutputString("Don't know how to display \"" + what + "\" for \"" + | 
|  | 679         Target::GetStringForOutputType(target->output_type()) + "\".\n"); | 
|  | 680     return false; | 
|  | 681   } | 
|  | 682   return true; | 
|  | 683 } | 
|  | 684 | 
|  | 685 bool PrintConfig(const Config* config, | 
|  | 686                  const std::string& what, | 
|  | 687                  bool display_config_header) { | 
|  | 688   const ConfigValues& values = config->resolved_values(); | 
|  | 689 | 
|  | 690   if (display_config_header) { | 
|  | 691     OutputString("Config: ", DECORATION_YELLOW); | 
|  | 692     OutputString(config->label().GetUserVisibleName(false) + "\n"); | 
|  | 693     OutputString("Toolchain: ", DECORATION_YELLOW); | 
|  | 694     OutputString( | 
|  | 695         config->label().GetToolchainLabel().GetUserVisibleName(false) + "\n"); | 
|  | 696     if (what.empty() && !config->configs().empty()) { | 
|  | 697       OutputString( | 
|  | 698           "(This is a composite config, the values below are after the\n" | 
|  | 699           "expansion of the child configs.)\n"); | 
|  | 700     } | 
|  | 701   } | 
|  | 702 | 
|  | 703   // Display headers when outputting everything. | 
|  | 704   bool display_headers = what.empty(); | 
|  | 705 | 
|  | 706   if (what.empty() || what == variables::kConfigs) | 
|  | 707     PrintConfigs(config, display_headers); | 
|  | 708 | 
|  | 709 #define CONFIG_VALUE_ARRAY_HANDLER(name, type) \ | 
|  | 710   if (what.empty() || what == #name) { \ | 
|  | 711     OutputConfigValueArray<type>(values, display_headers ? #name : nullptr, \ | 
|  | 712                                  &ConfigValues::name); \ | 
|  | 713     found_match = true; \ | 
|  | 714   } | 
|  | 715 | 
|  | 716   bool found_match = false; | 
|  | 717 | 
|  | 718   CONFIG_VALUE_ARRAY_HANDLER(arflags, std::string) | 
|  | 719   CONFIG_VALUE_ARRAY_HANDLER(asmflags, std::string) | 
|  | 720   CONFIG_VALUE_ARRAY_HANDLER(cflags, std::string) | 
|  | 721   CONFIG_VALUE_ARRAY_HANDLER(cflags_c, std::string) | 
|  | 722   CONFIG_VALUE_ARRAY_HANDLER(cflags_cc, std::string) | 
|  | 723   CONFIG_VALUE_ARRAY_HANDLER(cflags_objc, std::string) | 
|  | 724   CONFIG_VALUE_ARRAY_HANDLER(cflags_objcc, std::string) | 
|  | 725   CONFIG_VALUE_ARRAY_HANDLER(defines, std::string) | 
|  | 726   CONFIG_VALUE_ARRAY_HANDLER(include_dirs, SourceDir) | 
|  | 727   CONFIG_VALUE_ARRAY_HANDLER(ldflags, std::string) | 
|  | 728   CONFIG_VALUE_ARRAY_HANDLER(lib_dirs, SourceDir) | 
|  | 729   CONFIG_VALUE_ARRAY_HANDLER(libs, LibFile) | 
|  | 730 | 
|  | 731 #undef CONFIG_VALUE_ARRAY_HANDLER | 
|  | 732 | 
|  | 733   // Handles all PCH-related variables. | 
|  | 734   found_match |= PrintPrecompiledHeaderInfo(config->resolved_values(), | 
|  | 735                                             what, display_headers); | 
|  | 736 | 
|  | 737   if (!found_match) { | 
|  | 738     OutputString("Don't know how to display \"" + what + "\" for a config.\n"); | 
|  | 739     return false; | 
|  | 740   } | 
|  | 741   return true; | 
|  | 742 } | 
|  | 743 | 
| 465 }  // namespace | 744 }  // namespace | 
| 466 | 745 | 
| 467 // desc ------------------------------------------------------------------------ | 746 // desc ------------------------------------------------------------------------ | 
| 468 | 747 | 
| 469 const char kDesc[] = "desc"; | 748 const char kDesc[] = "desc"; | 
| 470 const char kDesc_HelpShort[] = | 749 const char kDesc_HelpShort[] = | 
| 471     "desc: Show lots of insightful information about a target."; | 750     "desc: Show lots of insightful information about a target or config."; | 
| 472 const char kDesc_Help[] = | 751 const char kDesc_Help[] = | 
| 473     "gn desc <out_dir> <target label> [<what to show>] [--blame]\n" | 752     "gn desc <out_dir> <label or pattern> [<what to show>] [--blame]\n" | 
| 474     "\n" | 753     "\n" | 
| 475     "  Displays information about a given labeled target for the given build.\n" | 754     "  Displays information about a given target or config. The build\n" | 
| 476     "  The build parameters will be taken for the build in the given\n" | 755     "  build parameters will be taken for the build in the given <out_dir>.\n" | 
| 477     "  <out_dir>.\n" | 756     "\n" | 
|  | 757     "  The <label or pattern> can be a target label, a config label, or a\n" | 
|  | 758     "  label pattern (see \"gn help label_pattern\"). A label pattern will\n" | 
|  | 759     "  only match targets.\n" | 
| 478     "\n" | 760     "\n" | 
| 479     "Possibilities for <what to show>\n" | 761     "Possibilities for <what to show>\n" | 
|  | 762     "\n" | 
| 480     "  (If unspecified an overall summary will be displayed.)\n" | 763     "  (If unspecified an overall summary will be displayed.)\n" | 
| 481     "\n" | 764     "\n" | 
| 482     "  sources\n" | 765     "  all_dependent_configs\n" | 
| 483     "      Source files.\n" | 766     "  allow_circular_includes_from\n" | 
| 484     "\n" | 767     "  arflags [--blame]\n" | 
|  | 768     "  args\n" | 
|  | 769     "  cflags [--blame]\n" | 
|  | 770     "  cflags_cc [--blame]\n" | 
|  | 771     "  cflags_cxx [--blame]\n" | 
|  | 772     "  check_includes\n" | 
|  | 773     "  configs [--tree] (see below)\n" | 
|  | 774     "  defines [--blame]\n" | 
|  | 775     "  depfile\n" | 
|  | 776     "  deps [--all] [--tree] (see below)\n" | 
|  | 777     "  include_dirs [--blame]\n" | 
| 485     "  inputs\n" | 778     "  inputs\n" | 
| 486     "      Additional input dependencies.\n" | 779     "  ldflags [--blame]\n" | 
| 487     "\n" |  | 
| 488     "  public\n" |  | 
| 489     "      Public header files.\n" |  | 
| 490     "\n" |  | 
| 491     "  check_includes\n" |  | 
| 492     "      Whether \"gn check\" checks this target for include usage.\n" |  | 
| 493     "\n" |  | 
| 494     "  allow_circular_includes_from\n" |  | 
| 495     "      Permit includes from these targets.\n" |  | 
| 496     "\n" |  | 
| 497     "  visibility\n" |  | 
| 498     "      Prints which targets can depend on this one.\n" |  | 
| 499     "\n" |  | 
| 500     "  testonly\n" |  | 
| 501     "      Whether this target may only be used in tests.\n" |  | 
| 502     "\n" |  | 
| 503     "  configs\n" |  | 
| 504     "      Shows configs applied to the given target, sorted in the order\n" |  | 
| 505     "      they're specified. This includes both configs specified in the\n" |  | 
| 506     "      \"configs\" variable, as well as configs pushed onto this target\n" |  | 
| 507     "      via dependencies specifying \"all\" or \"direct\" dependent\n" |  | 
| 508     "      configs.\n" |  | 
| 509     "\n" |  | 
| 510     "  deps\n" |  | 
| 511     "      Show immediate or recursive dependencies. See below for flags that\n" |  | 
| 512     "      control deps printing.\n" |  | 
| 513     "\n" |  | 
| 514     "  public_configs\n" |  | 
| 515     "  all_dependent_configs\n" |  | 
| 516     "      Shows the labels of configs applied to targets that depend on this\n" |  | 
| 517     "      one (either directly or all of them).\n" |  | 
| 518     "\n" |  | 
| 519     "  script\n" |  | 
| 520     "  args\n" |  | 
| 521     "  depfile\n" |  | 
| 522     "      Actions only. The script and related values.\n" |  | 
| 523     "\n" |  | 
| 524     "  outputs\n" |  | 
| 525     "      Outputs for script and copy target types.\n" |  | 
| 526     "\n" |  | 
| 527     "  arflags       [--blame]\n" |  | 
| 528     "  defines       [--blame]\n" |  | 
| 529     "  include_dirs  [--blame]\n" |  | 
| 530     "  cflags        [--blame]\n" |  | 
| 531     "  cflags_cc     [--blame]\n" |  | 
| 532     "  cflags_cxx    [--blame]\n" |  | 
| 533     "  ldflags       [--blame]\n" |  | 
| 534     "  lib_dirs\n" | 780     "  lib_dirs\n" | 
| 535     "  libs\n" | 781     "  libs\n" | 
| 536     "      Shows the given values taken from the target and all configs\n" | 782     "  outputs\n" | 
| 537     "      applying. See \"--blame\" below.\n" | 783     "  public_configs\n" | 
|  | 784     "  public\n" | 
|  | 785     "  script\n" | 
|  | 786     "  sources\n" | 
|  | 787     "  testonly\n" | 
|  | 788     "  visibility\n" | 
| 538     "\n" | 789     "\n" | 
| 539     "  runtime_deps\n" | 790     "  runtime_deps\n" | 
| 540     "      Compute all runtime deps for the given target. This is a\n" | 791     "      Compute all runtime deps for the given target. This is a\n" | 
| 541     "      computed list and does not correspond to any GN variable, unlike\n" | 792     "      computed list and does not correspond to any GN variable, unlike\n" | 
| 542     "      most other values here.\n" | 793     "      most other values here.\n" | 
| 543     "\n" | 794     "\n" | 
| 544     "      The output is a list of file names relative to the build\n" | 795     "      The output is a list of file names relative to the build\n" | 
| 545     "      directory. See \"gn help runtime_deps\" for how this is computed.\n" | 796     "      directory. See \"gn help runtime_deps\" for how this is computed.\n" | 
| 546     "      This also works with \"--blame\" to see the source of the\n" | 797     "      This also works with \"--blame\" to see the source of the\n" | 
| 547     "      dependency.\n" | 798     "      dependency.\n" | 
| 548     "\n" | 799     "\n" | 
| 549     "Shared flags\n" | 800     "Shared flags\n" | 
| 550     "\n" | 801     "\n" | 
|  | 802     ALL_TOOLCHAINS_SWITCH_HELP | 
|  | 803     "\n" | 
|  | 804     "Target flags\n" | 
|  | 805     "\n" | 
| 551     "  --blame\n" | 806     "  --blame\n" | 
| 552     "      Used with any value specified by a config, this will name\n" | 807     "      Used with any value specified on a config, this will name\n" | 
| 553     "      the config that specified the value. This doesn't currently work\n" | 808     "      the config that cause that target to get the flag. This doesn't\n" | 
| 554     "      for libs and lib_dirs because those are inherited and are more\n" | 809     "      currently work for libs and lib_dirs because those are inherited\n" | 
| 555     "      complicated to figure out the blame (patches welcome).\n" | 810     "      and are more complicated to figure out the blame (patches\n" | 
|  | 811     "      welcome).\n" | 
| 556     "\n" | 812     "\n" | 
| 557     "Flags that control how deps are printed\n" | 813     "Configs\n" | 
|  | 814     "\n" | 
|  | 815     "  The \"configs\" section will list all configs that apply. For targets\n" | 
|  | 816     "  this will include configs specified in the \"configs\" variable of\n" | 
|  | 817     "  the target, and also configs pushed onto this target via public\n" | 
|  | 818     "  or \"all dependent\" configs.\n" | 
|  | 819     "\n" | 
|  | 820     "  Configs can have child configs. Specifying --tree will show the\n" | 
|  | 821     "  hierarchy.\n" | 
|  | 822     "\n" | 
|  | 823     "Printing deps\n" | 
|  | 824     "\n" | 
|  | 825     "  Deps will include all public, private, and data deps (TODO this could\n" | 
|  | 826     "  be clarified and enhanced) sorted in order applying. The following\n" | 
|  | 827     "  may be used:\n" | 
| 558     "\n" | 828     "\n" | 
| 559     "  --all\n" | 829     "  --all\n" | 
| 560     "      Collects all recursive dependencies and prints a sorted flat list.\n" | 830     "      Collects all recursive dependencies and prints a sorted flat list.\n" | 
| 561     "      Also usable with --tree (see below).\n" | 831     "      Also usable with --tree (see below).\n" | 
| 562     "\n" | 832     "\n" | 
| 563     TARGET_PRINTING_MODE_COMMAND_LINE_HELP | 833     TARGET_PRINTING_MODE_COMMAND_LINE_HELP | 
| 564     "\n" | 834     "\n" | 
| 565     TARGET_TESTONLY_FILTER_COMMAND_LINE_HELP | 835     TARGET_TESTONLY_FILTER_COMMAND_LINE_HELP | 
| 566     "\n" | 836     "\n" | 
| 567     "  --tree\n" | 837     "  --tree\n" | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 591     "      Summarizes the given target.\n" | 861     "      Summarizes the given target.\n" | 
| 592     "\n" | 862     "\n" | 
| 593     "  gn desc out/Foo :base_unittests deps --tree\n" | 863     "  gn desc out/Foo :base_unittests deps --tree\n" | 
| 594     "      Shows a dependency tree of the \"base_unittests\" project in\n" | 864     "      Shows a dependency tree of the \"base_unittests\" project in\n" | 
| 595     "      the current directory.\n" | 865     "      the current directory.\n" | 
| 596     "\n" | 866     "\n" | 
| 597     "  gn desc out/Debug //base defines --blame\n" | 867     "  gn desc out/Debug //base defines --blame\n" | 
| 598     "      Shows defines set for the //base:base target, annotated by where\n" | 868     "      Shows defines set for the //base:base target, annotated by where\n" | 
| 599     "      each one was set from.\n"; | 869     "      each one was set from.\n"; | 
| 600 | 870 | 
| 601 #define OUTPUT_CONFIG_VALUE(name, type) \ |  | 
| 602     OutputRecursiveTargetConfig<type>(target, #name, &ConfigValues::name); |  | 
| 603 |  | 
| 604 int RunDesc(const std::vector<std::string>& args) { | 871 int RunDesc(const std::vector<std::string>& args) { | 
| 605   if (args.size() != 2 && args.size() != 3) { | 872   if (args.size() != 2 && args.size() != 3) { | 
| 606     Err(Location(), "You're holding it wrong.", | 873     Err(Location(), "You're holding it wrong.", | 
| 607         "Usage: \"gn desc <out_dir> <target_name> [<what to display>]\"") | 874         "Usage: \"gn desc <out_dir> <target_name> [<what to display>]\"") | 
| 608         .PrintToStdout(); | 875         .PrintToStdout(); | 
| 609     return 1; | 876     return 1; | 
| 610   } | 877   } | 
|  | 878   const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); | 
| 611 | 879 | 
| 612   // Deliberately leaked to avoid expensive process teardown. | 880   // Deliberately leaked to avoid expensive process teardown. | 
| 613   Setup* setup = new Setup; | 881   Setup* setup = new Setup; | 
| 614   setup->build_settings().set_check_for_bad_items(false); | 882   setup->build_settings().set_check_for_bad_items(false); | 
| 615   if (!setup->DoSetup(args[0], false)) | 883   if (!setup->DoSetup(args[0], false)) | 
| 616     return 1; | 884     return 1; | 
| 617   if (!setup->Run()) | 885   if (!setup->Run()) | 
| 618     return 1; | 886     return 1; | 
| 619 | 887 | 
| 620   const Target* target = ResolveTargetFromCommandLineString(setup, args[1]); | 888   // Resolve target(s) and config from inputs. | 
| 621   if (!target) | 889   UniqueVector<const Target*> target_matches; | 
|  | 890   UniqueVector<const Config*> config_matches; | 
|  | 891   UniqueVector<const Toolchain*> toolchain_matches; | 
|  | 892   UniqueVector<SourceFile> file_matches; | 
|  | 893 | 
|  | 894   std::vector<std::string> target_list; | 
|  | 895   target_list.push_back(args[1]); | 
|  | 896 | 
|  | 897   if (!ResolveFromCommandLineInput( | 
|  | 898           setup, target_list, cmdline->HasSwitch(switches::kAllToolchains), | 
|  | 899           &target_matches, &config_matches, &toolchain_matches, &file_matches)) | 
| 622     return 1; | 900     return 1; | 
| 623 | 901 | 
| 624 #define CONFIG_VALUE_HANDLER(name, type) \ | 902   std::string what_to_print; | 
| 625     } else if (what == #name) { OUTPUT_CONFIG_VALUE(name, type) | 903   if (args.size() == 3) | 
|  | 904     what_to_print = args[2]; | 
| 626 | 905 | 
| 627   if (args.size() == 3) { | 906   bool multiple_outputs = (target_matches.size() + config_matches.size()) > 1; | 
| 628     // User specified one thing to display. |  | 
| 629     const std::string& what = args[2]; |  | 
| 630     if (what == variables::kConfigs) { |  | 
| 631       PrintConfigs(target, false); |  | 
| 632     } else if (what == variables::kPublicConfigs) { |  | 
| 633       PrintPublicConfigs(target, false); |  | 
| 634     } else if (what == variables::kAllDependentConfigs) { |  | 
| 635       PrintAllDependentConfigs(target, false); |  | 
| 636     } else if (what == variables::kSources) { |  | 
| 637       PrintSources(target, false); |  | 
| 638     } else if (what == variables::kPublic) { |  | 
| 639       PrintPublic(target, false); |  | 
| 640     } else if (what == variables::kCheckIncludes) { |  | 
| 641       PrintCheckIncludes(target, false); |  | 
| 642     } else if (what == variables::kAllowCircularIncludesFrom) { |  | 
| 643       PrintAllowCircularIncludesFrom(target, false); |  | 
| 644     } else if (what == variables::kVisibility) { |  | 
| 645       PrintVisibility(target, false); |  | 
| 646     } else if (what == variables::kTestonly) { |  | 
| 647       PrintTestonly(target, false); |  | 
| 648     } else if (what == variables::kInputs) { |  | 
| 649       PrintInputs(target, false); |  | 
| 650     } else if (what == variables::kScript) { |  | 
| 651       PrintScript(target, false); |  | 
| 652     } else if (what == variables::kArgs) { |  | 
| 653       PrintArgs(target, false); |  | 
| 654     } else if (what == variables::kDepfile) { |  | 
| 655       PrintDepfile(target, false); |  | 
| 656     } else if (what == variables::kOutputs) { |  | 
| 657       PrintOutputs(target, false); |  | 
| 658     } else if (what == variables::kDeps) { |  | 
| 659       PrintDeps(target, false); |  | 
| 660     } else if (what == variables::kLibDirs) { |  | 
| 661       PrintLibDirs(target, false); |  | 
| 662     } else if (what == variables::kLibs) { |  | 
| 663       PrintLibs(target, false); |  | 
| 664     } else if (what == "runtime_deps") { |  | 
| 665       PrintRuntimeDeps(target); |  | 
| 666 //  }  Hidden closing brace in macro below. |  | 
| 667 | 907 | 
| 668     CONFIG_VALUE_HANDLER(defines, std::string) | 908   // Display headers for each target when printing all values, or when printing | 
| 669     CONFIG_VALUE_HANDLER(include_dirs, SourceDir) | 909   // multiple targets or configs. | 
| 670     CONFIG_VALUE_HANDLER(arflags, std::string) | 910   bool display_item_header = multiple_outputs || what_to_print.empty(); | 
| 671     CONFIG_VALUE_HANDLER(asmflags, std::string) |  | 
| 672     CONFIG_VALUE_HANDLER(cflags, std::string) |  | 
| 673     CONFIG_VALUE_HANDLER(cflags_c, std::string) |  | 
| 674     CONFIG_VALUE_HANDLER(cflags_cc, std::string) |  | 
| 675     CONFIG_VALUE_HANDLER(cflags_objc, std::string) |  | 
| 676     CONFIG_VALUE_HANDLER(cflags_objcc, std::string) |  | 
| 677     CONFIG_VALUE_HANDLER(ldflags, std::string) |  | 
| 678 | 911 | 
| 679     } else { | 912   bool printed_output = false; | 
| 680       OutputString("Don't know how to display \"" + what + "\".\n"); | 913   for (const Target* target : target_matches) { | 
|  | 914     if (printed_output) | 
|  | 915       OutputString("\n\n"); | 
|  | 916     printed_output = true; | 
|  | 917 | 
|  | 918     if (!PrintTarget(target, what_to_print, display_item_header)) | 
| 681       return 1; | 919       return 1; | 
| 682     } | 920   } | 
|  | 921   for (const Config* config : config_matches) { | 
|  | 922     if (printed_output) | 
|  | 923       OutputString("\n\n"); | 
|  | 924     printed_output = true; | 
| 683 | 925 | 
| 684 #undef CONFIG_VALUE_HANDLER | 926     if (!PrintConfig(config, what_to_print, display_item_header)) | 
| 685     return 0; | 927       return 1; | 
| 686   } | 928   } | 
| 687 | 929 | 
| 688   // Display summary. |  | 
| 689 |  | 
| 690   // Display this only applicable to binary targets. |  | 
| 691   bool is_binary_output = |  | 
| 692     target->output_type() != Target::GROUP && |  | 
| 693     target->output_type() != Target::COPY_FILES && |  | 
| 694     target->output_type() != Target::ACTION && |  | 
| 695     target->output_type() != Target::ACTION_FOREACH && |  | 
| 696     target->output_type() != Target::BUNDLE_DATA && |  | 
| 697     target->output_type() != Target::CREATE_BUNDLE; |  | 
| 698 |  | 
| 699   // Generally we only want to display toolchains on labels when the toolchain |  | 
| 700   // is different than the default one for this target (which we always print |  | 
| 701   // in the header). |  | 
| 702   Label target_toolchain = target->label().GetToolchainLabel(); |  | 
| 703 |  | 
| 704   // Header. |  | 
| 705   OutputString("Target: ", DECORATION_YELLOW); |  | 
| 706   OutputString(target->label().GetUserVisibleName(false) + "\n"); |  | 
| 707   OutputString("Type: ", DECORATION_YELLOW); |  | 
| 708   OutputString(std::string( |  | 
| 709       Target::GetStringForOutputType(target->output_type())) + "\n"); |  | 
| 710   OutputString("Toolchain: ", DECORATION_YELLOW); |  | 
| 711   OutputString(target_toolchain.GetUserVisibleName(false) + "\n"); |  | 
| 712 |  | 
| 713   PrintSources(target, true); |  | 
| 714   if (is_binary_output) { |  | 
| 715     PrintPublic(target, true); |  | 
| 716     PrintCheckIncludes(target, true); |  | 
| 717     PrintAllowCircularIncludesFrom(target, true); |  | 
| 718   } |  | 
| 719   PrintVisibility(target, true); |  | 
| 720   if (is_binary_output) { |  | 
| 721     PrintTestonly(target, true); |  | 
| 722     PrintConfigs(target, true); |  | 
| 723   } |  | 
| 724 |  | 
| 725   PrintPublicConfigs(target, true); |  | 
| 726   PrintAllDependentConfigs(target, true); |  | 
| 727 |  | 
| 728   PrintInputs(target, true); |  | 
| 729 |  | 
| 730   if (is_binary_output) { |  | 
| 731     OUTPUT_CONFIG_VALUE(defines, std::string) |  | 
| 732     OUTPUT_CONFIG_VALUE(include_dirs, SourceDir) |  | 
| 733     OUTPUT_CONFIG_VALUE(asmflags, std::string) |  | 
| 734     OUTPUT_CONFIG_VALUE(cflags, std::string) |  | 
| 735     OUTPUT_CONFIG_VALUE(cflags_c, std::string) |  | 
| 736     OUTPUT_CONFIG_VALUE(cflags_cc, std::string) |  | 
| 737     OUTPUT_CONFIG_VALUE(cflags_objc, std::string) |  | 
| 738     OUTPUT_CONFIG_VALUE(cflags_objcc, std::string) |  | 
| 739 |  | 
| 740     if (target->output_type() == Target::STATIC_LIBRARY) |  | 
| 741       OUTPUT_CONFIG_VALUE(arflags, std::string) |  | 
| 742     else if (target->output_type() != Target::SOURCE_SET) |  | 
| 743       OUTPUT_CONFIG_VALUE(ldflags, std::string) |  | 
| 744   } |  | 
| 745 |  | 
| 746   if (target->output_type() == Target::ACTION || |  | 
| 747       target->output_type() == Target::ACTION_FOREACH) { |  | 
| 748     PrintScript(target, true); |  | 
| 749     PrintArgs(target, true); |  | 
| 750     PrintDepfile(target, true); |  | 
| 751   } |  | 
| 752 |  | 
| 753   if (target->output_type() == Target::ACTION || |  | 
| 754       target->output_type() == Target::ACTION_FOREACH || |  | 
| 755       target->output_type() == Target::COPY_FILES || |  | 
| 756       target->output_type() == Target::CREATE_BUNDLE) { |  | 
| 757     PrintOutputs(target, true); |  | 
| 758   } |  | 
| 759 |  | 
| 760   // Libs can be part of any target and get recursively pushed up the chain, |  | 
| 761   // so always display them, even for groups and such. |  | 
| 762   PrintLibs(target, true); |  | 
| 763   PrintLibDirs(target, true); |  | 
| 764 |  | 
| 765   PrintDeps(target, true); |  | 
| 766 |  | 
| 767   return 0; | 930   return 0; | 
| 768 } | 931 } | 
| 769 | 932 | 
| 770 }  // namespace commands | 933 }  // namespace commands | 
| OLD | NEW | 
|---|