summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2008-01-17 22:19:13 (GMT)
committerBrad King <brad.king@kitware.com>2008-01-17 22:19:13 (GMT)
commit669db35aa445cc67eef1ff53aced9602e253249e (patch)
tree4d2d3eec6f0f04c78f9e5e5a2c3b93a2935824bb /Source
parent83901b30da3e42c43b06d1579a86b14be2acf50e (diff)
downloadCMake-669db35aa445cc67eef1ff53aced9602e253249e.zip
CMake-669db35aa445cc67eef1ff53aced9602e253249e.tar.gz
CMake-669db35aa445cc67eef1ff53aced9602e253249e.tar.bz2
ENH: Changed signature of GET_PROPERTY command to be more powerful and extendible.
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGetPropertyCommand.cxx429
-rw-r--r--Source/cmGetPropertyCommand.h62
2 files changed, 329 insertions, 162 deletions
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index 273cfd6..2649cb6 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -20,9 +20,14 @@
#include "cmTest.h"
#include "cmPropertyDefinition.h"
-// cmGetPropertyCommand
-bool cmGetPropertyCommand::InitialPass(
- std::vector<std::string> const& args)
+//----------------------------------------------------------------------------
+cmGetPropertyCommand::cmGetPropertyCommand()
+{
+ this->InfoType = OutValue;
+}
+
+//----------------------------------------------------------------------------
+bool cmGetPropertyCommand::InitialPass(std::vector<std::string> const& args)
{
if(args.size() < 3 )
{
@@ -30,182 +35,308 @@ bool cmGetPropertyCommand::InitialPass(
return false;
}
- // the last argument in the property to get
- const char *property = args[args.size()-1].c_str();
- bool get_brief = false;
- if (!strcmp(property,"BRIEF_DOCS"))
- {
- get_brief = true;
- property = args[args.size()-2].c_str();
- }
- bool get_full = false;
- if (!strcmp(property,"FULL_DOCS"))
- {
- get_full = true;
- property = args[args.size()-2].c_str();
- }
-
- std::string output = "NOTFOUND";
+ // The cmake variable in which to store the result.
+ this->Variable = args[0];
+ // Get the scope from which to get the property.
cmProperty::ScopeType scope;
- const char *scopeName = 0;
- if (args[1] == "GLOBAL")
+ if(args[1] == "GLOBAL")
{
scope = cmProperty::GLOBAL;
}
- else if (args[1] == "VARIABLE")
- {
- scope = cmProperty::VARIABLE;
- }
- else if (args[1] == "DIRECTORY" && args.size() >= 3)
+ else if(args[1] == "DIRECTORY")
{
scope = cmProperty::DIRECTORY;
- if ((args.size() == 4 && !get_brief && !get_full) ||
- (args.size() == 5 && (get_brief || get_full)))
- {
- scopeName = args[2].c_str();
- }
}
- else if (args[1] == "TARGET" && args.size() >= 4)
+ else if(args[1] == "TARGET")
{
scope = cmProperty::TARGET;
- scopeName = args[2].c_str();
}
- else if (args[1] == "TEST" && args.size() >= 4)
+ else if(args[1] == "SOURCE")
+ {
+ scope = cmProperty::SOURCE_FILE;
+ }
+ else if(args[1] == "TEST")
{
scope = cmProperty::TEST;
- scopeName = args[2].c_str();
}
- else if (args[1] == "SOURCE_FILE" && args.size() >= 4)
+ else if(args[1] == "VARIABLE")
{
- scope = cmProperty::SOURCE_FILE;
- scopeName = args[2].c_str();
+ scope = cmProperty::VARIABLE;
}
else
{
- this->SetError("called with illegal arguments.");
+ cmOStringStream e;
+ e << "given invalid scope " << args[1] << ". "
+ << "Valid scopes are "
+ << "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE.";
+ this->SetError(e.str().c_str());
return false;
}
-
- if (get_brief)
+
+ // Parse remaining arguments.
+ enum Doing { DoingNone, DoingName, DoingProperty, DoingType };
+ Doing doing = DoingName;
+ for(unsigned int i=2; i < args.size(); ++i)
{
- cmPropertyDefinition *def =
- this->Makefile->GetCMakeInstance()->
- GetPropertyDefinition(property,scope);
- if (def)
+ if(args[i] == "PROPERTY")
+ {
+ doing = DoingProperty;
+ }
+ else if(args[i] == "BRIEF_DOCS")
+ {
+ doing = DoingNone;
+ this->InfoType = OutBriefDoc;
+ }
+ else if(args[i] == "FULL_DOCS")
+ {
+ doing = DoingNone;
+ this->InfoType = OutFullDoc;
+ }
+ else if(args[i] == "DEFINED")
+ {
+ doing = DoingNone;
+ this->InfoType = OutDefined;
+ }
+ else if(doing == DoingName)
+ {
+ doing = DoingNone;
+ this->Name = args[i];
+ }
+ else if(doing == DoingProperty)
+ {
+ doing = DoingNone;
+ this->PropertyName = args[i];
+ }
+ else
+ {
+ cmOStringStream e;
+ e << "given invalid argument \"" << args[i] << "\".";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ }
+
+ // Make sure a property name was found.
+ if(this->PropertyName.empty())
+ {
+ this->SetError("not given a PROPERTY <name> argument.");
+ return false;
+ }
+
+ // Compute requested output.
+ if(this->InfoType == OutBriefDoc)
+ {
+ // Lookup brief documentation.
+ std::string output;
+ if(cmPropertyDefinition* def =
+ this->Makefile->GetCMakeInstance()->
+ GetPropertyDefinition(this->PropertyName.c_str(), scope))
{
output = def->GetShortDescription();
}
+ else
+ {
+ output = "NOTFOUND";
+ }
+ this->Makefile->AddDefinition(this->Variable.c_str(), output.c_str());
}
- else if (get_full)
+ else if(this->InfoType == OutFullDoc)
{
- cmPropertyDefinition *def =
- this->Makefile->GetCMakeInstance()->
- GetPropertyDefinition(property,scope);
- if (def)
+ // Lookup full documentation.
+ std::string output;
+ if(cmPropertyDefinition* def =
+ this->Makefile->GetCMakeInstance()->
+ GetPropertyDefinition(this->PropertyName.c_str(), scope))
{
output = def->GetFullDescription();
}
+ else
+ {
+ output = "NOTFOUND";
+ }
+ this->Makefile->AddDefinition(this->Variable.c_str(), output.c_str());
}
-
- else switch (scope)
- {
- case cmProperty::VARIABLE:
- {
- if (this->Makefile->GetDefinition(property))
- {
- output = this->Makefile->GetDefinition(property);
- }
- }
- break;
- case cmProperty::TARGET:
- {
- cmTarget *tgt = this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->FindTarget(0, scopeName, true);
- if (tgt)
- {
- cmTarget& target = *tgt;
- const char *prop = target.GetProperty(property);
- if (prop)
- {
- output = prop;
- }
- }
- }
- break;
- case cmProperty::DIRECTORY:
- {
- cmLocalGenerator *lg = this->Makefile->GetLocalGenerator();
- if (args.size() >= 4)
- {
- std::string sd = scopeName;
- // make sure the start dir is a full path
- if (!cmSystemTools::FileIsFullPath(sd.c_str()))
- {
- sd = this->Makefile->GetStartDirectory();
- sd += "/";
- sd += scopeName;
- }
-
- // The local generators are associated with collapsed paths.
- sd = cmSystemTools::CollapseFullPath(sd.c_str());
-
- // lookup the makefile from the directory name
- lg =
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
- FindLocalGenerator(sd.c_str());
- }
- if (!lg)
- {
- this->SetError
- ("DIRECTORY argument provided but requested directory not found. "
- "This could be because the directory argument was invalid or, "
- "it is valid but has not been processed yet.");
- return false;
- }
- const char *prop = lg->GetMakefile()->GetProperty(property);
- if (prop)
- {
- output = prop;
- }
- }
- break;
- case cmProperty::GLOBAL:
- {
- const char *prop =
- this->Makefile->GetCMakeInstance()->GetProperty(property);
- if (prop)
- {
- output = prop;
- }
- }
- break;
- case cmProperty::TEST:
- {
- cmTest *test = this->Makefile->GetTest(scopeName);
- const char *prop = test->GetProperty(property);
- if (prop)
- {
- output = prop;
- }
- }
- break;
- case cmProperty::SOURCE_FILE:
- {
- cmSourceFile* sf = this->Makefile->GetSource(scopeName);
- const char *prop = sf->GetProperty(property);
- if (prop)
- {
- output = prop;
- }
- }
- break;
- case cmProperty::CACHED_VARIABLE:
- // not handled by GetProperty
- break;
- }
-
- this->Makefile->AddDefinition(args[0].c_str(), output.c_str());
+ else
+ {
+ // Dispatch property getting.
+ switch(scope)
+ {
+ case cmProperty::GLOBAL: return this->HandleGlobalMode();
+ case cmProperty::DIRECTORY: return this->HandleDirectoryMode();
+ case cmProperty::TARGET: return this->HandleTargetMode();
+ case cmProperty::SOURCE_FILE: return this->HandleSourceMode();
+ case cmProperty::TEST: return this->HandleTestMode();
+ case cmProperty::VARIABLE: return this->HandleVariableMode();
+
+ case cmProperty::CACHED_VARIABLE:
+ break; // should never happen
+ }
+ }
+
return true;
}
+//----------------------------------------------------------------------------
+bool cmGetPropertyCommand::StoreResult(const char* value)
+{
+ if(this->InfoType == OutDefined)
+ {
+ this->Makefile->AddDefinition(this->Variable.c_str(), value? "1":"0");
+ }
+ else // if(this->InfoType == OutValue)
+ {
+ this->Makefile->AddDefinition(this->Variable.c_str(), value);
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmGetPropertyCommand::HandleGlobalMode()
+{
+ if(!this->Name.empty())
+ {
+ this->SetError("given name for GLOBAL scope.");
+ return false;
+ }
+
+ // Get the property.
+ cmake* cm = this->Makefile->GetCMakeInstance();
+ return this->StoreResult(cm->GetProperty(this->PropertyName.c_str()));
+}
+
+//----------------------------------------------------------------------------
+bool cmGetPropertyCommand::HandleDirectoryMode()
+{
+ // Default to the current directory.
+ cmMakefile* mf = this->Makefile;
+
+ // Lookup the directory if given.
+ if(!this->Name.empty())
+ {
+ // Construct the directory name. Interpret relative paths with
+ // respect to the current directory.
+ std::string dir = this->Name;
+ if(!cmSystemTools::FileIsFullPath(dir.c_str()))
+ {
+ dir = this->Makefile->GetCurrentDirectory();
+ dir += "/";
+ dir += this->Name;
+ }
+
+ // The local generators are associated with collapsed paths.
+ dir = cmSystemTools::CollapseFullPath(dir.c_str());
+
+ // Lookup the generator.
+ if(cmLocalGenerator* lg =
+ (this->Makefile->GetLocalGenerator()
+ ->GetGlobalGenerator()->FindLocalGenerator(dir.c_str())))
+ {
+ // Use the makefile for the directory found.
+ mf = lg->GetMakefile();
+ }
+ else
+ {
+ // Could not find the directory.
+ this->SetError
+ ("DIRECTORY scope provided but requested directory was not found. "
+ "This could be because the directory argument was invalid or, "
+ "it is valid but has not been processed yet.");
+ return false;
+ }
+ }
+
+ // Get the property.
+ return this->StoreResult(mf->GetProperty(this->PropertyName.c_str()));
+}
+
+//----------------------------------------------------------------------------
+bool cmGetPropertyCommand::HandleTargetMode()
+{
+ if(this->Name.empty())
+ {
+ this->SetError("not given name for TARGET scope.");
+ return false;
+ }
+
+ if(cmTarget* target =
+ this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
+ ->FindTarget(0, this->Name.c_str(), true))
+ {
+ return this->StoreResult(target->GetProperty(this->PropertyName.c_str()));
+ }
+ else
+ {
+ cmOStringStream e;
+ e << "could not find TARGET " << this->Name
+ << ". Perhaps it has not yet been created.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+}
+
+//----------------------------------------------------------------------------
+bool cmGetPropertyCommand::HandleSourceMode()
+{
+ if(this->Name.empty())
+ {
+ this->SetError("not given name for SOURCE scope.");
+ return false;
+ }
+
+ // Get the source file.
+ if(cmSourceFile* sf =
+ this->Makefile->GetOrCreateSource(this->Name.c_str()))
+ {
+ return this->StoreResult(sf->GetProperty(this->PropertyName.c_str()));
+ }
+ else
+ {
+ cmOStringStream e;
+ e << "given SOURCE name that could not be found or created: "
+ << this->Name;
+ this->SetError(e.str().c_str());
+ return false;
+ }
+}
+
+//----------------------------------------------------------------------------
+bool cmGetPropertyCommand::HandleTestMode()
+{
+ if(this->Name.empty())
+ {
+ this->SetError("not given name for TEST scope.");
+ return false;
+ }
+
+ // Loop over all tests looking for matching names.
+ std::vector<cmTest*> const& tests = *this->Makefile->GetTests();
+ for(std::vector<cmTest*>::const_iterator ti = tests.begin();
+ ti != tests.end(); ++ti)
+ {
+ cmTest* test = *ti;
+ if(test->GetName() == this->Name)
+ {
+ return this->StoreResult(test->GetProperty(this->PropertyName.c_str()));
+ }
+ }
+
+ // If not found it is an error.
+ cmOStringStream e;
+ e << "given TEST name that does not exist: " << this->Name;
+ this->SetError(e.str().c_str());
+ return false;
+}
+
+//----------------------------------------------------------------------------
+bool cmGetPropertyCommand::HandleVariableMode()
+{
+ if(!this->Name.empty())
+ {
+ this->SetError("given name for VARIABLE scope.");
+ return false;
+ }
+
+ return this->StoreResult
+ (this->Makefile->GetDefinition(this->PropertyName.c_str()));
+}
diff --git a/Source/cmGetPropertyCommand.h b/Source/cmGetPropertyCommand.h
index f7155e1..f7c8ece 100644
--- a/Source/cmGetPropertyCommand.h
+++ b/Source/cmGetPropertyCommand.h
@@ -22,6 +22,8 @@
class cmGetPropertyCommand : public cmCommand
{
public:
+ cmGetPropertyCommand();
+
virtual cmCommand* Clone()
{
return new cmGetPropertyCommand;
@@ -57,23 +59,57 @@ public:
virtual const char* GetFullDocumentation()
{
return
- " get_property(VAR scope_value property)\n"
- " get_property(VAR scope_value property \n"
- " BRIEF_DOCS)\n"
- " get_property(VAR scope_value property \n"
- " FULL_DOCS)\n"
- "Get a property from cmake. The scope_value is either GLOBAL, "
- "DIRECTORY dir_name, TARGET tgt_name, SOURCE_FILE src_name, "
- "TEST test_name or VARIABLE var_name. The resulting value is "
- "stored in the variable VAR. If the property is not found, "
- "CMake will report an error. The second and third signatures "
- "return the documentation for a property or variable instead of "
- "its value.";
+ " get_property(<variable>\n"
+ " <GLOBAL |\n"
+ " DIRECTORY [dir] |\n"
+ " TARGET <target> |\n"
+ " SOURCE <source> |\n"
+ " TEST <test> |\n"
+ " VARIABLE>\n"
+ " PROPERTY <name>\n"
+ " [DEFINED | BRIEF_DOCS | FULL_DOCS])\n"
+ "Get one property from one object in a scope. "
+ "The first argument specifies the variable in which to store the "
+ "result. "
+ "The second argument determines the scope from which to get the "
+ "property. It must be one of the following:\n"
+ "GLOBAL scope is unique and does not accept a name.\n"
+ "DIRECTORY scope defaults to the current directory but another "
+ "directory (already processed by CMake) may be named by full or "
+ "relative path.\n"
+ "TARGET scope must name one existing target.\n"
+ "SOURCE scope must name one source file.\n"
+ "TEST scope must name one existing test.\n"
+ "VARIABLE scope is unique and does not accept a name.\n"
+ "The required PROPERTY option is immediately followed by the name "
+ "of the property to get. "
+ "If the property is not set an empty value is returned. "
+ "If the DEFINED option is given the variable is set to a boolean "
+ "value indicating whether the property has been set. "
+ "If BRIEF_DOCS or FULL_DOCS is given then the variable is set to "
+ "a string containing documentation for the requested property. "
+ "If documentation is requested for a property that has not been "
+ "defined NOTFOUND is returned.";
}
cmTypeMacro(cmGetPropertyCommand, cmCommand);
-};
+private:
+ enum OutType { OutValue, OutDefined, OutBriefDoc, OutFullDoc };
+ std::string Variable;
+ std::string Name;
+ std::string PropertyName;
+ OutType InfoType;
+ // Implementation of result storage.
+ bool StoreResult(const char* value);
+ // Implementation of each property type.
+ bool HandleGlobalMode();
+ bool HandleDirectoryMode();
+ bool HandleTargetMode();
+ bool HandleSourceMode();
+ bool HandleTestMode();
+ bool HandleVariableMode();
+};
#endif