cmStateSnapshot.cxx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  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 "cmStateSnapshot.h"
  4. #include <algorithm>
  5. #include <cassert>
  6. #include <string>
  7. #include <cm/iterator>
  8. #include "cmDefinitions.h"
  9. #include "cmLinkedTree.h"
  10. #include "cmListFileCache.h"
  11. #include "cmPropertyMap.h"
  12. #include "cmState.h"
  13. #include "cmStateDirectory.h"
  14. #include "cmStatePrivate.h"
  15. #include "cmSystemTools.h"
  16. #include "cmValue.h"
  17. #include "cmVersion.h"
  18. #if defined(__CYGWIN__)
  19. # include "cmStringAlgorithms.h"
  20. #endif
  21. cmStateSnapshot::cmStateSnapshot(cmState* state)
  22. : State(state)
  23. {
  24. }
  25. std::vector<cmStateSnapshot> cmStateSnapshot::GetChildren()
  26. {
  27. return this->Position->BuildSystemDirectory->Children;
  28. }
  29. cmStateSnapshot::cmStateSnapshot(cmState* state,
  30. cmStateDetail::PositionType position)
  31. : State(state)
  32. , Position(position)
  33. {
  34. }
  35. cmStateEnums::SnapshotType cmStateSnapshot::GetType() const
  36. {
  37. return this->Position->SnapshotType;
  38. }
  39. void cmStateSnapshot::SetListFile(std::string const& listfile)
  40. {
  41. *this->Position->ExecutionListFile = listfile;
  42. }
  43. std::string const& cmStateSnapshot::GetExecutionListFile() const
  44. {
  45. return *this->Position->ExecutionListFile;
  46. }
  47. bool cmStateSnapshot::IsValid() const
  48. {
  49. return this->State && this->Position.IsValid()
  50. ? this->Position != this->State->SnapshotData.Root()
  51. : false;
  52. }
  53. cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectory() const
  54. {
  55. return { this->State, this->Position->BuildSystemDirectory->CurrentScope };
  56. }
  57. cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectoryParent() const
  58. {
  59. cmStateSnapshot snapshot;
  60. if (!this->State || this->Position == this->State->SnapshotData.Root()) {
  61. return snapshot;
  62. }
  63. cmStateDetail::PositionType parentPos = this->Position->DirectoryParent;
  64. if (parentPos != this->State->SnapshotData.Root()) {
  65. snapshot = cmStateSnapshot(this->State,
  66. parentPos->BuildSystemDirectory->CurrentScope);
  67. }
  68. return snapshot;
  69. }
  70. cmStateSnapshot cmStateSnapshot::GetCallStackParent() const
  71. {
  72. assert(this->State);
  73. assert(this->Position != this->State->SnapshotData.Root());
  74. cmStateSnapshot snapshot;
  75. cmStateDetail::PositionType parentPos = this->Position;
  76. while (parentPos->SnapshotType == cmStateEnums::PolicyScopeType ||
  77. parentPos->SnapshotType == cmStateEnums::VariableScopeType) {
  78. ++parentPos;
  79. }
  80. if (parentPos->SnapshotType == cmStateEnums::BuildsystemDirectoryType ||
  81. parentPos->SnapshotType == cmStateEnums::BaseType) {
  82. return snapshot;
  83. }
  84. ++parentPos;
  85. while (parentPos->SnapshotType == cmStateEnums::PolicyScopeType ||
  86. parentPos->SnapshotType == cmStateEnums::VariableScopeType) {
  87. ++parentPos;
  88. }
  89. if (parentPos == this->State->SnapshotData.Root()) {
  90. return snapshot;
  91. }
  92. snapshot = cmStateSnapshot(this->State, parentPos);
  93. return snapshot;
  94. }
  95. cmStateSnapshot cmStateSnapshot::GetCallStackBottom() const
  96. {
  97. assert(this->State);
  98. assert(this->Position != this->State->SnapshotData.Root());
  99. cmStateDetail::PositionType pos = this->Position;
  100. while (pos->SnapshotType != cmStateEnums::BaseType &&
  101. pos->SnapshotType != cmStateEnums::BuildsystemDirectoryType &&
  102. pos != this->State->SnapshotData.Root()) {
  103. ++pos;
  104. }
  105. return { this->State, pos };
  106. }
  107. void cmStateSnapshot::PushPolicy(cmPolicies::PolicyMap const& entry, bool weak)
  108. {
  109. cmStateDetail::PositionType pos = this->Position;
  110. pos->Policies = this->State->PolicyStack.Push(
  111. pos->Policies, cmStateDetail::PolicyStackEntry(entry, weak));
  112. }
  113. bool cmStateSnapshot::PopPolicy()
  114. {
  115. cmStateDetail::PositionType pos = this->Position;
  116. if (pos->Policies == pos->PolicyScope) {
  117. return false;
  118. }
  119. pos->Policies = this->State->PolicyStack.Pop(pos->Policies);
  120. return true;
  121. }
  122. bool cmStateSnapshot::CanPopPolicyScope()
  123. {
  124. return this->Position->Policies != this->Position->PolicyScope;
  125. }
  126. void cmStateSnapshot::SetPolicy(cmPolicies::PolicyID id,
  127. cmPolicies::PolicyStatus status)
  128. {
  129. // Update the policy stack from the top to the top-most strong entry.
  130. bool previous_was_weak = true;
  131. for (cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator psi =
  132. this->Position->Policies;
  133. previous_was_weak && psi != this->Position->PolicyRoot; ++psi) {
  134. psi->Set(id, status);
  135. previous_was_weak = psi->Weak;
  136. }
  137. }
  138. cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(cmPolicies::PolicyID id,
  139. bool parent_scope) const
  140. {
  141. if (cmPolicies::IsRemoved(id)) {
  142. return cmPolicies::NEW;
  143. }
  144. cmPolicies::PolicyStatus status = cmPolicies::WARN;
  145. cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator dir =
  146. this->Position->BuildSystemDirectory;
  147. while (true) {
  148. assert(dir.IsValid());
  149. cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator leaf =
  150. dir->CurrentScope->Policies;
  151. cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator root =
  152. dir->CurrentScope->PolicyRoot;
  153. for (; leaf != root; ++leaf) {
  154. if (parent_scope) {
  155. parent_scope = false;
  156. continue;
  157. }
  158. if (leaf->IsDefined(id)) {
  159. status = leaf->Get(id);
  160. return status;
  161. }
  162. }
  163. cmStateDetail::PositionType e = dir->CurrentScope;
  164. cmStateDetail::PositionType p = e->DirectoryParent;
  165. if (p == this->State->SnapshotData.Root()) {
  166. break;
  167. }
  168. dir = p->BuildSystemDirectory;
  169. }
  170. return status;
  171. }
  172. cmValue cmStateSnapshot::GetDefinition(std::string const& name) const
  173. {
  174. assert(this->Position->Vars.IsValid());
  175. return cmDefinitions::Get(name, this->Position->Vars, this->Position->Root);
  176. }
  177. bool cmStateSnapshot::IsInitialized(std::string const& name) const
  178. {
  179. return cmDefinitions::HasKey(name, this->Position->Vars,
  180. this->Position->Root);
  181. }
  182. void cmStateSnapshot::SetDefinition(std::string const& name,
  183. cm::string_view value)
  184. {
  185. this->Position->Vars->Set(name, value);
  186. }
  187. void cmStateSnapshot::RemoveDefinition(std::string const& name)
  188. {
  189. this->Position->Vars->Unset(name);
  190. }
  191. std::vector<std::string> cmStateSnapshot::ClosureKeys() const
  192. {
  193. return cmDefinitions::ClosureKeys(this->Position->Vars,
  194. this->Position->Root);
  195. }
  196. bool cmStateSnapshot::RaiseScope(std::string const& var, char const* varDef)
  197. {
  198. if (this->Position->ScopeParent == this->Position->DirectoryParent) {
  199. cmStateSnapshot parentDir = this->GetBuildsystemDirectoryParent();
  200. if (!parentDir.IsValid()) {
  201. return false;
  202. }
  203. // Update the definition in the parent directory top scope. This
  204. // directory's scope was initialized by the closure of the parent
  205. // scope, so we do not need to localize the definition first.
  206. if (varDef) {
  207. parentDir.SetDefinition(var, varDef);
  208. } else {
  209. parentDir.RemoveDefinition(var);
  210. }
  211. return true;
  212. }
  213. // First localize the definition in the current scope.
  214. cmDefinitions::Raise(var, this->Position->Vars, this->Position->Root);
  215. // Now update the definition in the parent scope.
  216. if (varDef) {
  217. this->Position->Parent->Set(var, varDef);
  218. } else {
  219. this->Position->Parent->Unset(var);
  220. }
  221. return true;
  222. }
  223. template <typename T, typename U>
  224. void InitializeContentFromParent(T& parentContent, T& thisContent,
  225. U& contentEndPosition)
  226. {
  227. auto parentEnd = parentContent.end();
  228. auto parentRbegin = cm::make_reverse_iterator(parentEnd);
  229. auto parentRend = parentContent.rend();
  230. parentRbegin = std::find(parentRbegin, parentRend, cmPropertySentinel);
  231. auto parentIt = parentRbegin.base();
  232. thisContent = std::vector<BT<std::string>>(parentIt, parentEnd);
  233. contentEndPosition = thisContent.size();
  234. }
  235. void cmStateSnapshot::SetDefaultDefinitions()
  236. {
  237. /* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set.
  238. With CMake must separate between target and host platform. In most cases
  239. the tests for WIN32, UNIX and APPLE will be for the target system, so an
  240. additional set of variables for the host system is required ->
  241. CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE.
  242. WIN32, UNIX and APPLE are now set in the platform files in
  243. Modules/Platforms/.
  244. To keep cmake scripts (-P) and custom language and compiler modules
  245. working, these variables are still also set here in this place, but they
  246. will be reset in CMakeSystemSpecificInformation.cmake before the platform
  247. files are executed. */
  248. cm::string_view hostSystemName = cmSystemTools::GetSystemName();
  249. this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", hostSystemName);
  250. if (hostSystemName == "Windows") {
  251. this->SetDefinition("WIN32", "1");
  252. this->SetDefinition("CMAKE_HOST_WIN32", "1");
  253. this->SetDefinition("CMAKE_HOST_EXECUTABLE_SUFFIX", ".exe");
  254. } else {
  255. this->SetDefinition("UNIX", "1");
  256. this->SetDefinition("CMAKE_HOST_UNIX", "1");
  257. this->SetDefinition("CMAKE_HOST_EXECUTABLE_SUFFIX", "");
  258. }
  259. #if defined(__APPLE__)
  260. this->SetDefinition("APPLE", "1");
  261. this->SetDefinition("CMAKE_HOST_APPLE", "1");
  262. #endif
  263. #if defined(__sun__)
  264. this->SetDefinition("CMAKE_HOST_SOLARIS", "1");
  265. #endif
  266. #if defined(__OpenBSD__)
  267. this->SetDefinition("BSD", "OpenBSD");
  268. this->SetDefinition("CMAKE_HOST_BSD", "OpenBSD");
  269. #elif defined(__FreeBSD__)
  270. this->SetDefinition("BSD", "FreeBSD");
  271. this->SetDefinition("CMAKE_HOST_BSD", "FreeBSD");
  272. #elif defined(__NetBSD__)
  273. this->SetDefinition("BSD", "NetBSD");
  274. this->SetDefinition("CMAKE_HOST_BSD", "NetBSD");
  275. #elif defined(__DragonFly__)
  276. this->SetDefinition("BSD", "DragonFlyBSD");
  277. this->SetDefinition("CMAKE_HOST_BSD", "DragonFlyBSD");
  278. #endif
  279. #if defined(__linux__)
  280. this->SetDefinition("LINUX", "1");
  281. this->SetDefinition("CMAKE_HOST_LINUX", "1");
  282. #endif
  283. #if defined(_AIX)
  284. this->SetDefinition("AIX", "1");
  285. this->SetDefinition("CMAKE_HOST_AIX", "1");
  286. #endif
  287. this->SetDefinition("CMAKE_MAJOR_VERSION",
  288. std::to_string(cmVersion::GetMajorVersion()));
  289. this->SetDefinition("CMAKE_MINOR_VERSION",
  290. std::to_string(cmVersion::GetMinorVersion()));
  291. this->SetDefinition("CMAKE_PATCH_VERSION",
  292. std::to_string(cmVersion::GetPatchVersion()));
  293. this->SetDefinition("CMAKE_TWEAK_VERSION",
  294. std::to_string(cmVersion::GetTweakVersion()));
  295. this->SetDefinition("CMAKE_VERSION", cmVersion::GetCMakeVersion());
  296. this->SetDefinition("CMAKE_FILES_DIRECTORY", "/CMakeFiles");
  297. // Setup the default include file regular expression (match everything).
  298. this->Position->BuildSystemDirectory->Properties.SetProperty(
  299. "INCLUDE_REGULAR_EXPRESSION", "^.*$");
  300. }
  301. void cmStateSnapshot::SetDirectoryDefinitions()
  302. {
  303. this->SetDefinition("CMAKE_SOURCE_DIR", this->State->GetSourceDirectory());
  304. this->SetDefinition("CMAKE_CURRENT_SOURCE_DIR",
  305. this->State->GetSourceDirectory());
  306. this->SetDefinition("CMAKE_BINARY_DIR", this->State->GetBinaryDirectory());
  307. this->SetDefinition("CMAKE_CURRENT_BINARY_DIR",
  308. this->State->GetBinaryDirectory());
  309. }
  310. void cmStateSnapshot::InitializeFromParent()
  311. {
  312. cmStateDetail::PositionType parent = this->Position->DirectoryParent;
  313. assert(this->Position->Vars.IsValid());
  314. assert(parent->Vars.IsValid());
  315. *this->Position->Vars =
  316. cmDefinitions::MakeClosure(parent->Vars, parent->Root);
  317. InitializeContentFromParent(
  318. parent->BuildSystemDirectory->IncludeDirectories,
  319. this->Position->BuildSystemDirectory->IncludeDirectories,
  320. this->Position->IncludeDirectoryPosition);
  321. InitializeContentFromParent(
  322. parent->BuildSystemDirectory->CompileDefinitions,
  323. this->Position->BuildSystemDirectory->CompileDefinitions,
  324. this->Position->CompileDefinitionsPosition);
  325. InitializeContentFromParent(
  326. parent->BuildSystemDirectory->CompileOptions,
  327. this->Position->BuildSystemDirectory->CompileOptions,
  328. this->Position->CompileOptionsPosition);
  329. InitializeContentFromParent(
  330. parent->BuildSystemDirectory->LinkOptions,
  331. this->Position->BuildSystemDirectory->LinkOptions,
  332. this->Position->LinkOptionsPosition);
  333. InitializeContentFromParent(
  334. parent->BuildSystemDirectory->LinkDirectories,
  335. this->Position->BuildSystemDirectory->LinkDirectories,
  336. this->Position->LinkDirectoriesPosition);
  337. cmValue include_regex =
  338. parent->BuildSystemDirectory->Properties.GetPropertyValue(
  339. "INCLUDE_REGULAR_EXPRESSION");
  340. this->Position->BuildSystemDirectory->Properties.SetProperty(
  341. "INCLUDE_REGULAR_EXPRESSION", include_regex);
  342. }
  343. cmState* cmStateSnapshot::GetState() const
  344. {
  345. return this->State;
  346. }
  347. cmStateDirectory cmStateSnapshot::GetDirectory() const
  348. {
  349. return { this->Position->BuildSystemDirectory, *this };
  350. }
  351. void cmStateSnapshot::SetProjectName(std::string const& name)
  352. {
  353. this->Position->BuildSystemDirectory->ProjectName = name;
  354. }
  355. std::string cmStateSnapshot::GetProjectName() const
  356. {
  357. return this->Position->BuildSystemDirectory->ProjectName;
  358. }
  359. void cmStateSnapshot::InitializeFromParent_ForSubdirsCommand()
  360. {
  361. std::string currentSrcDir = *this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR");
  362. std::string currentBinDir = *this->GetDefinition("CMAKE_CURRENT_BINARY_DIR");
  363. this->InitializeFromParent();
  364. this->SetDefinition("CMAKE_SOURCE_DIR", this->State->GetSourceDirectory());
  365. this->SetDefinition("CMAKE_BINARY_DIR", this->State->GetBinaryDirectory());
  366. this->SetDefinition("CMAKE_CURRENT_SOURCE_DIR", currentSrcDir);
  367. this->SetDefinition("CMAKE_CURRENT_BINARY_DIR", currentBinDir);
  368. }
  369. bool cmStateSnapshot::StrictWeakOrder::operator()(
  370. cmStateSnapshot const& lhs, cmStateSnapshot const& rhs) const
  371. {
  372. return lhs.Position.StrictWeakOrdered(rhs.Position);
  373. }
  374. bool operator==(cmStateSnapshot const& lhs, cmStateSnapshot const& rhs)
  375. {
  376. return lhs.Position == rhs.Position;
  377. }
  378. bool operator!=(cmStateSnapshot const& lhs, cmStateSnapshot const& rhs)
  379. {
  380. return lhs.Position != rhs.Position;
  381. }