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 |