cmLinkItemGraphVisitor.cxx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmLinkItemGraphVisitor.h"
  4. #include <map>
  5. #include <utility>
  6. #include <vector>
  7. #include "cmGeneratorTarget.h"
  8. #include "cmLinkItem.h"
  9. #include "cmMakefile.h"
  10. void cmLinkItemGraphVisitor::VisitItem(cmLinkItem const& item)
  11. {
  12. if (this->ItemVisited(item)) {
  13. return;
  14. }
  15. this->OnItem(item);
  16. this->VisitLinks(item, item);
  17. }
  18. void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item,
  19. cmLinkItem const& rootItem)
  20. {
  21. if (item.Target == nullptr) {
  22. return;
  23. }
  24. for (auto const& config : item.Target->Makefile->GetGeneratorConfigs(
  25. cmMakefile::IncludeEmptyConfig)) {
  26. this->VisitLinks(item, rootItem, config);
  27. }
  28. }
  29. void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item,
  30. cmLinkItem const& rootItem,
  31. std::string const& config)
  32. {
  33. auto const& target = *item.Target;
  34. DependencyMap dependencies;
  35. cmLinkItemGraphVisitor::GetDependencies(target, config, dependencies);
  36. for (auto const& d : dependencies) {
  37. auto const& dependency = d.second;
  38. auto const& dependencyType = dependency.first;
  39. auto const& dependee = dependency.second;
  40. this->VisitItem(dependee);
  41. if (this->LinkVisited(item, dependee)) {
  42. continue;
  43. }
  44. this->OnDirectLink(item, dependee, dependencyType);
  45. if (rootItem.AsStr() != item.AsStr()) {
  46. this->OnIndirectLink(rootItem, dependee);
  47. }
  48. // Visit all the direct and indirect links.
  49. this->VisitLinks(dependee, dependee);
  50. this->VisitLinks(dependee, item);
  51. this->VisitLinks(dependee, rootItem);
  52. }
  53. }
  54. bool cmLinkItemGraphVisitor::ItemVisited(cmLinkItem const& item)
  55. {
  56. auto& collection = this->VisitedItems;
  57. bool const visited = collection.find(item.AsStr()) != collection.cend();
  58. if (!visited) {
  59. collection.insert(item.AsStr());
  60. }
  61. return visited;
  62. }
  63. bool cmLinkItemGraphVisitor::LinkVisited(cmLinkItem const& depender,
  64. cmLinkItem const& dependee)
  65. {
  66. auto const link = std::make_pair<>(depender.AsStr(), dependee.AsStr());
  67. bool const linkVisited =
  68. this->VisitedLinks.find(link) != this->VisitedLinks.cend();
  69. if (!linkVisited) {
  70. this->VisitedLinks.insert(link);
  71. }
  72. return linkVisited;
  73. }
  74. void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target,
  75. std::string const& config,
  76. DependencyMap& dependencies)
  77. {
  78. auto implementationLibraries = target.GetLinkImplementationLibraries(config);
  79. if (implementationLibraries != nullptr) {
  80. for (auto const& lib : implementationLibraries->Libraries) {
  81. auto const& name = lib.AsStr();
  82. dependencies[name] = Dependency(DependencyType::LinkPrivate, lib);
  83. }
  84. }
  85. auto interfaceLibraries =
  86. target.GetLinkInterfaceLibraries(config, &target, true);
  87. if (interfaceLibraries != nullptr) {
  88. for (auto const& lib : interfaceLibraries->Libraries) {
  89. auto const& name = lib.AsStr();
  90. if (dependencies.find(name) != dependencies.cend()) {
  91. dependencies[name] = Dependency(DependencyType::LinkPublic, lib);
  92. } else {
  93. dependencies[name] = Dependency(DependencyType::LinkInterface, lib);
  94. }
  95. }
  96. }
  97. std::vector<cmGeneratorTarget*> objectLibraries;
  98. target.GetObjectLibrariesCMP0026(objectLibraries);
  99. for (auto const& lib : objectLibraries) {
  100. auto const& name = lib->GetName();
  101. if (dependencies.find(name) == dependencies.cend()) {
  102. auto objectItem = cmLinkItem(lib, false, lib->GetBacktrace());
  103. dependencies[name] = Dependency(DependencyType::Object, objectItem);
  104. }
  105. }
  106. auto const& utilityItems = target.GetUtilityItems();
  107. for (auto const& item : utilityItems) {
  108. auto const& name = item.AsStr();
  109. if (dependencies.find(name) == dependencies.cend()) {
  110. dependencies[name] = Dependency(DependencyType::Utility, item);
  111. }
  112. }
  113. }