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::kPrecomiledSources || 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) { | |
scottmg
2016/05/10 18:59:39
I suspect this might be incorrect. :p
| |
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 |