cmFileSet.cxx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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 "cmFileSet.h"
  4. #include <sstream>
  5. #include <string>
  6. #include <utility>
  7. #include <vector>
  8. #include <cmext/string_view>
  9. #include "cmsys/RegularExpression.hxx"
  10. #include "cmGeneratorExpression.h"
  11. #include "cmListFileCache.h"
  12. #include "cmLocalGenerator.h"
  13. #include "cmMakefile.h"
  14. #include "cmMessageType.h"
  15. #include "cmStringAlgorithms.h"
  16. #include "cmSystemTools.h"
  17. #include "cmake.h"
  18. cm::static_string_view cmFileSetVisibilityToName(cmFileSetVisibility vis)
  19. {
  20. switch (vis) {
  21. case cmFileSetVisibility::Interface:
  22. return "INTERFACE"_s;
  23. case cmFileSetVisibility::Public:
  24. return "PUBLIC"_s;
  25. case cmFileSetVisibility::Private:
  26. return "PRIVATE"_s;
  27. }
  28. return ""_s;
  29. }
  30. cmFileSetVisibility cmFileSetVisibilityFromName(cm::string_view name,
  31. cmMakefile* mf)
  32. {
  33. if (name == "INTERFACE"_s) {
  34. return cmFileSetVisibility::Interface;
  35. }
  36. if (name == "PUBLIC"_s) {
  37. return cmFileSetVisibility::Public;
  38. }
  39. if (name == "PRIVATE"_s) {
  40. return cmFileSetVisibility::Private;
  41. }
  42. auto msg = cmStrCat("File set visibility \"", name, "\" is not valid.");
  43. if (mf) {
  44. mf->IssueMessage(MessageType::FATAL_ERROR, msg);
  45. } else {
  46. cmSystemTools::Error(msg);
  47. }
  48. return cmFileSetVisibility::Private;
  49. }
  50. bool cmFileSetVisibilityIsForSelf(cmFileSetVisibility vis)
  51. {
  52. switch (vis) {
  53. case cmFileSetVisibility::Interface:
  54. return false;
  55. case cmFileSetVisibility::Public:
  56. case cmFileSetVisibility::Private:
  57. return true;
  58. }
  59. return false;
  60. }
  61. bool cmFileSetVisibilityIsForInterface(cmFileSetVisibility vis)
  62. {
  63. switch (vis) {
  64. case cmFileSetVisibility::Interface:
  65. case cmFileSetVisibility::Public:
  66. return true;
  67. case cmFileSetVisibility::Private:
  68. return false;
  69. }
  70. return false;
  71. }
  72. cmFileSet::cmFileSet(cmake& cmakeInstance, std::string name, std::string type,
  73. cmFileSetVisibility visibility)
  74. : CMakeInstance(cmakeInstance)
  75. , Name(std::move(name))
  76. , Type(std::move(type))
  77. , Visibility(visibility)
  78. {
  79. }
  80. void cmFileSet::ClearDirectoryEntries()
  81. {
  82. this->DirectoryEntries.clear();
  83. }
  84. void cmFileSet::AddDirectoryEntry(BT<std::string> directories)
  85. {
  86. this->DirectoryEntries.push_back(std::move(directories));
  87. }
  88. void cmFileSet::ClearFileEntries()
  89. {
  90. this->FileEntries.clear();
  91. }
  92. void cmFileSet::AddFileEntry(BT<std::string> files)
  93. {
  94. this->FileEntries.push_back(std::move(files));
  95. }
  96. std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
  97. cmFileSet::CompileFileEntries() const
  98. {
  99. std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result;
  100. for (auto const& entry : this->FileEntries) {
  101. for (auto const& ex : cmExpandedList(entry.Value)) {
  102. cmGeneratorExpression ge(this->CMakeInstance, entry.Backtrace);
  103. auto cge = ge.Parse(ex);
  104. result.push_back(std::move(cge));
  105. }
  106. }
  107. return result;
  108. }
  109. std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
  110. cmFileSet::CompileDirectoryEntries() const
  111. {
  112. std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result;
  113. for (auto const& entry : this->DirectoryEntries) {
  114. for (auto const& ex : cmExpandedList(entry.Value)) {
  115. cmGeneratorExpression ge(this->CMakeInstance, entry.Backtrace);
  116. auto cge = ge.Parse(ex);
  117. result.push_back(std::move(cge));
  118. }
  119. }
  120. return result;
  121. }
  122. std::vector<std::string> cmFileSet::EvaluateDirectoryEntries(
  123. const std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>& cges,
  124. cmLocalGenerator* lg, const std::string& config,
  125. const cmGeneratorTarget* target,
  126. cmGeneratorExpressionDAGChecker* dagChecker) const
  127. {
  128. std::vector<std::string> result;
  129. for (auto const& cge : cges) {
  130. auto entry = cge->Evaluate(lg, config, target, dagChecker);
  131. auto dirs = cmExpandedList(entry);
  132. for (std::string dir : dirs) {
  133. if (!cmSystemTools::FileIsFullPath(dir)) {
  134. dir = cmStrCat(lg->GetCurrentSourceDirectory(), '/', dir);
  135. }
  136. auto collapsedDir = cmSystemTools::CollapseFullPath(dir);
  137. for (auto const& priorDir : result) {
  138. auto collapsedPriorDir = cmSystemTools::CollapseFullPath(priorDir);
  139. if (!cmSystemTools::SameFile(collapsedDir, collapsedPriorDir) &&
  140. (cmSystemTools::IsSubDirectory(collapsedDir, collapsedPriorDir) ||
  141. cmSystemTools::IsSubDirectory(collapsedPriorDir, collapsedDir))) {
  142. lg->GetCMakeInstance()->IssueMessage(
  143. MessageType::FATAL_ERROR,
  144. cmStrCat(
  145. "Base directories in file set cannot be subdirectories of each "
  146. "other:\n ",
  147. priorDir, "\n ", dir),
  148. cge->GetBacktrace());
  149. return {};
  150. }
  151. }
  152. result.push_back(dir);
  153. }
  154. }
  155. return result;
  156. }
  157. void cmFileSet::EvaluateFileEntry(
  158. const std::vector<std::string>& dirs,
  159. std::map<std::string, std::vector<std::string>>& filesPerDir,
  160. const std::unique_ptr<cmCompiledGeneratorExpression>& cge,
  161. cmLocalGenerator* lg, const std::string& config,
  162. const cmGeneratorTarget* target,
  163. cmGeneratorExpressionDAGChecker* dagChecker) const
  164. {
  165. auto files = cge->Evaluate(lg, config, target, dagChecker);
  166. for (std::string file : cmExpandedList(files)) {
  167. if (!cmSystemTools::FileIsFullPath(file)) {
  168. file = cmStrCat(lg->GetCurrentSourceDirectory(), '/', file);
  169. }
  170. auto collapsedFile = cmSystemTools::CollapseFullPath(file);
  171. bool found = false;
  172. std::string relDir;
  173. for (auto const& dir : dirs) {
  174. auto collapsedDir = cmSystemTools::CollapseFullPath(dir);
  175. if (cmSystemTools::IsSubDirectory(collapsedFile, collapsedDir)) {
  176. found = true;
  177. relDir = cmSystemTools::GetParentDirectory(
  178. cmSystemTools::RelativePath(collapsedDir, collapsedFile));
  179. break;
  180. }
  181. }
  182. if (!found) {
  183. std::ostringstream e;
  184. e << "File:\n " << file
  185. << "\nmust be in one of the file set's base directories:";
  186. for (auto const& dir : dirs) {
  187. e << "\n " << dir;
  188. }
  189. lg->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
  190. cge->GetBacktrace());
  191. return;
  192. }
  193. filesPerDir[relDir].push_back(file);
  194. }
  195. }
  196. bool cmFileSet::IsValidName(const std::string& name)
  197. {
  198. static const cmsys::RegularExpression regex("^[a-z0-9][a-zA-Z0-9_]*$");
  199. cmsys::RegularExpressionMatch match;
  200. return regex.find(name.c_str(), match);
  201. }