| 611 | } |
| 612 | |
| 613 | void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( |
| 614 | cmCustomCommand const* cc, std::set<cmGeneratorTarget*> const& targets, |
| 615 | std::string const& fileConfig) |
| 616 | { |
| 617 | cmGlobalNinjaGenerator* gg = this->GetGlobalNinjaGenerator(); |
| 618 | if (gg->SeenCustomCommand(cc, fileConfig)) { |
| 619 | return; |
| 620 | } |
| 621 | |
| 622 | auto ccgs = this->MakeCustomCommandGenerators(*cc, fileConfig); |
| 623 | for (cmCustomCommandGenerator const& ccg : ccgs) { |
| 624 | if (ccg.GetOutputs().empty() && ccg.GetByproducts().empty()) { |
| 625 | // Generator expressions evaluate to no output for this config. |
| 626 | continue; |
| 627 | } |
| 628 | |
| 629 | std::unordered_set<std::string> orderOnlyDeps; |
| 630 | |
| 631 | if (!cc->GetDependsExplicitOnly()) { |
| 632 | // A custom command may appear on multiple targets. However, some build |
| 633 | // systems exist where the target dependencies on some of the targets are |
| 634 | // overspecified, leading to a dependency cycle. If we assume all target |
| 635 | // dependencies are a superset of the true target dependencies for this |
| 636 | // custom command, we can take the set intersection of all target |
| 637 | // dependencies to obtain a correct dependency list. |
| 638 | // |
| 639 | // FIXME: This won't work in certain obscure scenarios involving indirect |
| 640 | // dependencies. |
| 641 | auto j = targets.begin(); |
| 642 | assert(j != targets.end()); |
| 643 | this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure( |
| 644 | *j, orderOnlyDeps, ccg.GetOutputConfig(), fileConfig, ccgs.size() > 1); |
| 645 | ++j; |
| 646 | |
| 647 | for (; j != targets.end(); ++j) { |
| 648 | std::unordered_set<std::string> jDeps; |
| 649 | this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure( |
| 650 | *j, jDeps, ccg.GetOutputConfig(), fileConfig, ccgs.size() > 1); |
| 651 | cm::erase_if(orderOnlyDeps, [&jDeps](std::string const& dep) { |
| 652 | return jDeps.find(dep) == jDeps.end(); |
| 653 | }); |
| 654 | } |
| 655 | } |
| 656 | |
| 657 | std::vector<std::string> const& outputs = ccg.GetOutputs(); |
| 658 | std::vector<std::string> const& byproducts = ccg.GetByproducts(); |
| 659 | |
| 660 | bool symbolic = false; |
| 661 | for (std::string const& output : outputs) { |
| 662 | if (cmSourceFile* sf = this->Makefile->GetSource(output)) { |
| 663 | if (sf->GetPropertyAsBool("SYMBOLIC")) { |
| 664 | symbolic = true; |
| 665 | break; |
| 666 | } |
| 667 | } |
| 668 | } |
| 669 | |
| 670 | cmGlobalNinjaGenerator::CCOutputs ccOutputs(gg); |
no test coverage detected