cmLoadCacheCommand.cxx 4.4 KB

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