ENH: Teach set/get_property about CACHE properties

This adds the CACHE option to set_property and get_property commands.
This allows full control over cache entry information, so advanced users
can tweak their project cache as desired.  The set_property command
allows only pre-defined CACHE properties to be set since others would
not persist anyway.
This commit is contained in:
Brad King 2009-03-10 11:10:59 -04:00
parent ca9fb4826f
commit e5e91d6179
7 changed files with 167 additions and 3 deletions

View File

@ -71,6 +71,18 @@ cmCacheManager::CacheEntryType cmCacheManager::StringToType(const char* s)
return STRING; return STRING;
} }
bool cmCacheManager::IsType(const char* s)
{
for(int i=0; cmCacheManagerTypes[i]; ++i)
{
if(strcmp(s, cmCacheManagerTypes[i]) == 0)
{
return true;
}
}
return false;
}
bool cmCacheManager::LoadCache(cmMakefile* mf) bool cmCacheManager::LoadCache(cmMakefile* mf)
{ {
return this->LoadCache(mf->GetHomeOutputDirectory()); return this->LoadCache(mf->GetHomeOutputDirectory());

View File

@ -105,6 +105,7 @@ public:
*/ */
static CacheEntryType StringToType(const char*); static CacheEntryType StringToType(const char*);
static const char* TypeToString(CacheEntryType); static const char* TypeToString(CacheEntryType);
static bool IsType(const char*);
///! Load a cache for given makefile. Loads from ouput home. ///! Load a cache for given makefile. Loads from ouput home.
bool LoadCache(cmMakefile*); bool LoadCache(cmMakefile*);

View File

@ -65,12 +65,16 @@ bool cmGetPropertyCommand
{ {
scope = cmProperty::VARIABLE; scope = cmProperty::VARIABLE;
} }
else if(args[1] == "CACHE")
{
scope = cmProperty::CACHE;
}
else else
{ {
cmOStringStream e; cmOStringStream e;
e << "given invalid scope " << args[1] << ". " e << "given invalid scope " << args[1] << ". "
<< "Valid scopes are " << "Valid scopes are "
<< "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE."; << "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE, CACHE.";
this->SetError(e.str().c_str()); this->SetError(e.str().c_str());
return false; return false;
} }
@ -187,6 +191,7 @@ bool cmGetPropertyCommand
case cmProperty::SOURCE_FILE: return this->HandleSourceMode(); case cmProperty::SOURCE_FILE: return this->HandleSourceMode();
case cmProperty::TEST: return this->HandleTestMode(); case cmProperty::TEST: return this->HandleTestMode();
case cmProperty::VARIABLE: return this->HandleVariableMode(); case cmProperty::VARIABLE: return this->HandleVariableMode();
case cmProperty::CACHE: return this->HandleCacheMode();
case cmProperty::CACHED_VARIABLE: case cmProperty::CACHED_VARIABLE:
break; // should never happen break; // should never happen
@ -359,3 +364,23 @@ bool cmGetPropertyCommand::HandleVariableMode()
return this->StoreResult return this->StoreResult
(this->Makefile->GetDefinition(this->PropertyName.c_str())); (this->Makefile->GetDefinition(this->PropertyName.c_str()));
} }
//----------------------------------------------------------------------------
bool cmGetPropertyCommand::HandleCacheMode()
{
if(this->Name.empty())
{
this->SetError("not given name for CACHE scope.");
return false;
}
const char* value = 0;
cmCacheManager::CacheIterator it =
this->Makefile->GetCacheManager()->GetCacheIterator(this->Name.c_str());
if(!it.IsAtEnd())
{
value = it.GetProperty(this->PropertyName.c_str());
}
this->StoreResult(value);
return true;
}

View File

@ -66,6 +66,7 @@ public:
" TARGET <target> |\n" " TARGET <target> |\n"
" SOURCE <source> |\n" " SOURCE <source> |\n"
" TEST <test> |\n" " TEST <test> |\n"
" CACHE <entry> |\n"
" VARIABLE>\n" " VARIABLE>\n"
" PROPERTY <name>\n" " PROPERTY <name>\n"
" [SET | DEFINED | BRIEF_DOCS | FULL_DOCS])\n" " [SET | DEFINED | BRIEF_DOCS | FULL_DOCS])\n"
@ -81,6 +82,7 @@ public:
"TARGET scope must name one existing target.\n" "TARGET scope must name one existing target.\n"
"SOURCE scope must name one source file.\n" "SOURCE scope must name one source file.\n"
"TEST scope must name one existing test.\n" "TEST scope must name one existing test.\n"
"CACHE scope must name one cache entry.\n"
"VARIABLE scope is unique and does not accept a name.\n" "VARIABLE scope is unique and does not accept a name.\n"
"The required PROPERTY option is immediately followed by the name " "The required PROPERTY option is immediately followed by the name "
"of the property to get. " "of the property to get. "
@ -114,6 +116,7 @@ private:
bool HandleSourceMode(); bool HandleSourceMode();
bool HandleTestMode(); bool HandleTestMode();
bool HandleVariableMode(); bool HandleVariableMode();
bool HandleCacheMode();
}; };
#endif #endif

View File

@ -19,6 +19,8 @@
#include "cmSetTestsPropertiesCommand.h" #include "cmSetTestsPropertiesCommand.h"
#include "cmSetSourceFilesPropertiesCommand.h" #include "cmSetSourceFilesPropertiesCommand.h"
#include "cmCacheManager.h"
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmSetPropertyCommand::cmSetPropertyCommand() cmSetPropertyCommand::cmSetPropertyCommand()
{ {
@ -59,11 +61,15 @@ bool cmSetPropertyCommand
{ {
scope = cmProperty::TEST; scope = cmProperty::TEST;
} }
else if(*arg == "CACHE")
{
scope = cmProperty::CACHE;
}
else else
{ {
cmOStringStream e; cmOStringStream e;
e << "given invalid scope " << *arg << ". " e << "given invalid scope " << *arg << ". "
<< "Valid scopes are GLOBAL, DIRECTORY, TARGET, SOURCE, TEST."; << "Valid scopes are GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, CACHE.";
this->SetError(e.str().c_str()); this->SetError(e.str().c_str());
return false; return false;
} }
@ -123,6 +129,7 @@ bool cmSetPropertyCommand
case cmProperty::TARGET: return this->HandleTargetMode(); case cmProperty::TARGET: return this->HandleTargetMode();
case cmProperty::SOURCE_FILE: return this->HandleSourceMode(); case cmProperty::SOURCE_FILE: return this->HandleSourceMode();
case cmProperty::TEST: return this->HandleTestMode(); case cmProperty::TEST: return this->HandleTestMode();
case cmProperty::CACHE: return this->HandleCacheMode();
case cmProperty::VARIABLE: case cmProperty::VARIABLE:
case cmProperty::CACHED_VARIABLE: case cmProperty::CACHED_VARIABLE:
@ -384,3 +391,89 @@ bool cmSetPropertyCommand::HandleTest(cmTest* test)
return true; return true;
} }
//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleCacheMode()
{
if(this->PropertyName == "ADVANCED")
{
if(!this->Remove &&
!cmSystemTools::IsOn(this->PropertyValue.c_str()) &&
!cmSystemTools::IsOff(this->PropertyValue.c_str()))
{
cmOStringStream e;
e << "given non-boolean value \"" << this->PropertyValue
<< "\" for CACHE property \"ADVANCED\". ";
this->SetError(e.str().c_str());
return false;
}
}
else if(this->PropertyName == "TYPE")
{
if(!cmCacheManager::IsType(this->PropertyValue.c_str()))
{
cmOStringStream e;
e << "given invalid CACHE entry TYPE \"" << this->PropertyValue << "\"";
this->SetError(e.str().c_str());
return false;
}
}
else if(this->PropertyName != "HELPSTRING" &&
this->PropertyName != "VALUE")
{
cmOStringStream e;
e << "given invalid CACHE property " << this->PropertyName << ". "
<< "Settable CACHE properties are: "
<< "ADVANCED, HELPSTRING, TYPE, and VALUE.";
this->SetError(e.str().c_str());
return false;
}
for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
ni != this->Names.end(); ++ni)
{
// Get the source file.
cmMakefile* mf = this->GetMakefile();
cmake* cm = mf->GetCMakeInstance();
cmCacheManager::CacheIterator it =
cm->GetCacheManager()->GetCacheIterator(ni->c_str());
if(!it.IsAtEnd())
{
if(!this->HandleCacheEntry(it))
{
return false;
}
}
else
{
cmOStringStream e;
e << "could not find CACHE variable " << *ni
<< ". Perhaps it has not yet been created.";
this->SetError(e.str().c_str());
return false;
}
}
return true;
}
//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleCacheEntry(cmCacheManager::CacheIterator& it)
{
// Set or append the property.
const char* name = this->PropertyName.c_str();
const char* value = this->PropertyValue.c_str();
if (this->Remove)
{
value = 0;
}
if(this->AppendMode)
{
it.AppendProperty(name, value);
}
else
{
it.SetProperty(name, value);
}
return true;
}

View File

@ -59,7 +59,8 @@ public:
" DIRECTORY [dir] |\n" " DIRECTORY [dir] |\n"
" TARGET [target1 [target2 ...]] |\n" " TARGET [target1 [target2 ...]] |\n"
" SOURCE [src1 [src2 ...]] |\n" " SOURCE [src1 [src2 ...]] |\n"
" TEST [test1 [test2 ...]]>\n" " TEST [test1 [test2 ...]] |\n"
" CACHE [entry1 [entry2 ...]]>\n"
" [APPEND]\n" " [APPEND]\n"
" PROPERTY <name> [value1 [value2 ...]])\n" " PROPERTY <name> [value1 [value2 ...]])\n"
"Set one property on zero or more objects of a scope. " "Set one property on zero or more objects of a scope. "
@ -72,6 +73,7 @@ public:
"TARGET scope may name zero or more existing targets.\n" "TARGET scope may name zero or more existing targets.\n"
"SOURCE scope may name zero or more source files.\n" "SOURCE scope may name zero or more source files.\n"
"TEST scope may name zero or more existing tests.\n" "TEST scope may name zero or more existing tests.\n"
"CACHE scope must name zero or more cache existing entries.\n"
"The required PROPERTY option is immediately followed by the name " "The required PROPERTY option is immediately followed by the name "
"of the property to set. Remaining arguments are used to " "of the property to set. Remaining arguments are used to "
"compose the property value in the form of a semicolon-separated " "compose the property value in the form of a semicolon-separated "
@ -104,6 +106,8 @@ private:
bool HandleSource(cmSourceFile* sf); bool HandleSource(cmSourceFile* sf);
bool HandleTestMode(); bool HandleTestMode();
bool HandleTest(cmTest* test); bool HandleTest(cmTest* test);
bool HandleCacheMode();
bool HandleCacheEntry(cmCacheManager::CacheIterator&);
}; };

View File

@ -97,3 +97,29 @@ if(NOT RESULT4)
" RESULT4=${RESULT4}" " RESULT4=${RESULT4}"
" Properties_SOURCES=[${Properties_SOURCES}]") " Properties_SOURCES=[${Properties_SOURCES}]")
endif(NOT RESULT4) endif(NOT RESULT4)
# test CACHE properties
macro(check_cache_props)
foreach(prop VALUE TYPE HELPSTRING ADVANCED)
get_property(result CACHE SOME_ENTRY PROPERTY ${prop})
if(NOT "x${result}" STREQUAL "x${expect_${prop}}")
message(SEND_ERROR "CACHE property ${prop} is [${result}], not [${expect_${prop}}]")
endif()
endforeach(prop)
endmacro(check_cache_props)
set(expect_VALUE "ON")
set(expect_TYPE "BOOL")
set(expect_HELPSTRING "sample cache entry")
set(expect_ADVANCED 0)
set(SOME_ENTRY "${expect_VALUE}" CACHE ${expect_TYPE} "${expect_HELPSTRING}" FORCE)
mark_as_advanced(CLEAR SOME_ENTRY)
check_cache_props()
set(expect_VALUE "Some string")
set(expect_TYPE "STRING")
set(expect_HELPSTRING "sample cache entry help")
set(expect_ADVANCED 1)
set_property(CACHE SOME_ENTRY PROPERTY TYPE "${expect_TYPE}")
set_property(CACHE SOME_ENTRY PROPERTY HELPSTRING "${expect_HELPSTRING}")
set_property(CACHE SOME_ENTRY PROPERTY VALUE "${expect_VALUE}")
set_property(CACHE SOME_ENTRY PROPERTY ADVANCED "${expect_ADVANCED}")
check_cache_props()