cmLoadCacheCommand.cxx 6.1 KB

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