cmStateSnapshot.cxx 15 KB

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