summaryrefslogtreecommitdiff
path: root/Source/cmSetPropertyCommand.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2008-01-17 15:54:49 -0500
committerBrad King <brad.king@kitware.com>2008-01-17 15:54:49 -0500
commitb8357db11d96eeb995b8443404e46466a493ab15 (patch)
tree9ccde29b2977a773527fed66ecb595e0b8282fbc /Source/cmSetPropertyCommand.cxx
parent456631225b11163f52b82989c1824bcd9ca3471c (diff)
downloadcmake-b8357db11d96eeb995b8443404e46466a493ab15.tar.gz
ENH: Rename SET_PROPERITES command to SET_PROPERTY and give it a more powerful signature.
Diffstat (limited to 'Source/cmSetPropertyCommand.cxx')
-rw-r--r--Source/cmSetPropertyCommand.cxx408
1 files changed, 408 insertions, 0 deletions
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
new file mode 100644
index 0000000000..a0455aa5b7
--- /dev/null
+++ b/Source/cmSetPropertyCommand.cxx
@@ -0,0 +1,408 @@
+/*=========================================================================
+
+ Program: CMake - Cross-Platform Makefile Generator
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmSetPropertyCommand.h"
+#include "cmSetTargetPropertiesCommand.h"
+#include "cmSetTestsPropertiesCommand.h"
+#include "cmSetSourceFilesPropertiesCommand.h"
+
+//----------------------------------------------------------------------------
+cmSetPropertyCommand::cmSetPropertyCommand()
+{
+ this->AppendMode = false;
+}
+
+//----------------------------------------------------------------------------
+bool cmSetPropertyCommand::InitialPass(std::vector<std::string> const& args)
+{
+ if(args.size() < 2 )
+ {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+
+ // Get the scope on which to set the property.
+ std::vector<std::string>::const_iterator arg = args.begin();
+ cmProperty::ScopeType scope;
+ if(*arg == "GLOBAL")
+ {
+ scope = cmProperty::GLOBAL;
+ }
+ else if(*arg == "DIRECTORY")
+ {
+ scope = cmProperty::DIRECTORY;
+ }
+ else if(*arg == "TARGET")
+ {
+ scope = cmProperty::TARGET;
+ }
+ else if(*arg == "SOURCE")
+ {
+ scope = cmProperty::SOURCE_FILE;
+ }
+ else if(*arg == "TEST")
+ {
+ scope = cmProperty::TEST;
+ }
+ else
+ {
+ cmOStringStream e;
+ e << "given invalid scope " << *arg << ". "
+ << "Valid scopes are GLOBAL, DIRECTORY, TARGET, SOURCE, TEST.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+
+ // Parse the rest of the arguments up to the values.
+ enum Doing { DoingNone, DoingNames, DoingProperty, DoingValues };
+ Doing doing = DoingNames;
+ const char* sep = "";
+ for(++arg; arg != args.end(); ++arg)
+ {
+ if(*arg == "PROPERTY")
+ {
+ doing = DoingProperty;
+ }
+ else if(*arg == "APPEND")
+ {
+ doing = DoingNone;
+ this->AppendMode = true;
+ }
+ else if(doing == DoingNames)
+ {
+ this->Names.insert(*arg);
+ }
+ else if(doing == DoingProperty)
+ {
+ this->PropertyName = *arg;
+ doing = DoingValues;
+ }
+ else if(doing == DoingValues)
+ {
+ this->PropertyValue += sep;
+ sep = ";";
+ this->PropertyValue += *arg;
+ }
+ else
+ {
+ cmOStringStream e;
+ e << "given invalid argument \"" << *arg << "\".";
+ 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;
+ }
+
+ // Dispatch property setting.
+ 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:
+ case cmProperty::CACHED_VARIABLE:
+ break; // should never happen
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmSetPropertyCommand::ConstructValue(std::string& value,
+ const char* old)
+{
+ if(this->AppendMode)
+ {
+ // This is an append. Start with the original value.
+ if(old)
+ {
+ value = old;
+ }
+ }
+ else if(this->PropertyValue.empty())
+ {
+ // This is a set to no values. Remove the property.
+ return false;
+ }
+
+ // Add the new value.
+ if(!this->PropertyValue.empty())
+ {
+ if(!value.empty())
+ {
+ value += ";";
+ }
+ value += this->PropertyValue;
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmSetPropertyCommand::HandleGlobalMode()
+{
+ if(!this->Names.empty())
+ {
+ this->SetError("given names for GLOBAL scope.");
+ return false;
+ }
+
+ // Set or append the property.
+ cmake* cm = this->Makefile->GetCMakeInstance();
+ const char* name = this->PropertyName.c_str();
+ std::string value;
+ if(this->ConstructValue(value, cm->GetProperty(name)))
+ {
+ // Set the new property.
+ cm->SetProperty(name, value.c_str());
+ }
+ else
+ {
+ // Remove the property.
+ cm->SetProperty(name, 0);
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmSetPropertyCommand::HandleDirectoryMode()
+{
+ if(this->Names.size() > 1)
+ {
+ this->SetError("allows at most one name for DIRECTORY scope.");
+ return false;
+ }
+
+ // Default to the current directory.
+ cmMakefile* mf = this->Makefile;
+
+ // Lookup the directory if given.
+ if(!this->Names.empty())
+ {
+ // Construct the directory name. Interpret relative paths with
+ // respect to the current directory.
+ std::string dir = *this->Names.begin();
+ if(!cmSystemTools::FileIsFullPath(dir.c_str()))
+ {
+ dir = this->Makefile->GetCurrentDirectory();
+ dir += "/";
+ dir += *this->Names.begin();
+ }
+
+ // 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;
+ }
+ }
+
+ // Set or append the property.
+ const char* name = this->PropertyName.c_str();
+ std::string value;
+ if(this->ConstructValue(value, mf->GetProperty(name)))
+ {
+ // Set the new property.
+ mf->SetProperty(name, value.c_str());
+ }
+ else
+ {
+ // Remove the property.
+ mf->SetProperty(name, 0);
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmSetPropertyCommand::HandleTargetMode()
+{
+ for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
+ ni != this->Names.end(); ++ni)
+ {
+ if(cmTarget* target =
+ this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
+ ->FindTarget(0, ni->c_str(), true))
+ {
+ // Handle the current target.
+ if(!this->HandleTarget(target))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ cmOStringStream e;
+ e << "could not find TARGET " << *ni
+ << ". Perhaps it has not yet been created.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmSetPropertyCommand::HandleTarget(cmTarget* target)
+{
+ // Set or append the property.
+ const char* name = this->PropertyName.c_str();
+ std::string value;
+ if(this->ConstructValue(value, target->GetProperty(name)))
+ {
+ // Set the new property.
+ target->SetProperty(name, value.c_str());
+ }
+ else
+ {
+ // Remove the property.
+ target->SetProperty(name, 0);
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmSetPropertyCommand::HandleSourceMode()
+{
+ for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
+ ni != this->Names.end(); ++ni)
+ {
+ // Get the source file.
+ if(cmSourceFile* sf = this->Makefile->GetOrCreateSource(ni->c_str()))
+ {
+ if(!this->HandleSource(sf))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ cmOStringStream e;
+ e << "given SOURCE name that could not be found or created: " << *ni;
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf)
+{
+ // Set or append the property.
+ const char* name = this->PropertyName.c_str();
+ std::string value;
+ if(this->ConstructValue(value, sf->GetProperty(name)))
+ {
+ // Set the new property.
+ sf->SetProperty(name, value.c_str());
+ }
+ else
+ {
+ // Remove the property.
+ sf->SetProperty(name, 0);
+ }
+
+ // TODO: MACOSX_PACKAGE_LOCATION special case in
+ // cmSetSourceFilesPropertiesCommand
+ // The logic should be moved to cmSourceFile.
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmSetPropertyCommand::HandleTestMode()
+{
+ // 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;
+ std::set<cmStdString>::const_iterator ni =
+ this->Names.find(test->GetName());
+ if(ni != this->Names.end())
+ {
+ if(this->HandleTest(test))
+ {
+ this->Names.erase(ni);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ // Names that are still left were not found.
+ if(!this->Names.empty())
+ {
+ cmOStringStream e;
+ e << "given TEST names that do not exist:\n";
+ for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
+ ni != this->Names.end(); ++ni)
+ {
+ e << " " << *ni << "\n";
+ }
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmSetPropertyCommand::HandleTest(cmTest* test)
+{
+ // Set or append the property.
+ const char* name = this->PropertyName.c_str();
+ std::string value;
+ if(this->ConstructValue(value, test->GetProperty(name)))
+ {
+ // Set the new property.
+ test->SetProperty(name, value.c_str());
+ }
+ else
+ {
+ // Remove the property.
+ test->SetProperty(name, 0);
+ }
+
+ return true;
+}