You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

234 lines
6.1 KiB

  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmLoadCacheCommand.h"
  14. #include <cmsys/RegularExpression.hxx>
  15. // cmLoadCacheCommand
  16. bool cmLoadCacheCommand::InitialPass(std::vector<std::string> const& args)
  17. {
  18. if (args.size()< 1)
  19. {
  20. this->SetError("called with wrong number of arguments.");
  21. }
  22. if(args.size() >= 2 && args[1] == "READ_WITH_PREFIX")
  23. {
  24. return this->ReadWithPrefix(args);
  25. }
  26. // Cache entries to be excluded from the import list.
  27. // If this set is empty, all cache entries are brought in
  28. // and they can not be overridden.
  29. bool excludeFiles=false;
  30. unsigned int i;
  31. std::set<cmStdString> excludes;
  32. for(i=0; i<args.size(); i++)
  33. {
  34. if (excludeFiles)
  35. {
  36. excludes.insert(args[i]);
  37. }
  38. if (args[i] == "EXCLUDE")
  39. {
  40. excludeFiles=true;
  41. }
  42. if (excludeFiles && (args[i] == "INCLUDE_INTERNALS"))
  43. {
  44. break;
  45. }
  46. }
  47. // Internal cache entries to be imported.
  48. // If this set is empty, no internal cache entries are
  49. // brought in.
  50. bool includeFiles=false;
  51. std::set<cmStdString> includes;
  52. for(i=0; i<args.size(); i++)
  53. {
  54. if (includeFiles)
  55. {
  56. includes.insert(args[i]);
  57. }
  58. if (args[i] == "INCLUDE_INTERNALS")
  59. {
  60. includeFiles=true;
  61. }
  62. if (includeFiles && (args[i] == "EXCLUDE"))
  63. {
  64. break;
  65. }
  66. }
  67. // Loop over each build directory listed in the arguments. Each
  68. // directory has a cache file.
  69. for(i=0; i<args.size(); i++)
  70. {
  71. if ((args[i] == "EXCLUDE") || (args[i] == "INCLUDE_INTERNALS"))
  72. {
  73. break;
  74. }
  75. this->Makefile->GetCacheManager()->LoadCache(args[i].c_str(), false,
  76. excludes, includes);
  77. }
  78. return true;
  79. }
  80. //----------------------------------------------------------------------------
  81. bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args)
  82. {
  83. // Make sure we have a prefix.
  84. if(args.size() < 3)
  85. {
  86. this->SetError("READ_WITH_PREFIX form must specify a prefix.");
  87. return false;
  88. }
  89. // Make sure the cache file exists.
  90. std::string cacheFile = args[0]+"/CMakeCache.txt";
  91. if(!cmSystemTools::FileExists(cacheFile.c_str()))
  92. {
  93. std::string e = "Cannot load cache file from " + cacheFile;
  94. this->SetError(e.c_str());
  95. return false;
  96. }
  97. // Prepare the table of variables to read.
  98. this->Prefix = args[2];
  99. for(unsigned int i=3; i < args.size(); ++i)
  100. {
  101. this->VariablesToRead.insert(args[i]);
  102. }
  103. // Read the cache file.
  104. std::ifstream fin(cacheFile.c_str());
  105. // This is a big hack read loop to overcome a buggy ifstream
  106. // implementation on HP-UX. This should work on all platforms even
  107. // for small buffer sizes.
  108. const int bufferSize = 4096;
  109. char buffer[bufferSize];
  110. std::string line;
  111. while(fin)
  112. {
  113. // Read a block of the file.
  114. fin.read(buffer, bufferSize);
  115. if(fin.gcount())
  116. {
  117. // Parse for newlines directly.
  118. const char* i = buffer;
  119. const char* end = buffer+fin.gcount();
  120. while(i != end)
  121. {
  122. const char* begin = i;
  123. while(i != end && *i != '\n') { ++i; }
  124. if(i == begin || *(i-1) != '\r')
  125. {
  126. // Include this portion of the line.
  127. line += std::string(begin, i-begin);
  128. }
  129. else
  130. {
  131. // Include this portion of the line.
  132. // Don't include the \r in a \r\n pair.
  133. line += std::string(begin, i-1-begin);
  134. }
  135. if(i != end)
  136. {
  137. // Completed a line.
  138. this->CheckLine(line.c_str());
  139. line = "";
  140. // Skip the newline character.
  141. ++i;
  142. }
  143. }
  144. }
  145. }
  146. if(line.length())
  147. {
  148. // Partial last line.
  149. this->CheckLine(line.c_str());
  150. }
  151. return true;
  152. }
  153. //----------------------------------------------------------------------------
  154. void cmLoadCacheCommand::CheckLine(const char* line)
  155. {
  156. // Check one line of the cache file.
  157. std::string var;
  158. std::string value;
  159. if(this->ParseEntry(line, var, value))
  160. {
  161. // Found a real entry. See if this one was requested.
  162. if(this->VariablesToRead.find(var) != this->VariablesToRead.end())
  163. {
  164. // This was requested. Set this variable locally with the given
  165. // prefix.
  166. var = this->Prefix + var;
  167. if(value.length())
  168. {
  169. this->Makefile->AddDefinition(var.c_str(), value.c_str());
  170. }
  171. else
  172. {
  173. this->Makefile->RemoveDefinition(var.c_str());
  174. }
  175. }
  176. }
  177. }
  178. //----------------------------------------------------------------------------
  179. bool cmLoadCacheCommand::ParseEntry(const char* entry, std::string& var,
  180. std::string& value)
  181. {
  182. // input line is: key:type=value
  183. cmsys::RegularExpression reg("^([^:]*):([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*$");
  184. // input line is: "key":type=value
  185. cmsys::RegularExpression
  186. regQuoted("^\"([^\"]*)\":([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*$");
  187. bool flag = false;
  188. if(regQuoted.find(entry))
  189. {
  190. var = regQuoted.match(1);
  191. value = regQuoted.match(3);
  192. flag = true;
  193. }
  194. else if (reg.find(entry))
  195. {
  196. var = reg.match(1);
  197. value = reg.match(3);
  198. flag = true;
  199. }
  200. // if value is enclosed in single quotes ('foo') then remove them
  201. // it is used to enclose trailing space or tab
  202. if (flag &&
  203. value.size() >= 2 &&
  204. value[0] == '\'' &&
  205. value[value.size() - 1] == '\'')
  206. {
  207. value = value.substr(1, value.size() - 2);
  208. }
  209. return flag;
  210. }