Build tool
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DepNode.cc 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #include "DepNode.h"
  2. #include <mutex>
  3. #include <condition_variable>
  4. #include <unordered_set>
  5. #include "parallel.h"
  6. #include "logger.h"
  7. static void maybeAddStrings(
  8. std::unordered_set<std::string> &set,
  9. const std::vector<std::string> &vec,
  10. std::vector<std::string> &out) {
  11. for (auto &str: vec) {
  12. auto pair = set.emplace(str);
  13. bool inserted = pair.second;
  14. if (inserted) {
  15. out.push_back(str);
  16. }
  17. }
  18. }
  19. void DepNode::addChild(std::shared_ptr<DepNode> node) {
  20. deps_.push_back(std::move(node));
  21. }
  22. bool DepNode::haveDepsChanged(const std::string &outDir) {
  23. auto it = deps_.begin();
  24. bool changed = false;
  25. int workers = 0;
  26. std::mutex mut;
  27. std::condition_variable cond;
  28. std::unique_lock<std::mutex> lock(mut, std::defer_lock);
  29. while (it != deps_.end()) {
  30. lock.lock();
  31. if (changed) {
  32. cond.wait(lock, [&] { return workers == 0; });
  33. return true;
  34. }
  35. workers += 1;
  36. lock.unlock();
  37. parallel::run([&, it] {
  38. bool ch = (*it)->hasChanged(outDir);
  39. std::unique_lock<std::mutex> lock(mut);
  40. workers -= 1;
  41. if (ch) {
  42. changed = true;
  43. }
  44. lock.unlock();
  45. cond.notify_one();
  46. });
  47. it = ++it;
  48. }
  49. lock.lock();
  50. cond.wait(lock, [&] { return workers == 0; });
  51. return changed;
  52. }
  53. bool DepNode::hasChanged(const std::string &outDir) {
  54. std::lock_guard<std::mutex> lock(mut_);
  55. if (was_rebuilt_) {
  56. return true;
  57. }
  58. if (has_changed_ == TriState::TRUE) {
  59. return true;
  60. } else if (has_changed_ == TriState::FALSE) {
  61. return false;
  62. } else {
  63. bool changed = checkHasChanged(outDir);
  64. if (!changed) {
  65. changed = haveDepsChanged(outDir);
  66. }
  67. if (changed) {
  68. has_changed_ = TriState::TRUE;
  69. return true;
  70. } else {
  71. has_changed_ = TriState::FALSE;
  72. return false;
  73. }
  74. }
  75. }
  76. void DepNode::build(const std::string &outDir) {
  77. bool changed = hasChanged(outDir);
  78. std::lock_guard<std::mutex> lock(mut_);\
  79. if (!was_rebuilt_ && changed) {
  80. int workers = 0;
  81. std::mutex mut;
  82. std::condition_variable cond;
  83. std::unique_lock<std::mutex> lock(mut, std::defer_lock);
  84. for (auto &dep: deps_) {
  85. if (dep->hasChanged(outDir)) {
  86. lock.lock();
  87. workers += 1;
  88. lock.unlock();
  89. parallel::run([&] {
  90. dep->build(outDir);
  91. std::unique_lock<std::mutex> lock(mut);
  92. workers -= 1;
  93. lock.unlock();
  94. cond.notify_one();
  95. });
  96. }
  97. }
  98. lock.lock();
  99. cond.wait(lock, [&] { return workers == 0; });
  100. doBuild(outDir);
  101. was_rebuilt_ = true;
  102. }
  103. }
  104. std::vector<std::string> DepNode::publicLDFlags(const std::string &outDir) {
  105. std::unordered_set<std::string> set;
  106. std::vector<std::string> flags;
  107. maybeAddStrings(set, getPublicLDFlags(outDir), flags);
  108. for (auto &dep: deps_) {
  109. maybeAddStrings(set, dep->publicLDFlags(outDir), flags);
  110. }
  111. return flags;
  112. }
  113. std::vector<std::string> DepNode::publicLDLibs(const std::string &outDir) {
  114. std::unordered_set<std::string> set;
  115. std::vector<std::string> libs;
  116. maybeAddStrings(set, getPublicLDLibs(outDir), libs);
  117. for (auto &dep: deps_) {
  118. maybeAddStrings(set, dep->publicLDLibs(outDir), libs);
  119. }
  120. return libs;
  121. }
  122. std::vector<std::string> DepNode::publicObjects(const std::string &outDir) {
  123. std::vector<std::string> objs = getPublicObjects(outDir);;
  124. for (auto &dep: deps_) {
  125. for (auto &obj: dep->publicObjects(outDir)) {
  126. objs.push_back(obj);
  127. }
  128. }
  129. return objs;
  130. }