cmLoadCacheCommand.cxx 6.0 KB

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