| 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 |