cmake/Source/cmLoadCacheCommand.cxx

163 lines
4.4 KiB
C++
Raw Normal View History

2016-10-30 18:24:19 +01:00
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLoadCacheCommand.h"
2017-07-20 19:35:53 +02:00
#include "cmsys/FStream.hxx"
2017-04-14 19:02:05 +02:00
#include "cmMakefile.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmake.h"
class cmExecutionStatus;
// cmLoadCacheCommand
2016-07-09 11:21:54 +02:00
bool cmLoadCacheCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus&)
{
2016-10-30 18:24:19 +01:00
if (args.empty()) {
this->SetError("called with wrong number of arguments.");
2016-07-09 11:21:54 +02:00
}
2016-07-09 11:21:54 +02:00
if (args.size() >= 2 && args[1] == "READ_WITH_PREFIX") {
return this->ReadWithPrefix(args);
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
// 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.
2016-07-09 11:21:54 +02:00
bool excludeFiles = false;
2015-04-27 22:25:09 +02:00
std::set<std::string> excludes;
2018-01-26 17:06:56 +01:00
for (std::string const& arg : args) {
2016-07-09 11:21:54 +02:00
if (excludeFiles) {
2018-01-26 17:06:56 +01:00
excludes.insert(arg);
2016-07-09 11:21:54 +02:00
}
2018-01-26 17:06:56 +01:00
if (arg == "EXCLUDE") {
2016-07-09 11:21:54 +02:00
excludeFiles = true;
}
2018-01-26 17:06:56 +01:00
if (excludeFiles && (arg == "INCLUDE_INTERNALS")) {
break;
}
2016-07-09 11:21:54 +02:00
}
// Internal cache entries to be imported.
// If this set is empty, no internal cache entries are
// brought in.
2016-07-09 11:21:54 +02:00
bool includeFiles = false;
2015-04-27 22:25:09 +02:00
std::set<std::string> includes;
2018-01-26 17:06:56 +01:00
for (std::string const& arg : args) {
2016-07-09 11:21:54 +02:00
if (includeFiles) {
2018-01-26 17:06:56 +01:00
includes.insert(arg);
2016-07-09 11:21:54 +02:00
}
2018-01-26 17:06:56 +01:00
if (arg == "INCLUDE_INTERNALS") {
2016-07-09 11:21:54 +02:00
includeFiles = true;
}
2018-01-26 17:06:56 +01:00
if (includeFiles && (arg == "EXCLUDE")) {
break;
}
2016-07-09 11:21:54 +02:00
}
// Loop over each build directory listed in the arguments. Each
// directory has a cache file.
2018-01-26 17:06:56 +01:00
for (std::string const& arg : args) {
if ((arg == "EXCLUDE") || (arg == "INCLUDE_INTERNALS")) {
break;
}
2018-01-26 17:06:56 +01:00
this->Makefile->GetCMakeInstance()->LoadCache(arg, false, excludes,
2016-07-09 11:21:54 +02:00
includes);
}
return true;
}
bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args)
{
// Make sure we have a prefix.
2016-07-09 11:21:54 +02:00
if (args.size() < 3) {
this->SetError("READ_WITH_PREFIX form must specify a prefix.");
return false;
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
// Make sure the cache file exists.
2016-07-09 11:21:54 +02:00
std::string cacheFile = args[0] + "/CMakeCache.txt";
2018-04-23 21:13:27 +02:00
if (!cmSystemTools::FileExists(cacheFile)) {
std::string e = "Cannot load cache file from " + cacheFile;
2015-04-27 22:25:09 +02:00
this->SetError(e);
return false;
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
// Prepare the table of variables to read.
this->Prefix = args[2];
2015-04-27 22:25:09 +02:00
this->VariablesToRead.insert(args.begin() + 3, args.end());
2013-03-16 19:13:01 +02:00
// Read the cache file.
2014-08-03 19:52:23 +02:00
cmsys::ifstream fin(cacheFile.c_str());
2013-03-16 19:13:01 +02:00
// 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;
2013-03-16 19:13:01 +02:00
char buffer[bufferSize];
std::string line;
2016-07-09 11:21:54 +02:00
while (fin) {
// Read a block of the file.
fin.read(buffer, bufferSize);
2016-07-09 11:21:54 +02:00
if (fin.gcount()) {
// Parse for newlines directly.
const char* i = buffer;
2016-07-09 11:21:54 +02:00
const char* end = buffer + fin.gcount();
while (i != end) {
const char* begin = i;
2016-07-09 11:21:54 +02:00
while (i != end && *i != '\n') {
++i;
}
if (i == begin || *(i - 1) != '\r') {
// Include this portion of the line.
2016-07-09 11:21:54 +02:00
line += std::string(begin, i - begin);
} else {
// Include this portion of the line.
// Don't include the \r in a \r\n pair.
2016-07-09 11:21:54 +02:00
line += std::string(begin, i - 1 - begin);
}
if (i != end) {
// Completed a line.
this->CheckLine(line.c_str());
2018-01-26 17:06:56 +01:00
line.clear();
2013-03-16 19:13:01 +02:00
// Skip the newline character.
++i;
}
}
}
2016-07-09 11:21:54 +02:00
}
if (!line.empty()) {
// Partial last line.
this->CheckLine(line.c_str());
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
return true;
}
void cmLoadCacheCommand::CheckLine(const char* line)
{
// Check one line of the cache file.
std::string var;
std::string value;
2017-04-14 19:02:05 +02:00
cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
2016-07-09 11:21:54 +02:00
if (cmake::ParseCacheEntry(line, var, value, type)) {
// Found a real entry. See if this one was requested.
2016-07-09 11:21:54 +02:00
if (this->VariablesToRead.find(var) != this->VariablesToRead.end()) {
// This was requested. Set this variable locally with the given
// prefix.
var = this->Prefix + var;
2016-07-09 11:21:54 +02:00
if (!value.empty()) {
2015-04-27 22:25:09 +02:00
this->Makefile->AddDefinition(var, value.c_str());
2016-07-09 11:21:54 +02:00
} else {
2015-04-27 22:25:09 +02:00
this->Makefile->RemoveDefinition(var);
}
}
2016-07-09 11:21:54 +02:00
}
}