1
0

cmLoadCacheCommand.cxx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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 "cmLoadCacheCommand.h"
  4. #include <cmsys/FStream.hxx>
  5. #include "cmMakefile.h"
  6. #include "cmState.h"
  7. #include "cmSystemTools.h"
  8. #include "cmake.h"
  9. class cmExecutionStatus;
  10. // cmLoadCacheCommand
  11. bool cmLoadCacheCommand::InitialPass(std::vector<std::string> const& args,
  12. cmExecutionStatus&)
  13. {
  14. if (args.empty()) {
  15. this->SetError("called with wrong number of arguments.");
  16. }
  17. if (args.size() >= 2 && args[1] == "READ_WITH_PREFIX") {
  18. return this->ReadWithPrefix(args);
  19. }
  20. // Cache entries to be excluded from the import list.
  21. // If this set is empty, all cache entries are brought in
  22. // and they can not be overridden.
  23. bool excludeFiles = false;
  24. unsigned int i;
  25. std::set<std::string> excludes;
  26. for (i = 0; i < args.size(); i++) {
  27. if (excludeFiles) {
  28. excludes.insert(args[i]);
  29. }
  30. if (args[i] == "EXCLUDE") {
  31. excludeFiles = true;
  32. }
  33. if (excludeFiles && (args[i] == "INCLUDE_INTERNALS")) {
  34. break;
  35. }
  36. }
  37. // Internal cache entries to be imported.
  38. // If this set is empty, no internal cache entries are
  39. // brought in.
  40. bool includeFiles = false;
  41. std::set<std::string> includes;
  42. for (i = 0; i < args.size(); i++) {
  43. if (includeFiles) {
  44. includes.insert(args[i]);
  45. }
  46. if (args[i] == "INCLUDE_INTERNALS") {
  47. includeFiles = true;
  48. }
  49. if (includeFiles && (args[i] == "EXCLUDE")) {
  50. break;
  51. }
  52. }
  53. // Loop over each build directory listed in the arguments. Each
  54. // directory has a cache file.
  55. for (i = 0; i < args.size(); i++) {
  56. if ((args[i] == "EXCLUDE") || (args[i] == "INCLUDE_INTERNALS")) {
  57. break;
  58. }
  59. this->Makefile->GetCMakeInstance()->LoadCache(args[i], false, excludes,
  60. includes);
  61. }
  62. return true;
  63. }
  64. bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args)
  65. {
  66. // Make sure we have a prefix.
  67. if (args.size() < 3) {
  68. this->SetError("READ_WITH_PREFIX form must specify a prefix.");
  69. return false;
  70. }
  71. // Make sure the cache file exists.
  72. std::string cacheFile = args[0] + "/CMakeCache.txt";
  73. if (!cmSystemTools::FileExists(cacheFile.c_str())) {
  74. std::string e = "Cannot load cache file from " + cacheFile;
  75. this->SetError(e);
  76. return false;
  77. }
  78. // Prepare the table of variables to read.
  79. this->Prefix = args[2];
  80. this->VariablesToRead.insert(args.begin() + 3, args.end());
  81. // Read the cache file.
  82. cmsys::ifstream fin(cacheFile.c_str());
  83. // This is a big hack read loop to overcome a buggy ifstream
  84. // implementation on HP-UX. This should work on all platforms even
  85. // for small buffer sizes.
  86. const int bufferSize = 4096;
  87. char buffer[bufferSize];
  88. std::string line;
  89. while (fin) {
  90. // Read a block of the file.
  91. fin.read(buffer, bufferSize);
  92. if (fin.gcount()) {
  93. // Parse for newlines directly.
  94. const char* i = buffer;
  95. const char* end = buffer + fin.gcount();
  96. while (i != end) {
  97. const char* begin = i;
  98. while (i != end && *i != '\n') {
  99. ++i;
  100. }
  101. if (i == begin || *(i - 1) != '\r') {
  102. // Include this portion of the line.
  103. line += std::string(begin, i - begin);
  104. } else {
  105. // Include this portion of the line.
  106. // Don't include the \r in a \r\n pair.
  107. line += std::string(begin, i - 1 - begin);
  108. }
  109. if (i != end) {
  110. // Completed a line.
  111. this->CheckLine(line.c_str());
  112. line = "";
  113. // Skip the newline character.
  114. ++i;
  115. }
  116. }
  117. }
  118. }
  119. if (!line.empty()) {
  120. // Partial last line.
  121. this->CheckLine(line.c_str());
  122. }
  123. return true;
  124. }
  125. void cmLoadCacheCommand::CheckLine(const char* line)
  126. {
  127. // Check one line of the cache file.
  128. std::string var;
  129. std::string value;
  130. cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
  131. if (cmake::ParseCacheEntry(line, var, value, type)) {
  132. // Found a real entry. See if this one was requested.
  133. if (this->VariablesToRead.find(var) != this->VariablesToRead.end()) {
  134. // This was requested. Set this variable locally with the given
  135. // prefix.
  136. var = this->Prefix + var;
  137. if (!value.empty()) {
  138. this->Makefile->AddDefinition(var, value.c_str());
  139. } else {
  140. this->Makefile->RemoveDefinition(var);
  141. }
  142. }
  143. }
  144. }