ENH: Added READ_WITH_PREFIX option to LOAD_CACHE command. This allows reading of cache values from another cache without actually creating local copies of the cache entires. The values are stored as prefixed local makefile variables.

This commit is contained in:
Brad King 2002-11-20 18:00:02 -05:00
parent c2addf1630
commit 7ef6173664
2 changed files with 157 additions and 2 deletions

View File

@ -17,7 +17,7 @@
#include "cmLoadCacheCommand.h"
// cmLoadcacheCommand
// cmLoadCacheCommand
bool cmLoadCacheCommand::InitialPass(std::vector<std::string> const& argsIn)
{
if (argsIn.size()< 1)
@ -27,6 +27,11 @@ bool cmLoadCacheCommand::InitialPass(std::vector<std::string> const& argsIn)
std::vector<std::string> args;
cmSystemTools::ExpandListArguments(argsIn, args);
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.
@ -88,4 +93,142 @@ bool cmLoadCacheCommand::InitialPass(std::vector<std::string> const& argsIn)
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.c_str());
return false;
}
// Prepare the table of variables to read.
this->Prefix = args[2];
for(unsigned int i=3; i < args.size(); ++i)
{
this->VariablesToRead.insert(args[i]);
}
// Read the cache file.
std::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.length())
{
// 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;
if(this->ParseEntry(line, var, value))
{
// 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.length())
{
m_Makefile->AddDefinition(var.c_str(), value.c_str());
}
else
{
m_Makefile->RemoveDefinition(var.c_str());
}
}
}
}
//----------------------------------------------------------------------------
bool cmLoadCacheCommand::ParseEntry(const char* entry, std::string& var,
std::string& value)
{
// input line is: key:type=value
cmRegularExpression reg("^([^:]*):([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*$");
// input line is: "key":type=value
cmRegularExpression regQuoted("^\"([^\"]*)\":([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*$");
bool flag = false;
if(regQuoted.find(entry))
{
var = regQuoted.match(1);
value = regQuoted.match(3);
flag = true;
}
else if (reg.find(entry))
{
var = reg.match(1);
value = reg.match(3);
flag = true;
}
// if value is enclosed in single quotes ('foo') then remove them
// it is used to enclose trailing space or tab
if (flag &&
value.size() >= 2 &&
value[0] == '\'' &&
value[value.size() - 1] == '\'')
{
value = value.substr(1, value.size() - 2);
}
return flag;
}

View File

@ -65,14 +65,26 @@ public:
{
return
"LOAD_CACHE(pathToCacheFile [EXCLUDE entry1...] [INCLUDE_INTERNALS entry1...])\n"
"LOAD_CACHE(pathToCacheFile READ_WITH_PREFIX prefix entry1...)\n"
"Load in the values from another cache. This is useful for a project "
"that depends on another project built in a different tree."
"EXCLUDE option can be used to provide a list of entries to be excluded."
"INCLUDE_INTERNALS can be used to provide a list of internal entries"
"to be included. Normally, no internal entries are brougt in.";
"to be included. Normally, no internal entries are brougt in.\n"
"The READ_WITH_PREFIX form will read the cache and store the requested "
"entries in variables with their name prefixed with the given prefix. "
"This form only reads the values, and does not create local cache entries.";
}
cmTypeMacro(cmLoadCacheCommand, cmCommand);
protected:
std::set<cmStdString> VariablesToRead;
std::string Prefix;
bool ReadWithPrefix(std::vector<std::string> const& args);
void CheckLine(const char* line);
bool ParseEntry(const char* entry, std::string& var, std::string& value);
};