cmLinkItemGraphVisitor.cxx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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) {
  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. const auto* implementationLibraries = target.GetLinkImplementationLibraries(
  79. config, cmGeneratorTarget::UseTo::Link);
  80. if (implementationLibraries) {
  81. for (auto const& lib : implementationLibraries->Libraries) {
  82. auto const& name = lib.AsStr();
  83. dependencies[name] = Dependency(DependencyType::LinkPrivate, lib);
  84. }
  85. }
  86. const auto* interfaceLibraries = target.GetLinkInterfaceLibraries(
  87. config, &target, cmGeneratorTarget::UseTo::Compile);
  88. if (interfaceLibraries) {
  89. for (auto const& lib : interfaceLibraries->Libraries) {
  90. auto const& name = lib.AsStr();
  91. if (dependencies.find(name) != dependencies.cend()) {
  92. dependencies[name] = Dependency(DependencyType::LinkPublic, lib);
  93. } else {
  94. dependencies[name] = Dependency(DependencyType::LinkInterface, lib);
  95. }
  96. }
  97. }
  98. std::vector<cmGeneratorTarget*> objectLibraries;
  99. target.GetObjectLibrariesCMP0026(objectLibraries);
  100. for (auto const& lib : objectLibraries) {
  101. auto const& name = lib->GetName();
  102. if (dependencies.find(name) == dependencies.cend()) {
  103. auto objectItem = cmLinkItem(lib, false, lib->GetBacktrace());
  104. dependencies[name] = Dependency(DependencyType::Object, objectItem);
  105. }
  106. }
  107. auto const& utilityItems = target.GetUtilityItems();
  108. for (auto const& item : utilityItems) {
  109. auto const& name = item.AsStr();
  110. if (dependencies.find(name) == dependencies.cend()) {
  111. dependencies[name] = Dependency(DependencyType::Utility, item);
  112. }
  113. }
  114. }