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 "tools/gn/ninja_build_writer.h" | 5 #include "tools/gn/ninja_build_writer.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <fstream> | 9 #include <fstream> |
10 #include <map> | 10 #include <map> |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 out_ << "subninja "; | 334 out_ << "subninja "; |
335 path_output_.WriteFile(out_, subninja); | 335 path_output_.WriteFile(out_, subninja); |
336 out_ << std::endl; | 336 out_ << std::endl; |
337 previous_subninja = subninja; | 337 previous_subninja = subninja; |
338 previous_toolchain = pair.second; | 338 previous_toolchain = pair.second; |
339 } | 339 } |
340 out_ << std::endl; | 340 out_ << std::endl; |
341 return true; | 341 return true; |
342 } | 342 } |
343 | 343 |
| 344 const char kNinjaRules_Help[] = |
| 345 R"(Ninja build rules |
| 346 |
| 347 The "all" and "default" rules |
| 348 |
| 349 All generated targets (see "gn help execution") will be added to an implicit |
| 350 build rule called "all" so "ninja all" will always compile everything. The |
| 351 default rule will be used by Ninja if no specific target is specified (just |
| 352 typing "ninja"). If there is a target named "//:default" it will be the |
| 353 default build rule, otherwise the implicit "all" rule will be used. |
| 354 |
| 355 Phony rules |
| 356 |
| 357 GN generates Ninja "phony" rules for targets in the default toolchain. The |
| 358 phony rules can collide with each other and with the names of generated files |
| 359 so are generated with the following priority: |
| 360 |
| 361 1. Actual files generated by the build always take precedence. |
| 362 |
| 363 2. Targets in the toplevel //BUILD.gn file. |
| 364 |
| 365 3. Targets in toplevel directories matching the names of the directories. |
| 366 So "ninja foo" can be used to compile "//foo:foo". This only applies to |
| 367 the first level of directories since usually these are the most |
| 368 important (so this won't apply to "//foo/bar:bar"). |
| 369 |
| 370 4. The short names of executables if there is only one executable with that |
| 371 short name. Use "ninja doom_melon" to compile the |
| 372 "//tools/fruit:doom_melon" executable. |
| 373 |
| 374 5. The short names of all targets if there is only one target with that |
| 375 short name. |
| 376 |
| 377 6. Full label name with no leading slashes. So you can use |
| 378 "ninja tools/fruit:doom_melon" to build "//tools/fruit:doom_melon". |
| 379 |
| 380 7. Labels with an implicit name part (when the short names match the |
| 381 directory). So you can use "ninja foo/bar" to compile "//foo/bar:bar". |
| 382 |
| 383 These "phony" rules are provided only for running Ninja since this matches |
| 384 people's historical expectations for building. For consistency with the rest |
| 385 of the program, GN introspection commands accept explicit labels. |
| 386 |
| 387 To explicitly compile a target in a non-default toolchain, you must give |
| 388 Ninja the exact name of the output file relative to the build directory. |
| 389 )"; |
| 390 |
344 bool NinjaBuildWriter::WritePhonyAndAllRules(Err* err) { | 391 bool NinjaBuildWriter::WritePhonyAndAllRules(Err* err) { |
345 // Track rules as we generate them so we don't accidentally write a phony | 392 // Track rules as we generate them so we don't accidentally write a phony |
346 // rule that collides with something else. | 393 // rule that collides with something else. |
347 // GN internally generates an "all" target, so don't duplicate it. | 394 // GN internally generates an "all" target, so don't duplicate it. |
348 base::hash_set<std::string> written_rules; | 395 base::hash_set<std::string> written_rules; |
349 written_rules.insert("all"); | 396 written_rules.insert("all"); |
350 | 397 |
351 // Set if we encounter a target named "//:default". | 398 // Set if we encounter a target named "//:default". |
352 bool default_target_exists = false; | 399 bool default_target_exists = false; |
353 | 400 |
354 // Targets in the root build file. | 401 // Targets in the root build file. |
355 std::vector<const Target*> toplevel_targets; | 402 std::vector<const Target*> toplevel_targets; |
356 | 403 |
357 // Targets with names matching their toplevel directories. For example | 404 // Targets with names matching their toplevel directories. For example |
358 // "//foo:foo". Expect this is the naming scheme for "big components." | 405 // "//foo:foo". Expect this is the naming scheme for "big components." |
359 std::vector<const Target*> toplevel_dir_targets; | 406 std::vector<const Target*> toplevel_dir_targets; |
360 | 407 |
361 // Tracks the number of each target with the given short name, as well | 408 // Tracks the number of each target with the given short name, as well |
362 // as the short names of executables (which will be a subset of short_names). | 409 // as the short names of executables (which will be a subset of short_names). |
363 std::map<std::string, Counts> short_names; | 410 std::map<std::string, Counts> short_names; |
364 std::map<std::string, Counts> exes; | 411 std::map<std::string, Counts> exes; |
365 | 412 |
| 413 // ---------------------------------------------------- |
| 414 // If you change this algorithm, update the help above! |
| 415 // ---------------------------------------------------- |
| 416 |
366 for (const Target* target : default_toolchain_targets_) { | 417 for (const Target* target : default_toolchain_targets_) { |
367 const Label& label = target->label(); | 418 const Label& label = target->label(); |
368 const std::string& short_name = label.name(); | 419 const std::string& short_name = label.name(); |
369 | 420 |
370 if (label.dir().value() == "//" && label.name() == "default") | 421 if (label.dir().value() == "//" && label.name() == "default") |
371 default_target_exists = true; | 422 default_target_exists = true; |
372 | 423 |
373 // Count the number of targets with the given short name. | 424 // Count the number of targets with the given short name. |
374 Counts& short_names_counts = short_names[short_name]; | 425 Counts& short_names_counts = short_names[short_name]; |
375 short_names_counts.count++; | 426 short_names_counts.count++; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 // (e.g. "//foo/bar:bar" -> "foo/bar"). | 515 // (e.g. "//foo/bar:bar" -> "foo/bar"). |
465 if (FindLastDirComponent(label.dir()) == label.name()) { | 516 if (FindLastDirComponent(label.dir()) == label.name()) { |
466 std::string medium_name = DirectoryWithNoLastSlash(label.dir()); | 517 std::string medium_name = DirectoryWithNoLastSlash(label.dir()); |
467 base::TrimString(medium_name, "/", &medium_name); | 518 base::TrimString(medium_name, "/", &medium_name); |
468 // That may have generated a name the same as the short name of the | 519 // That may have generated a name the same as the short name of the |
469 // target which we already wrote. | 520 // target which we already wrote. |
470 if (medium_name != label.name() && | 521 if (medium_name != label.name() && |
471 written_rules.insert(medium_name).second) | 522 written_rules.insert(medium_name).second) |
472 WritePhonyRule(target, medium_name); | 523 WritePhonyRule(target, medium_name); |
473 } | 524 } |
474 | |
475 // Write the short name if no other target shares that short name and | |
476 // non of the higher-priority rules above claimed it. | |
477 if (short_names[label.name()].count == 1 && | |
478 written_rules.insert(label.name()).second) | |
479 WritePhonyRule(target, label.name()); | |
480 } | 525 } |
481 | 526 |
482 // Write the autogenerated "all" rule. | 527 // Write the autogenerated "all" rule. |
483 if (!default_toolchain_targets_.empty()) { | 528 if (!default_toolchain_targets_.empty()) { |
484 out_ << "\nbuild all: phony"; | 529 out_ << "\nbuild all: phony"; |
485 | 530 |
486 EscapeOptions ninja_escape; | 531 EscapeOptions ninja_escape; |
487 ninja_escape.mode = ESCAPE_NINJA; | 532 ninja_escape.mode = ESCAPE_NINJA; |
488 for (const Target* target : default_toolchain_targets_) { | 533 for (const Target* target : default_toolchain_targets_) { |
489 out_ << " $\n "; | 534 out_ << " $\n "; |
(...skipping 15 matching lines...) Expand all Loading... |
505 EscapeOptions ninja_escape; | 550 EscapeOptions ninja_escape; |
506 ninja_escape.mode = ESCAPE_NINJA; | 551 ninja_escape.mode = ESCAPE_NINJA; |
507 | 552 |
508 // Escape for special chars Ninja will handle. | 553 // Escape for special chars Ninja will handle. |
509 std::string escaped = EscapeString(phony_name, ninja_escape, nullptr); | 554 std::string escaped = EscapeString(phony_name, ninja_escape, nullptr); |
510 | 555 |
511 out_ << "build " << escaped << ": phony "; | 556 out_ << "build " << escaped << ": phony "; |
512 path_output_.WriteFile(out_, target->dependency_output_file()); | 557 path_output_.WriteFile(out_, target->dependency_output_file()); |
513 out_ << std::endl; | 558 out_ << std::endl; |
514 } | 559 } |
OLD | NEW |