diff options
Diffstat (limited to 'Source/cmLoadCacheCommand.cxx')
-rw-r--r-- | Source/cmLoadCacheCommand.cxx | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/Source/cmLoadCacheCommand.cxx b/Source/cmLoadCacheCommand.cxx new file mode 100644 index 0000000..ea84877 --- /dev/null +++ b/Source/cmLoadCacheCommand.cxx @@ -0,0 +1,163 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmLoadCacheCommand.h" + +#include <cmsys/FStream.hxx> + +#include "cmMakefile.h" +#include "cmStateTypes.h" +#include "cmSystemTools.h" +#include "cmake.h" + +class cmExecutionStatus; + +// cmLoadCacheCommand +bool cmLoadCacheCommand::InitialPass(std::vector<std::string> const& args, + cmExecutionStatus&) +{ + if (args.empty()) { + this->SetError("called with wrong number of arguments."); + } + + if (args.size() >= 2 && args[1] == "READ_WITH_PREFIX") { + return this->ReadWithPrefix(args); + } + + // Cache entries to be excluded from the import list. + // If this set is empty, all cache entries are brought in + // and they can not be overridden. + bool excludeFiles = false; + unsigned int i; + std::set<std::string> excludes; + + for (i = 0; i < args.size(); i++) { + if (excludeFiles) { + excludes.insert(args[i]); + } + if (args[i] == "EXCLUDE") { + excludeFiles = true; + } + if (excludeFiles && (args[i] == "INCLUDE_INTERNALS")) { + break; + } + } + + // Internal cache entries to be imported. + // If this set is empty, no internal cache entries are + // brought in. + bool includeFiles = false; + std::set<std::string> includes; + + for (i = 0; i < args.size(); i++) { + if (includeFiles) { + includes.insert(args[i]); + } + if (args[i] == "INCLUDE_INTERNALS") { + includeFiles = true; + } + if (includeFiles && (args[i] == "EXCLUDE")) { + break; + } + } + + // Loop over each build directory listed in the arguments. Each + // directory has a cache file. + for (i = 0; i < args.size(); i++) { + if ((args[i] == "EXCLUDE") || (args[i] == "INCLUDE_INTERNALS")) { + break; + } + this->Makefile->GetCMakeInstance()->LoadCache(args[i], false, excludes, + includes); + } + + return true; +} + +bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args) +{ + // Make sure we have a prefix. + if (args.size() < 3) { + this->SetError("READ_WITH_PREFIX form must specify a prefix."); + return false; + } + + // Make sure the cache file exists. + std::string cacheFile = args[0] + "/CMakeCache.txt"; + if (!cmSystemTools::FileExists(cacheFile.c_str())) { + std::string e = "Cannot load cache file from " + cacheFile; + this->SetError(e); + return false; + } + + // Prepare the table of variables to read. + this->Prefix = args[2]; + this->VariablesToRead.insert(args.begin() + 3, args.end()); + + // Read the cache file. + cmsys::ifstream fin(cacheFile.c_str()); + + // This is a big hack read loop to overcome a buggy ifstream + // implementation on HP-UX. This should work on all platforms even + // for small buffer sizes. + const int bufferSize = 4096; + char buffer[bufferSize]; + std::string line; + while (fin) { + // Read a block of the file. + fin.read(buffer, bufferSize); + if (fin.gcount()) { + // Parse for newlines directly. + const char* i = buffer; + const char* end = buffer + fin.gcount(); + while (i != end) { + const char* begin = i; + while (i != end && *i != '\n') { + ++i; + } + if (i == begin || *(i - 1) != '\r') { + // Include this portion of the line. + line += std::string(begin, i - begin); + } else { + // Include this portion of the line. + // Don't include the \r in a \r\n pair. + line += std::string(begin, i - 1 - begin); + } + if (i != end) { + // Completed a line. + this->CheckLine(line.c_str()); + line = ""; + + // Skip the newline character. + ++i; + } + } + } + } + if (!line.empty()) { + // Partial last line. + this->CheckLine(line.c_str()); + } + + return true; +} + +void cmLoadCacheCommand::CheckLine(const char* line) +{ + // Check one line of the cache file. + std::string var; + std::string value; + cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED; + if (cmake::ParseCacheEntry(line, var, value, type)) { + // Found a real entry. See if this one was requested. + if (this->VariablesToRead.find(var) != this->VariablesToRead.end()) { + // This was requested. Set this variable locally with the given + // prefix. + var = this->Prefix + var; + if (!value.empty()) { + this->Makefile->AddDefinition(var, value.c_str()); + } else { + this->Makefile->RemoveDefinition(var); + } + } + } +} |