Przeglądaj źródła

ENH: make properties a bit more formal with documentation and chaining

Ken Martin 19 lat temu
rodzic
commit
27379d7b08
44 zmienionych plików z 1130 dodań i 127 usunięć
  1. 4 4
      Source/CMakeLists.txt
  2. 2 0
      Source/cmAuxSourceDirectoryCommand.cxx
  3. 20 0
      Source/cmCPluginAPI.cxx
  4. 7 0
      Source/cmCPluginAPI.h
  5. 4 0
      Source/cmCommands.cxx
  6. 3 0
      Source/cmCreateTestSourceList.cxx
  7. 64 0
      Source/cmDefinePropertyCommand.cxx
  8. 74 0
      Source/cmDefinePropertyCommand.h
  9. 83 0
      Source/cmDocumentation.cxx
  10. 9 1
      Source/cmDocumentation.h
  11. 2 0
      Source/cmFLTKWrapUICommand.cxx
  12. 2 1
      Source/cmForEachCommand.cxx
  13. 1 0
      Source/cmGlobalGenerator.cxx
  14. 2 1
      Source/cmIfCommand.cxx
  15. 2 1
      Source/cmInstallFilesCommand.cxx
  16. 2 1
      Source/cmInstallProgramsCommand.cxx
  17. 4 3
      Source/cmLocalGenerator.cxx
  18. 2 1
      Source/cmMacroCommand.cxx
  19. 74 17
      Source/cmMakefile.cxx
  20. 12 2
      Source/cmMakefile.h
  21. 9 3
      Source/cmPropertyMap.cxx
  22. 31 16
      Source/cmSetDirectoryPropertiesCommand.cxx
  23. 8 0
      Source/cmSetDirectoryPropertiesCommand.h
  24. 30 16
      Source/cmSetTargetPropertiesCommand.cxx
  25. 8 1
      Source/cmSetTargetPropertiesCommand.h
  26. 119 16
      Source/cmSourceFile.cxx
  27. 11 5
      Source/cmSourceFile.h
  28. 247 14
      Source/cmTarget.cxx
  29. 11 1
      Source/cmTarget.h
  30. 50 13
      Source/cmTest.cxx
  31. 15 5
      Source/cmTest.h
  32. 4 0
      Source/cmVTKMakeInstantiatorCommand.cxx
  33. 2 0
      Source/cmVTKWrapJavaCommand.cxx
  34. 4 0
      Source/cmVTKWrapPythonCommand.cxx
  35. 4 0
      Source/cmVTKWrapTclCommand.cxx
  36. 2 1
      Source/cmWhileCommand.cxx
  37. 140 0
      Source/cmake.cxx
  38. 29 0
      Source/cmake.h
  39. 11 0
      Source/cmakemain.cxx
  40. 2 0
      Tests/Complex/Library/CMakeLists.txt
  41. 2 0
      Tests/ComplexOneConfig/Library/CMakeLists.txt
  42. 2 0
      Tests/ComplexRelativePaths/Library/CMakeLists.txt
  43. 8 2
      Tests/LoadCommand/CMakeCommands/cmTestCommand.c
  44. 8 2
      Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c

+ 4 - 4
Source/CMakeLists.txt

@@ -146,10 +146,10 @@ SET(SRCS
   cmProperty.h
   cmPropertyDefinition.cxx
   cmPropertyDefinition.h
-#  cmPropertyDefinitionMap.cxx
-#  cmPropertyDefinitionMap.h
-#  cmPropertyMap.cxx
-#  cmPropertyMap.h
+  cmPropertyDefinitionMap.cxx
+  cmPropertyDefinitionMap.h
+  cmPropertyMap.cxx
+  cmPropertyMap.h
   cmSourceFile.cxx
   cmSourceFile.h
   cmSourceGroup.cxx

+ 2 - 0
Source/cmAuxSourceDirectoryCommand.cxx

@@ -69,6 +69,8 @@ bool cmAuxSourceDirectoryCommand::InitialPass
           // add the file as a class file so 
           // depends can be done
           cmSourceFile cmfile;
+          cmfile.GetProperties().SetCMakeInstance
+            (this->Makefile->GetCMakeInstance());
           cmfile.SetName(fullname.c_str(), 
                          this->Makefile->GetCurrentDirectory(),
                          this->Makefile->GetSourceExtensions(),

+ 20 - 0
Source/cmCPluginAPI.cxx

@@ -507,6 +507,14 @@ void * CCONV cmCreateSourceFile()
   return (void *)(new cmSourceFile);
 }
 
+void * CCONV cmCreateNewSourceFile(void *arg)
+{
+  cmMakefile *mf = static_cast<cmMakefile *>(arg);
+  cmSourceFile *sf = new cmSourceFile;
+  sf->GetProperties().SetCMakeInstance(mf->GetCMakeInstance());
+  return (void *)sf;
+}
+
 void CCONV cmDestroySourceFile(void *arg)
 {
   cmSourceFile *sf = static_cast<cmSourceFile *>(arg);
@@ -624,6 +632,16 @@ void CCONV cmFree(void *data)
   free(data);
 }
 
+void CCONV DefineSourceFileProperty (void *arg, const char *name,
+  const char *briefDocs, 
+  const char *longDocs,
+  int chained)
+{
+  cmMakefile *mf = static_cast<cmMakefile *>(arg);
+  mf->GetCMakeInstance()->DefineProperty(name,cmProperty::SOURCE_FILE,
+                                         briefDocs, longDocs,chained);
+}
+
 } // close the extern "C" scope
 
 cmCAPI cmStaticCAPI =
@@ -683,5 +701,7 @@ cmCAPI cmStaticCAPI =
   cmAddCustomCommandToOutput,
   cmAddCustomCommandToTarget,
   cmDisplayStatus,
+  cmCreateNewSourceFile,
+  DefineSourceFileProperty,
 };
 

+ 7 - 0
Source/cmCPluginAPI.h

@@ -170,6 +170,13 @@ typedef struct
   /* display status information */
   void  (CCONV *DisplaySatus) (void *info, const char *message);
 
+  /* new functions added after 2.4 */
+  void *(CCONV *CreateNewSourceFile) (void *mf);
+  void (CCONV *DefineSourceFileProperty) (void *mf, const char *name,
+                                          const char *briefDocs, 
+                                          const char *longDocs,
+                                          int chained);
+  
   /* this is the end of the C function stub API structure */
 } cmCAPI;
 

+ 4 - 0
Source/cmCommands.cxx

@@ -20,6 +20,7 @@
 #include "cmAuxSourceDirectoryCommand.cxx"
 #include "cmBuildNameCommand.cxx"
 #include "cmCreateTestSourceList.cxx"
+#include "cmDefinePropertyCommand.cxx"
 #include "cmElseIfCommand.cxx"
 #include "cmEnableLanguageCommand.cxx"
 #include "cmEndMacroCommand.cxx"
@@ -44,6 +45,7 @@
 #include "cmRemoveDefinitionsCommand.cxx"
 #include "cmSeparateArgumentsCommand.cxx"
 #include "cmSetDirectoryPropertiesCommand.cxx"
+#include "cmSetPropertiesCommand.cxx"
 #include "cmSetTargetPropertiesCommand.cxx"
 #include "cmSetTestsPropertiesCommand.cxx"
 #include "cmSourceGroupCommand.cxx"
@@ -75,6 +77,7 @@ void GetPredefinedCommands(std::list<cmCommand*>&
   commands.push_back(new cmAuxSourceDirectoryCommand);
   commands.push_back(new cmBuildNameCommand);
   commands.push_back(new cmCreateTestSourceList);
+  commands.push_back(new cmDefinePropertyCommand);
   commands.push_back(new cmElseIfCommand);
   commands.push_back(new cmEnableLanguageCommand);
   commands.push_back(new cmEndMacroCommand);
@@ -100,6 +103,7 @@ void GetPredefinedCommands(std::list<cmCommand*>&
   commands.push_back(new cmRemoveDefinitionsCommand);
   commands.push_back(new cmSeparateArgumentsCommand);
   commands.push_back(new cmSetDirectoryPropertiesCommand);
+  commands.push_back(new cmSetPropertiesCommand);
   commands.push_back(new cmSetTargetPropertiesCommand);
   commands.push_back(new cmSetTestsPropertiesCommand);
   commands.push_back(new cmSourceGroupCommand);

+ 3 - 0
Source/cmCreateTestSourceList.cxx

@@ -172,6 +172,7 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args)
 
   // Create the source list
   cmSourceFile cfile;
+  cfile.GetProperties().SetCMakeInstance(this->Makefile->GetCMakeInstance());
   std::string sourceListValue;
 
   cfile.SetProperty("ABSTRACT","0");
@@ -185,6 +186,8 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args)
   for(i = testsBegin; i != tests.end(); ++i)
     {
     cmSourceFile icfile;
+    icfile.GetProperties().
+      SetCMakeInstance(this->Makefile->GetCMakeInstance());
     icfile.SetProperty("ABSTRACT","0");
     icfile.SetName(i->c_str(),
                   this->Makefile->GetCurrentDirectory(),

+ 64 - 0
Source/cmDefinePropertyCommand.cxx

@@ -0,0 +1,64 @@
+/*=========================================================================
+
+  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 "cmDefinePropertyCommand.h"
+#include "cmake.h"
+
+// cmDefinePropertiesCommand
+bool cmDefinePropertyCommand::InitialPass(
+  std::vector<std::string> const& args)
+{
+  if(args.size() < 5 )
+    {
+    this->SetError("called with incorrect number of arguments");
+    return false;
+    }
+
+  // determine the scope
+  cmProperty::ScopeType scope;
+  if (args[1] == "GLOBAL")
+    {
+    scope = cmProperty::GLOBAL;
+    }
+  else if (args[1] == "DIRECTORY")
+    {
+    scope = cmProperty::DIRECTORY;
+    }
+  else if (args[1] == "TARGET")
+    {
+    scope = cmProperty::TARGET;
+    }
+  else if (args[1] == "SOURCE_FILE")
+    {
+    scope = cmProperty::SOURCE_FILE;
+    }
+  else if (args[1] == "TEST")
+    {
+    scope = cmProperty::TEST;
+    }
+  else
+    {
+    this->SetError("called with illegal arguments.");
+    return false;
+    }
+
+  this->Makefile->GetCMakeInstance()->DefineProperty
+    (args[0].c_str(), scope,args[2].c_str(), args[3].c_str(),
+     cmSystemTools::IsOn(args[4].c_str()));
+  
+  return true;
+}
+

+ 74 - 0
Source/cmDefinePropertyCommand.h

@@ -0,0 +1,74 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+#ifndef cmDefinesPropertyCommand_h
+#define cmDefinesPropertyCommand_h
+
+#include "cmCommand.h"
+
+class cmDefinePropertyCommand : public cmCommand
+{
+public:
+  virtual cmCommand* Clone() 
+    {
+      return new cmDefinePropertyCommand;
+    }
+
+  /**
+   * This is called when the command is first encountered in
+   * the input file.
+   */
+  virtual bool InitialPass(std::vector<std::string> const& args);
+
+  /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual const char* GetName() { return "DEFINE_PROPERTY";}
+
+  /**
+   * Succinct documentation.
+   */
+  virtual const char* GetTerseDocumentation() 
+    {
+    return "Define properties used by CMake.";
+    }
+  
+  /**
+   * Longer documentation.
+   */
+  virtual const char* GetFullDocumentation()
+    {
+      return
+        "  DEFINE_PROPERTY(property_name scope_value\n"
+        "                  short_description\n"
+        "                  full_description chain)\n"
+        "Define a property for a scope. The scope_value is either GLOBAL "
+        "DIRECTORY, TARGET, TEST, SOURCE_FILE. The short and full "
+        "descriptions are used to document the property, chain indicates "
+        "if that property chains such that a request for the property "
+        "on a target will chain up to the directory if it is not set on the "
+        "target. In such cases the property's scope is the most specific. "
+        "In that example the scope would be TARGET even though it can "
+        "chain up to DIRECTORY and GLOBAL."
+        ;
+    }
+  
+  cmTypeMacro(cmDefinePropertyCommand, cmCommand);
+};
+
+
+
+#endif

+ 83 - 0
Source/cmDocumentation.cxx

@@ -51,6 +51,14 @@ static const cmDocumentationEntry cmDocumentationCommandsHeader[] =
   {0,0,0}
 };
 
+//----------------------------------------------------------------------------
+static const cmDocumentationEntry cmDocumentationPropertiesHeader[] =
+{
+  {0,
+   "The following properties are available in CMakeLists.txt code:", 0},
+  {0,0,0}
+};
+
 //----------------------------------------------------------------------------
 static const cmDocumentationEntry cmDocumentationModulesHeader[] =
 {
@@ -226,8 +234,11 @@ bool cmDocumentation::PrintDocumentation(Type ht, std::ostream& os)
       return this->PrintDocumentationSingle(os);
     case cmDocumentation::SingleModule:  
       return this->PrintDocumentationSingleModule(os);
+    case cmDocumentation::SingleProperty:  
+      return this->PrintDocumentationSingleProperty(os);
     case cmDocumentation::List:      return this->PrintDocumentationList(os);
     case cmDocumentation::ModuleList: return this->PrintModuleList(os);
+    case cmDocumentation::PropertyList: return this->PrintPropertyList(os);
     case cmDocumentation::Full:      return this->PrintDocumentationFull(os);
     case cmDocumentation::HTML:      return this->PrintDocumentationHTML(os);
     case cmDocumentation::Man:       return this->PrintDocumentationMan(os);
@@ -470,6 +481,15 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv)
         i = i+1;
         }
       }
+    else if(strcmp(argv[i], "--help-property") == 0)
+      {
+      type = cmDocumentation::SingleProperty;
+      if((i+1 < argc) && !this->IsOption(argv[i+1]))
+        {
+        this->SinglePropertyName = argv[i+1];
+        i = i+1;
+        }
+      }
     else if(strcmp(argv[i], "--help-command-list") == 0)
       {
       type = cmDocumentation::List;
@@ -478,6 +498,10 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv)
       {
       type = cmDocumentation::ModuleList;
       }
+    else if(strcmp(argv[i], "--help-property-list") == 0)
+      {
+      type = cmDocumentation::PropertyList;
+      }
     else if(strcmp(argv[i], "--copyright") == 0)
       {
       type = cmDocumentation::Copyright;
@@ -555,6 +579,13 @@ void cmDocumentation::SetCommandsSection(const cmDocumentationEntry* section)
                    this->CommandsSection);
 }
 
+//----------------------------------------------------------------------------
+void cmDocumentation::SetPropertiesSection(const cmDocumentationEntry* section)
+{
+  this->SetSection(cmDocumentationPropertiesHeader, section, 0,
+                   this->PropertiesSection);
+}
+
 //----------------------------------------------------------------------------
 void cmDocumentation
 ::SetGeneratorsSection(const cmDocumentationEntry* section)
@@ -1118,6 +1149,35 @@ bool cmDocumentation::PrintDocumentationSingleModule(std::ostream& os)
   return false;
 }
 
+//----------------------------------------------------------------------------
+bool cmDocumentation::PrintDocumentationSingleProperty(std::ostream& os)
+{
+  if(this->PropertiesSection.empty())
+    {
+    os << "Internal error: properties list is empty." << std::endl;
+    return false;
+    }
+  if(this->SinglePropertyName.length() == 0)
+    {
+    os << "Argument --help-property needs a property name.\n";
+    return false;
+    }
+  for(cmDocumentationEntry* entry = &this->PropertiesSection[0];
+      entry->brief; ++entry)
+    {
+    if(entry->name && this->SinglePropertyName == entry->name)
+      {
+      this->PrintDocumentationCommand(os, entry);
+      return true;
+      }
+    }
+  // Argument was not a command.  Complain.
+  os << "Argument \"" << this->SinglePropertyName.c_str()
+     << "\" to --help-property is not a CMake property.  "
+     << "Use --help-property-list to see all properties.\n";
+  return false;
+}
+
 //----------------------------------------------------------------------------
 bool cmDocumentation::PrintDocumentationList(std::ostream& os)
 {
@@ -1137,6 +1197,25 @@ bool cmDocumentation::PrintDocumentationList(std::ostream& os)
   return true;
 }
 
+//----------------------------------------------------------------------------
+bool cmDocumentation::PrintPropertyList(std::ostream& os)
+{
+  if(this->PropertiesSection.empty())
+    {
+    os << "Internal error: properties list is empty." << std::endl;
+    return false;
+    }
+  for(cmDocumentationEntry* entry = &this->PropertiesSection[0];
+      entry->brief; ++entry)
+    {
+    if(entry->name)
+      {
+      os << entry->name << std::endl;
+      }
+    }
+  return true;
+}
+
 //----------------------------------------------------------------------------
 bool cmDocumentation::PrintModuleList(std::ostream& os)
 {
@@ -1261,6 +1340,10 @@ void cmDocumentation::CreateFullDocumentation()
     {
     this->AddSection("Standard CMake Modules", &this->ModulesSection[0]);
     }
+  if(!this->PropertiesSection.empty())
+    {
+    this->AddSection("Standard Properties", &this->PropertiesSection[0]);
+    }
   this->AddSection("Copyright", cmDocumentationCopyright);
   this->AddSection("See Also", cmDocumentationStandardSeeAlso);
 }

+ 9 - 1
Source/cmDocumentation.h

@@ -29,7 +29,8 @@ public:
   // High-level interface for standard documents:
   
   /** Types of help provided.  */
-  enum Type { None, Usage, Single, SingleModule, List, ModuleList,
+  enum Type { None, Usage, Single, SingleModule, SingleProperty,
+              List, ModuleList, PropertyList,
               Full, HTML, Man, Copyright, Version };
   
   /**
@@ -70,6 +71,9 @@ public:
   /** Set the listfile commands for standard document generation.  */
   void SetCommandsSection(const cmDocumentationEntry*);
   
+  /** Set the properties for standard document generation.  */
+  void SetPropertiesSection(const cmDocumentationEntry*);
+
   /** Set the generator descriptions for standard document generation.  */
   void SetGeneratorsSection(const cmDocumentationEntry*);
   
@@ -132,8 +136,10 @@ private:
   bool PrintVersion(std::ostream& os);
   bool PrintDocumentationList(std::ostream& os);
   bool PrintModuleList(std::ostream& os);
+  bool PrintPropertyList(std::ostream& os);
   bool PrintDocumentationSingle(std::ostream& os);
   bool PrintDocumentationSingleModule(std::ostream& os);
+  bool PrintDocumentationSingleProperty(std::ostream& os);
   bool PrintDocumentationUsage(std::ostream& os);
   bool PrintDocumentationFull(std::ostream& os);
   bool PrintDocumentationHTML(std::ostream& os);
@@ -159,11 +165,13 @@ private:
   std::vector<cmDocumentationEntry> OptionsSection;
   std::vector<cmDocumentationEntry> CommandsSection;
   std::vector<cmDocumentationEntry> ModulesSection;
+  std::vector<cmDocumentationEntry> PropertiesSection;
   std::vector<cmDocumentationEntry> GeneratorsSection;
   std::vector<cmDocumentationEntry> SeeAlsoSection;
   std::string SeeAlsoString;
   std::string SingleCommand;
   std::string SingleModuleName;
+  std::string SinglePropertyName;
   std::string CMakeRoot;
   std::vector< char* > ModuleStrings;
   std::vector< const char* > Names;

+ 2 - 0
Source/cmFLTKWrapUICommand.cxx

@@ -54,6 +54,8 @@ bool cmFLTKWrapUICommand::InitialPass(std::vector<std::string> const& args)
     if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE"))
       {
       cmSourceFile header_file;
+      header_file.GetProperties().SetCMakeInstance
+        (this->Makefile->GetCMakeInstance());
       std::string srcName = cmSystemTools::GetFilenameWithoutExtension(*i);
       const bool headerFileOnly = true;
       header_file.SetName(srcName.c_str(), 

+ 2 - 1
Source/cmForEachCommand.cxx

@@ -87,7 +87,8 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf)
     mf.ExpandArguments(lff.Arguments, expandedArguments);
     if ((!expandedArguments.empty() && 
          (expandedArguments[0] == this->Args[0]))
-        || mf.IsOn("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS"))
+        || cmSystemTools::IsOn
+        (mf.GetPropertyOrDefinition("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS")))
       {
       return true;
       }

+ 1 - 0
Source/cmGlobalGenerator.cxx

@@ -1595,6 +1595,7 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(
 {
   // Package
   cmTarget target;
+  target.GetProperties().SetCMakeInstance(this->CMakeInstance);
   target.SetType(cmTarget::GLOBAL_TARGET, name);
   target.SetInAll(false);
 

+ 2 - 1
Source/cmIfCommand.cxx

@@ -96,7 +96,8 @@ bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
 {
   if (!cmSystemTools::Strucmp(lff.Name.c_str(),"endif"))
     {
-    if (mf.IsOn("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS") 
+    if (cmSystemTools::IsOn
+        (mf.GetPropertyOrDefinition("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS"))
         || lff.Arguments == this->Args)
       {
       return true;

+ 2 - 1
Source/cmInstallFilesCommand.cxx

@@ -36,8 +36,9 @@ bool cmInstallFilesCommand
   // Create an INSTALL_FILES target specifically for this path.
   this->TargetName = "INSTALL_FILES_"+args[0];
   cmTarget& target = this->Makefile->GetTargets()[this->TargetName];
-  target.SetInAll(false);
   target.SetType(cmTarget::INSTALL_FILES, this->TargetName.c_str());
+  target.SetMakefile(this->Makefile);
+  target.SetInAll(false);
   target.SetInstallPath(args[0].c_str());
   
   if((args.size() > 1) && (args[1] == "FILES"))

+ 2 - 1
Source/cmInstallProgramsCommand.cxx

@@ -33,8 +33,9 @@ bool cmInstallProgramsCommand
   // Create an INSTALL_PROGRAMS target specifically for this path.
   this->TargetName = "INSTALL_PROGRAMS_"+args[0];
   cmTarget& target = this->Makefile->GetTargets()[this->TargetName];
-  target.SetInAll(false);
   target.SetType(cmTarget::INSTALL_PROGRAMS, this->TargetName.c_str());
+  target.SetMakefile(this->Makefile);
+  target.SetInAll(false);
   target.SetInstallPath(args[0].c_str());
 
   std::vector<std::string>::const_iterator s = args.begin();

+ 4 - 3
Source/cmLocalGenerator.cxx

@@ -117,6 +117,7 @@ void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg)
   this->GlobalGenerator = gg;
 
   // setup the home directories
+  this->Makefile->GetProperties().SetCMakeInstance(gg->GetCMakeInstance());
   this->Makefile->SetHomeDirectory(
     gg->GetCMakeInstance()->GetHomeDirectory());
   this->Makefile->SetHomeOutputDirectory(
@@ -200,15 +201,15 @@ void cmLocalGenerator::GenerateTestFiles()
       fout << "\"";
       }
     fout << ")" << std::endl;
-    std::map<cmStdString,cmStdString>::const_iterator pit;
-    const std::map<cmStdString,cmStdString>* mpit = &test->GetProperties();
+    cmPropertyMap::const_iterator pit;
+    cmPropertyMap* mpit = &test->GetProperties();
     if ( mpit->size() )
       {
       fout << "SET_TESTS_PROPERTIES(" << test->GetName() << " PROPERTIES ";
       for ( pit = mpit->begin(); pit != mpit->end(); ++ pit )
         {
         fout << " " << pit->first.c_str() << " \"";
-        const char* value = pit->second.c_str();
+        const char* value = pit->second.GetValue();
         for ( ; *value; ++ value )
           {
           switch ( *value )

+ 2 - 1
Source/cmMacroCommand.cxx

@@ -316,7 +316,8 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf)
     mf.ExpandArguments(lff.Arguments, expandedArguments);
     if ((!expandedArguments.empty() && 
         (expandedArguments[0] == this->Args[0]))
-        || mf.IsOn("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS"))
+        || cmSystemTools::IsOn
+        (mf.GetPropertyOrDefinition("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS")))
       {
       return true;
       }

+ 74 - 17
Source/cmMakefile.cxx

@@ -816,9 +816,9 @@ void cmMakefile::AddUtilityCommand(const char* utilityName, bool all,
 {
   // Create a target instance for this utility.
   cmTarget target;
+  target.SetMakefile(this);
   target.SetType(cmTarget::UTILITY, utilityName);
   target.SetInAll(all);
-  target.SetMakefile(this);
 
   if(!comment)
     {
@@ -1309,6 +1309,7 @@ void cmMakefile::AddLibrary(const char* lname, int shared,
     default:
       target.SetType(cmTarget::STATIC_LIBRARY, lname);
     }
+  target.SetMakefile(this);
 
   // Clear its dependencies. Otherwise, dependencies might persist
   // over changes in CMakeLists.txt, making the information stale and
@@ -1316,7 +1317,6 @@ void cmMakefile::AddLibrary(const char* lname, int shared,
   target.ClearDependencyInformation( *this, lname );
   target.SetInAll(in_all);
   target.GetSourceLists() = srcs;
-  target.SetMakefile(this);
   this->AddGlobalLinkInformation(lname, target);
   cmTargets::iterator it = 
     this->Targets.insert(cmTargets::value_type(lname,target)).first;
@@ -1329,9 +1329,9 @@ cmTarget* cmMakefile::AddExecutable(const char *exeName,
 {
   cmTarget target;
   target.SetType(cmTarget::EXECUTABLE, exeName);
+  target.SetMakefile(this);
   target.SetInAll(in_all);
   target.GetSourceLists() = srcs;
-  target.SetMakefile(this);
   this->AddGlobalLinkInformation(exeName, target);
   cmTargets::iterator it = 
     this->Targets.insert(cmTargets::value_type(exeName,target)).first;
@@ -2281,6 +2281,7 @@ cmSourceFile* cmMakefile::GetOrCreateSource(const char* sourceName,
 
   // we must create one
   cmSourceFile file; 
+  file.GetProperties().SetCMakeInstance(this->GetCMakeInstance());
   std::string path = cmSystemTools::GetFilenamePath(src);
   if(generated)
     {
@@ -2328,6 +2329,7 @@ cmSourceFile* cmMakefile::GetOrCreateSource(const char* sourceName,
   this->AddSource(file);
   src = file.GetFullPath();
   ret = this->GetSource(src.c_str());
+  ret->GetProperties().SetCMakeInstance(this->GetCMakeInstance());
   if (!ret)
     {
     cmSystemTools::Error(
@@ -2738,10 +2740,27 @@ void cmMakefile::SetProperty(const char* prop, const char* value)
     {
     value = "NOTFOUND";
     }
-  this->Properties[prop] = value;
+
+  this->Properties.SetProperty(prop,value,cmProperty::DIRECTORY);
+}
+
+const char *cmMakefile::GetPropertyOrDefinition(const char* prop)
+{
+  const char *ret = this->GetProperty(prop, cmProperty::DIRECTORY);
+  if (!ret)
+    {
+    ret = this->GetDefinition(prop);
+    }
+  return ret;
 }
 
 const char *cmMakefile::GetProperty(const char* prop)
+{
+  return this->GetProperty(prop, cmProperty::DIRECTORY);
+}
+
+const char *cmMakefile::GetProperty(const char* prop,
+                                    cmProperty::ScopeType scope)
 {
   // watch for specific properties
   if (!strcmp("PARENT_DIRECTORY",prop))
@@ -2764,24 +2783,21 @@ const char *cmMakefile::GetProperty(const char* prop)
       }
     this->SetProperty("LISTFILE_STACK",tmp.c_str());
     }
-  std::map<cmStdString,cmStdString>::const_iterator i = 
-    this->Properties.find(prop);
-  if (i != this->Properties.end())
+  
+  bool chain = false;
+  const char *retVal = 
+    this->Properties.GetPropertyValue(prop, scope, chain);
+  if (chain)
     {
-    return i->second.c_str();
+    return this->GetCMakeInstance()->GetProperty(prop,scope);
     }
-  return 0;
+
+  return retVal;    
 }
 
-bool cmMakefile::GetPropertyAsBool(const char* prop) const
+bool cmMakefile::GetPropertyAsBool(const char* prop)
 {
-  std::map<cmStdString,cmStdString>::const_iterator i = 
-    this->Properties.find(prop);
-  if (i != this->Properties.end())
-    {
-    return cmSystemTools::IsOn(i->second.c_str());
-    }
-  return false;
+  return cmSystemTools::IsOn(this->GetProperty(prop));
 }
 
 
@@ -2810,6 +2826,7 @@ cmTest* cmMakefile::CreateTest(const char* testName)
     }
   test = new cmTest;
   test->SetName(testName);
+  test->SetMakefile(this);
   this->Tests.push_back(test);
   return test;
 }
@@ -2855,3 +2872,43 @@ std::string cmMakefile::GetListFileStack()
     }
   return tmp;
 }
+
+// define properties
+void cmMakefile::DefineProperties(cmake *cm)
+{
+  cm->DefineProperty
+    ("ADDITIONAL_MAKE_CLEAN_FILES", cmProperty::DIRECTORY, 
+     "Addditional files to clean during the make clean stage.",
+     "A list of files that will be cleaned as a part of the "
+     "\"make clean\" stage. ");
+
+  cm->DefineProperty
+    ("CLEAN_NO_CUSTOM", cmProperty::DIRECTORY, 
+     "Should the output of custom commands be left.",
+     "If this is true then the outputs of custom commands for this "
+     "directory will not be removed during the \"make clean\" stage. ");
+
+  cm->DefineProperty
+    ("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS", cmProperty::DIRECTORY, 
+     "Allow loops to have non-matching closing statements.",
+     "If this is set then the closing statement of control "
+     "structures in CMake will not require an exact match to the "
+     "opening statement. For example  IF(foo) will not require "
+     "ENDIF(foo) but simple ENDIF() will work.",
+     true);
+
+  cm->DefineProperty
+    ("LISTFILE_STACK", cmProperty::DIRECTORY, 
+     "The current stack of listfiles being processed.",
+     "This property is mainly useful when trying to debug errors "
+     "in your CMake scripts. It returns a list of what list files "
+     "are currently being processed, in order. So if one listfile "
+     "does an INCLUDE command then that is effectively pushing "
+     "the included listfile onto the stack.");
+
+  cm->DefineProperty
+    ("TEST_INCLUDE_FILE", cmProperty::DIRECTORY, 
+     "A cmake file that will be included when ctest is run.",
+     "If you specify TEST_INCLUDE_FILE, that file will be "
+     "included and processed when ctest is run on the directory.");
+}

+ 12 - 2
Source/cmMakefile.h

@@ -22,6 +22,7 @@
 #include "cmTarget.h"
 #include "cmListFileCache.h"
 #include "cmCacheManager.h"
+#include "cmPropertyMap.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cmSourceGroup.h"
@@ -697,7 +698,12 @@ public:
   ///! Set/Get a property of this directory 
   void SetProperty(const char *prop, const char *value);
   const char *GetProperty(const char *prop);
-  bool GetPropertyAsBool(const char *prop) const;
+  const char *GetPropertyOrDefinition(const char *prop);
+  const char *GetProperty(const char *prop, cmProperty::ScopeType scope);
+  bool GetPropertyAsBool(const char *prop);
+
+  // Get the properties
+  cmPropertyMap &GetProperties() { return this->Properties; };
 
   typedef std::map<cmStdString, cmStdString> DefinitionMap;
   ///! Initialize a makefile from its parent
@@ -711,6 +717,10 @@ public:
     { this->InstallGenerators.push_back(g); }
   std::vector<cmInstallGenerator*>& GetInstallGenerators()
     { return this->InstallGenerators; }
+
+  // Define the properties
+  static void DefineProperties(cmake *cm);
+
 protected:
   // add link libraries and directories to the target
   void AddGlobalLinkInformation(const char* name, cmTarget& target);
@@ -791,7 +801,7 @@ private:
   cmsys::RegularExpression cmDefineRegex;
   cmsys::RegularExpression cmDefine01Regex;
 
-  std::map<cmStdString,cmStdString> Properties;
+  cmPropertyMap Properties;
 
   // should this makefile be processed before or after processing the parent
   bool PreOrder;

+ 9 - 3
Source/cmPropertyMap.cxx

@@ -18,6 +18,9 @@
 #include "cmSystemTools.h"
 #include "cmake.h"
 
+// define STRICT to get checking of all set and get property calls
+//#define STRICT 
+
 cmProperty *cmPropertyMap::GetOrCreateProperty(const char *name)
 {
   cmPropertyMap::iterator it = this->find(name);
@@ -41,7 +44,7 @@ void cmPropertyMap::SetProperty(const char *name, const char *value,
     return;
     }
 
-#if 0
+#ifdef STRICT
   if (!this->CMakeInstance)
     {
     cmSystemTools::Error("CMakeInstance not set on a property map!"); 
@@ -92,7 +95,7 @@ const char *cmPropertyMap
     }
 
   // has the property been defined?
-#if 0
+#ifdef STRICT
   if (!this->CMakeInstance)
     {
     cmSystemTools::Error("CMakeInstance not set on a property map!"); 
@@ -131,7 +134,10 @@ const char *cmPropertyMap
   if (it == this->end())
     {
     // should we chain up?
-    chain = this->CMakeInstance->IsPropertyChained(name,scope);
+    if (this->CMakeInstance)
+      {
+      chain = this->CMakeInstance->IsPropertyChained(name,scope);
+      }
     return 0;
     }
 

+ 31 - 16
Source/cmSetDirectoryPropertiesCommand.cxx

@@ -27,59 +27,74 @@ bool cmSetDirectoryPropertiesCommand::InitialPass(
     this->SetError("called with incorrect number of arguments");
     return false;
     }
+  
+  std::string errors;
+  bool ret = 
+    cmSetDirectoryPropertiesCommand::RunCommand(this->Makefile, 
+                                                args.begin() + 1, 
+                                                args.end(), errors);
+  if (!ret)
+    {
+    this->SetError(errors.c_str());
+    }
+  return ret;
+}
 
-  std::vector<std::string>::const_iterator ait;
-  for ( ait = args.begin()+1; 
-    ait != args.end(); 
-    ait += 2 )
+bool cmSetDirectoryPropertiesCommand
+::RunCommand(cmMakefile *mf,
+             std::vector<std::string>::const_iterator ait,
+             std::vector<std::string>::const_iterator aitend,
+             std::string &errors)
+{
+  for (; ait != aitend; ait += 2 )
     {
-    if ( ait +1 == args.end() )
+    if ( ait +1 == aitend)
       {
-      this->SetError("Wrong number of arguments");
+      errors = "Wrong number of arguments";
       return false;
       }
     const std::string& prop = *ait;
     const std::string& value = *(ait+1);
     if ( prop == "VARIABLES" )
       {
-      this->SetError
-        ("Variables and cache variables should be set using SET command");
+      errors = 
+        "Variables and cache variables should be set using SET command";
       return false;
       }
     else if ( prop == "MACROS" )
       {
-      this->SetError
-        ("Commands and macros cannot be set using SET_CMAKE_PROPERTIES");
+      errors = 
+        "Commands and macros cannot be set using SET_CMAKE_PROPERTIES";
       return false;
       }
     else if ( prop == "INCLUDE_DIRECTORIES" )
       {
       std::vector<std::string> varArgsExpanded;
       cmSystemTools::ExpandListArgument(value, varArgsExpanded);
-      this->Makefile->SetIncludeDirectories(varArgsExpanded);
+      mf->SetIncludeDirectories(varArgsExpanded);
       }
     else if ( prop == "LINK_DIRECTORIES" )
       {
       std::vector<std::string> varArgsExpanded;
       cmSystemTools::ExpandListArgument(value, varArgsExpanded);
-      this->Makefile->SetLinkDirectories(varArgsExpanded);
+      mf->SetLinkDirectories(varArgsExpanded);
       }
     else if ( prop == "INCLUDE_REGULAR_EXPRESSION" )
       {
-      this->Makefile->SetIncludeRegularExpression(value.c_str());
+      mf->SetIncludeRegularExpression(value.c_str());
       }
     else
       {
       if ( prop == "ADDITIONAL_MAKE_CLEAN_FILES" )
         {
         // This property is not inherrited
-        if ( strcmp(this->Makefile->GetCurrentDirectory(), 
-                    this->Makefile->GetStartDirectory()) != 0 )
+        if ( strcmp(mf->GetCurrentDirectory(), 
+                    mf->GetStartDirectory()) != 0 )
           {
           continue;
           }
         }
-      this->Makefile->SetProperty(prop.c_str(), value.c_str());
+      mf->SetProperty(prop.c_str(), value.c_str());
       }
     }
   

+ 8 - 0
Source/cmSetDirectoryPropertiesCommand.h

@@ -51,6 +51,14 @@ public:
     return "Set a property of the directory.";
     }
   
+  /**
+   * Static entry point for use by other commands
+   */
+  static bool RunCommand(cmMakefile *mf,
+                         std::vector<std::string>::const_iterator ait,
+                         std::vector<std::string>::const_iterator aitend,
+                         std::string &errors);
+
   /**
    * Longer documentation.
    */

+ 30 - 16
Source/cmSetTargetPropertiesCommand.cxx

@@ -71,27 +71,14 @@ bool cmSetTargetPropertiesCommand::InitialPass(
      return false;
     }
   
-  cmTargets& targets = this->Makefile->GetTargets();
   // now loop over all the targets
   int i;
-  unsigned int k;
   for(i = 0; i < numFiles; ++i)
     {   
-    // if the file is already in the makefile just set properites on it
-    cmTargets::iterator t = targets.find(args[i]);
-    if ( t != targets.end())
+    bool ret = cmSetTargetPropertiesCommand::SetOneTarget
+      (args[i].c_str(),propertyPairs,this->Makefile);
+    if (!ret)
       {
-      cmTarget& target = t->second;
-      // now loop through all the props and set them
-      for (k = 0; k < propertyPairs.size(); k = k + 2)
-        {
-        target.SetProperty(propertyPairs[k].c_str(),
-                           propertyPairs[k+1].c_str());
-        }
-      }
-    // if file is not already in the makefile, then add it
-    else
-      { 
       std::string message = "Can not find target to add properties to: ";
       message += args[i];
       this->SetError(message.c_str());
@@ -101,3 +88,30 @@ bool cmSetTargetPropertiesCommand::InitialPass(
   return true;
 }
 
+bool cmSetTargetPropertiesCommand
+::SetOneTarget(const char *tname, 
+               std::vector<std::string> &propertyPairs,
+               cmMakefile *mf)
+{
+  cmTargets& targets = mf->GetTargets();
+
+  // if the file is already in the makefile just set properites on it
+  cmTargets::iterator t = targets.find(tname);
+  if ( t != targets.end())
+    {
+    cmTarget& target = t->second;
+    // now loop through all the props and set them
+    unsigned int k;
+    for (k = 0; k < propertyPairs.size(); k = k + 2)
+      {
+      target.SetProperty(propertyPairs[k].c_str(),
+                         propertyPairs[k+1].c_str());
+      }
+    }
+  // if file is not already in the makefile, then add it
+  else
+    { 
+    return false;
+    }
+  return true;
+}

+ 8 - 1
Source/cmSetTargetPropertiesCommand.h

@@ -36,7 +36,7 @@ public:
   /**
    * The name of the command as specified in CMakeList.txt.
    */
-  virtual const char* GetName() { return "SET_TARGET_PROPERTIES";}
+  virtual const char* GetName() { return "SET_TARGET_PROPERTIES";}  
 
   /**
    * Succinct documentation.
@@ -46,6 +46,13 @@ public:
     return "Targets can have properties that affect how they are built.";
     }
   
+  /**
+   *  Used by this command and cmSetPropertiesCommand
+   */
+  static bool SetOneTarget(const char *tname, 
+                           std::vector<std::string> &propertyPairs, 
+                           cmMakefile *mf);
+
   /**
    * Longer documentation.
    */

+ 119 - 16
Source/cmSourceFile.cxx

@@ -17,7 +17,7 @@
 #include "cmSourceFile.h"
 #include "cmSystemTools.h"
 
-
+#include "cmake.h"
 
 // Set the name of the class and the full path to the file.
 // The class must be found in dir and end in name.cxx, name.txx, 
@@ -179,7 +179,8 @@ void cmSourceFile::SetProperty(const char* prop, const char* value)
     {
     value = "NOTFOUND";
     }
-  this->Properties[prop] = value;
+
+  this->Properties.SetProperty(prop, value, cmProperty::SOURCE_FILE);
 }
 
 const char *cmSourceFile::GetProperty(const char* prop) const
@@ -191,24 +192,14 @@ const char *cmSourceFile::GetProperty(const char* prop) const
     return this->FullPath.c_str();
     }
 
-  std::map<cmStdString,cmStdString>::const_iterator i = 
-    this->Properties.find(prop);
-  if (i != this->Properties.end())
-    {
-    return i->second.c_str();
-    }
-  return 0;
+  bool chain = false;
+  return this->Properties.GetPropertyValue(prop,cmProperty::SOURCE_FILE, 
+                                           chain);
 }
 
 bool cmSourceFile::GetPropertyAsBool(const char* prop) const
 {
-  std::map<cmStdString,cmStdString>::const_iterator i = 
-    this->Properties.find(prop);
-  if (i != this->Properties.end())
-    {
-    return cmSystemTools::IsOn(i->second.c_str());
-    }
-  return false;
+  return cmSystemTools::IsOn(this->GetProperty(prop));
 }
 
 void cmSourceFile::SetCustomCommand(cmCustomCommand* cc)
@@ -229,3 +220,115 @@ const std::string& cmSourceFile::GetSourceNameWithoutLastExtension()
     }
   return this->SourceNameWithoutLastExtension;
 }
+
+cmSourceFile::cmSourceFile()
+{
+  this->CustomCommand = 0; 
+}
+
+// define properties
+void cmSourceFile::DefineProperties(cmake *cm)
+{
+  // define properties
+  cm->DefineProperty
+    ("ABSTRACT", cmProperty::SOURCE_FILE, 
+     "Is this source file an abstract class.",
+     "A property ona source file that indicates if the source file "
+     "represents a class that is abstract. This only makes sense for "
+     "languages that have a notion of an abstract class and it is "
+     "only used by somw tools that wrap classes into other languages.");
+
+  cm->DefineProperty
+    ("COMPILE_FLAGS", cmProperty::SOURCE_FILE, 
+     "Additional flags to be added when compiling this source file.",
+     "These flags will be added to the list of compile flags when "
+     "this source file.");
+
+  cm->DefineProperty
+    ("EXTERNAL_OBJECT", cmProperty::SOURCE_FILE, 
+     "If set to true then this is an object file.",
+     "If this property is set to true then the source file "
+     "is really an object file and should not be compiled.  "
+     "It will still be linked into the target though.");
+
+  cm->DefineProperty
+    ("EXTRA_CONTENT", cmProperty::SOURCE_FILE, 
+     "Is this file part of a target's extra content.",
+     "If this property is set, the source file will be added to the "
+     "target's list of extra content. This is used by makefile "
+     "generators for some sort of Mac budle framework support.");
+
+  cm->DefineProperty
+    ("GENERATED", cmProperty::SOURCE_FILE, 
+     "Is this source file generated as part of the build process.",
+     "If a source file is generated by the build process CMake will "
+     "handle it differently in temrs of dependency checking etc. "
+     "Otherwise having a non-existent source file could create problems.");
+
+  cm->DefineProperty
+    ("HEADER_FILE_ONLY", cmProperty::SOURCE_FILE, 
+     "Is this source file only a header file.",
+     "A property ona source file that indicates if the source file "
+     "is a header file with no associated implementation. This is "
+     "set automatically based on the file extension and is used by "
+     "CMake to determine is certain dependency information should be "
+     "computed.");
+
+  cm->DefineProperty
+    ("KEEP_EXTENSION", cmProperty::SOURCE_FILE, 
+     "Make th eoutput file have the same extension as the source file.",
+     "If this property is set then the file extension of the output "
+     "file will be the same as that of the source file. Normally "
+     "the output file extension is computed based on the language "
+     "of the source file, for example .cxx will go to a .o extension.");
+
+  cm->DefineProperty
+    ("LANGUAGE", cmProperty::SOURCE_FILE, 
+     "What programming language is the file.",
+     "A property that can be set to indicate what programming language "
+     "the source file is. If it is not set the language is determined "
+     "based on the file extension. Typical values are CXX C etc.");
+
+  cm->DefineProperty
+    ("LOCATION", cmProperty::SOURCE_FILE, 
+     "The full path to a source file.",
+     "A read only property on a SOURCE FILE that contains the full path "
+     "to the source file.");
+
+  cm->DefineProperty
+    ("MACOSX_PACKAGE_LOCATION", cmProperty::SOURCE_FILE, 
+     "Location for MACOSX bundles and frameworks.",
+     "MACOSX_PACKAGE_LOCATION is the property of a file within a mac osx "
+     "bundle or framework that specifies where this file should be "
+     "copied. This makes sense for things like icons and other "
+     "resources.");
+
+  cm->DefineProperty
+    ("MACOSX_CONTENT", cmProperty::SOURCE_FILE, 
+     "If true then this is part of a MACOSX bundle or framework.",
+     "MACOSX_CONTENT is a flag that if true this file will be copied "
+     "to the bundle or framework.");
+
+  cm->DefineProperty
+    ("OBJECT_DEPENDS", cmProperty::SOURCE_FILE, 
+     "Additional dependencies.",
+     "Additional dependencies that should be checked as part of "
+     "building this source file.");
+
+  cm->DefineProperty
+    ("SYMBOLIC", cmProperty::SOURCE_FILE, 
+     "Is this just a name for a rule.",
+     "If SYMBOLIC (boolean) is set to true the build system will be "
+     "informed that the source file is not actually created on disk but "
+     "instead used as a symbolic name for a build rule.");
+  
+  cm->DefineProperty
+    ("WRAP_EXCLUDE", cmProperty::SOURCE_FILE, 
+     "Exclude this source file from any code wrapping techniques.",
+     "Some packages can wrap source files into alternate languages "
+     "to provide additional functionality. For example, C++ code "
+     "can be wrapped into Java or Python etc using SWIG etc. "
+     "If WRAP_EXCLUDE is set to true (1 etc) that indicates then "
+     "this source file should not be wrapped.");
+}
+

+ 11 - 5
Source/cmSourceFile.h

@@ -18,6 +18,9 @@
 #define cmSourceFile_h
 
 #include "cmCustomCommand.h"
+#include "cmPropertyMap.h"
+
+class cmake;
 
 /** \class cmSourceFile
  * \brief Represent a class loaded from a makefile.
@@ -32,10 +35,7 @@ public:
    * Construct instance as a concrete class with both a
    * .h and .cxx file.
    */
-  cmSourceFile()
-    {
-      this->CustomCommand = 0;
-    }
+  cmSourceFile();
   ~cmSourceFile()
     {
       this->SetCustomCommand(0);
@@ -108,8 +108,14 @@ public:
    */
   const std::string& GetSourceNameWithoutLastExtension();
 
+  // Get the properties
+  cmPropertyMap &GetProperties() { return this->Properties; };
+
+  // Define the properties
+  static void DefineProperties(cmake *cm);
+
 private:
-  std::map<cmStdString,cmStdString> Properties;
+  cmPropertyMap Properties;
   cmCustomCommand *CustomCommand;
   std::string FullPath;
   std::string SourceName;

+ 247 - 14
Source/cmTarget.cxx

@@ -15,6 +15,7 @@
 
 =========================================================================*/
 #include "cmTarget.h"
+#include "cmake.h"
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
 #include "cmLocalGenerator.h"
@@ -36,6 +37,230 @@ cmTarget::cmTarget()
   this->LinkLibrariesAnalyzed = false;
   this->LinkDirectoriesComputed = false;
   this->HaveInstallRule = false;
+
+}
+
+// define properties
+void cmTarget::DefineProperties(cmake *cm)
+{
+  cm->DefineProperty
+    ("BUILD_WITH_INSTALL_RPATH", cmProperty::TARGET, 
+     "Should build tree targets have install tree rpaths.",
+     "BUILD_WITH_INSTALL_RPATH is a boolean specifying whether to link "
+     "the target in the build tree with the INSTALL_RPATH.  This takes "
+     "precedence over SKIP_BUILD_RPATH and avoids the need for relinking "
+     "before installation.");
+
+  cm->DefineProperty
+    ("CLEAN_DIRECT_OUTPUT", cmProperty::TARGET, 
+     "Do not delete other varients of this target.",
+     "When a library is built CMake by default generates code to remove "
+     "any existing library using all possible names.  This is needed "
+     "to support libraries that switch between STATIC and SHARED by "
+     "a user option.  However when using OUTPUT_NAME to build a static "
+     "and shared library of the same name using different logical target "
+     "names the two targets will remove each other's files.  This can be "
+     "prevented by setting the CLEAN_DIRECT_OUTPUT property to 1.");
+
+  cm->DefineProperty
+    ("COMPILE_FLAGS", cmProperty::TARGET, 
+     "Additional flags to yse when compiling this target's sources.",
+     "The COMPILE_FLAGS property sets additional compiler flags used "
+     "to build sources within the target.  It may also be used to pass "
+     "additional preprocessor definitions.");
+     
+  cm->DefineProperty
+    ("DEFINE_SYMBOL", cmProperty::TARGET, 
+     "Define a symbol when compiling this target's sources.",
+     "DEFINE_SYMBOL sets the name of the preprocessor symbol defined when "
+     "compiling sources in a shared library. "
+     "If not set here then it is set to target_EXPORTS by default "
+     "(with some substitutions if the target is not a valid C "
+     "identifier). This is useful for headers to know whether they are "
+     "being included from inside their library our outside to properly "
+     "setup dllexport/dllimport decorations. ");
+     
+  cm->DefineProperty
+    ("DEBUG_POSTFIX", cmProperty::TARGET, 
+     "A postfix that will be applied to this target when build debug.",
+     "A property on a target that sepcifies a postfix to add to the "
+     "target name when built in debug mode. For example foo.dll "
+     "versus fooD.dll");
+
+  cm->DefineProperty
+    ("EchoString", cmProperty::TARGET, 
+     "A message to be displayed when the target it built.",
+     "A message to display on some generaters (such as makefiles) when "
+     "the target is built.");
+
+  cm->DefineProperty
+    ("HAS_CXX", cmProperty::TARGET, 
+     "Force a target to use the CXX linker.",
+     "Setting HAS_CXX on a target will force the target to use the "
+     "C++ linker (and C++ runtime libraries) for linking even if the "
+     "target has no C++ code in it.");
+
+  cm->DefineProperty
+    ("IMPORT_PREFIX", cmProperty::TARGET, 
+     "What comes before the import library name.",
+     "Similar to the target property PREFIX, but used for import libraries "
+     "(typically corresponding to a DLL) instead of regular libraries. "
+     "A target property that can be set to override the prefix "
+     "(such as \"lib\") on an import library name.");
+
+  cm->DefineProperty
+    ("IMPORT_SUFFIX", cmProperty::TARGET, 
+     "What comes after the import library name.",
+     "Similar to the target property SUFFIX, but used for import libraries "
+     "(typically corresponding to a DLL) instead of regular libraries. "
+     "A target property that can be set to override the suffix "
+     "(such as \".lib\") on an import library name.");
+
+  cm->DefineProperty
+    ("IN_ALL", cmProperty::TARGET, 
+     "Is this target part of the all target.",
+     "A property on a target that indicates if the target is included as "
+     "part of the default build target. If it is, then with a Makefile "
+     "for example typing make will couse this target to be built as well. "
+     "The same concept applies to the default build of other generators.");
+
+  cm->DefineProperty
+    ("INSTALL_NAME_DIR", cmProperty::TARGET, 
+     "Mac OSX directory name for installed targets.",
+     "INSTALL_NAME_DIR is a string specifying the "
+     "directory portion of the \"install_name\" field of shared libraries "
+     "on Mac OSX to use in the installed targets. ");
+
+  cm->DefineProperty
+    ("INSTALL_RPATH", cmProperty::TARGET, 
+     "The rpath to use for installed targets.",
+     "A semicolon-separated list specifying the rpath "
+     "to use in installed targets (for platforms that support it).");
+
+  cm->DefineProperty
+    ("INSTALL_RPATH_USE_LINK_PATH", cmProperty::TARGET, 
+     "Add paths to linker search and installed rpath.",
+     "INSTALL_RPATH_USE_LINK_PATH is a boolean that if set to true will "
+     "append directories in the linker search path and outside the "
+     "project to the INSTALL_RPATH. ");
+
+  cm->DefineProperty
+    ("LINK_FLAGS", cmProperty::TARGET, 
+     "Additional flags to use when linking this target.",
+     "The LINK_FLAGS property can be used to add extra flags to the "
+     "link step of a target. LINK_FLAGS_<CONFIG> will add to the "
+     "configuration <CONFIG>, "
+     "for example, DEBUG, RELEASE, MINSIZEREL, RELWITHDEBINFO. ");
+
+  cm->DefineProperty
+    ("LINKER_LANGUAGE", cmProperty::TARGET, 
+     "What tool to use for linking, based on language.",
+     "The LINKER_LANGUAGE property is used to change the tool "
+     "used to link an executable or shared library. The default is "
+     "set the language to match the files in the library. CXX and C "
+     "are common values for this property.");
+
+  cm->DefineProperty
+    ("LOCATION", cmProperty::TARGET, 
+     "Where a target will be written on disk.",
+     "A read only property on a target that indicates where that target "
+     "will be written. For libraries and execuatables this will be where "
+     "the file is written on disk. This property is computed based on a "
+     "number of other settings.");
+
+  cm->DefineProperty
+    ("OUTPUT_NAME", cmProperty::TARGET, 
+     "Sets the real name of a target when it is built.",
+     "Sets the real name of a target when it is built and "
+     "can be used to help create two targets of the same name even though "
+     "CMake requires unique logical target names.  There is also a "
+     "<CONFIG>_OUTPUT_NAME that can set the output name on a "
+     "per-configuration basis.");
+
+  cm->DefineProperty
+    ("PRE_INSTALL_SCRIPT", cmProperty::TARGET, 
+     "Deprecated install support.",
+     "The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the "
+     "old way to specify CMake scripts to run before and after "
+     "installing a target.  They are used only when the old "
+     "INSTALL_TARGETS command is used to install the target.  Use the "
+     "INSTALL command instead.");
+
+  cm->DefineProperty
+    ("PREFIX", cmProperty::TARGET, 
+     "What comes before the library name.",
+     "A target property that can be set to override the prefix "
+     "(such as \"lib\") on a library name.");
+
+  cm->DefineProperty
+    ("POST_INSTALL_SCRIPT", cmProperty::TARGET, 
+     "Deprecated install support.",
+     "The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the "
+     "old way to specify CMake scripts to run before and after "
+     "installing a target.  They are used only when the old "
+     "INSTALL_TARGETS command is used to install the target.  Use the "
+     "INSTALL command instead.");
+
+  cm->DefineProperty
+    ("SKIP_BUILD_RPATH", cmProperty::TARGET, 
+     "Should rpaths be used for the build tree.",
+     "SKIP_BUILD_RPATH is a boolean specifying whether to skip automatic "
+     "generation of an rpath allowing the target to run from the "
+     "build tree. ");
+
+  cm->DefineProperty
+    ("SOVERSION", cmProperty::TARGET, 
+     "What version number is this target.",
+     "For shared libraries VERSION and SOVERSION can be used to specify "
+     "the build version and api version respectively. When building or "
+     "installing appropriate symlinks are created if the platform "
+     "supports symlinks and the linker supports so-names. "
+     "If only one of both is specified the missing is assumed to have "
+     "the same version number. "
+     "For shared libraries and executables on Windows the VERSION "
+     "attribute is parsed to extract a \"major.minor\" version number. "
+     "These numbers are used as the image version of the binary. ");
+
+  cm->DefineProperty
+    ("STATIC_LIBRARY_FLAGS", cmProperty::TARGET, 
+     "Extra flags to use when linking static libraries.",
+     "Extra flags to use when linking a static library.");
+
+  cm->DefineProperty
+    ("SUFFIX", cmProperty::TARGET, 
+     "What comes after the library name.",
+     "A target property that can be set to override the suffix "
+     "(such as \".so\") on a library name.");
+
+  cm->DefineProperty
+    ("VERSION", cmProperty::TARGET, 
+     "What version number is this target.",
+     "For shared libraries VERSION and SOVERSION can be used to specify "
+     "the build version and api version respectively. When building or "
+     "installing appropriate symlinks are created if the platform "
+     "supports symlinks and the linker supports so-names. "
+     "If only one of both is specified the missing is assumed to have "
+     "the same version number. "
+     "For executables VERSION can be used to specify the build version. "
+     "When building or installing appropriate symlinks are created if "
+     "the platform supports symlinks. "
+     "For shared libraries and executables on Windows the VERSION "
+     "attribute is parsed to extract a \"major.minor\" version number. "
+     "These numbers are used as the image version of the binary. ");
+
+
+  cm->DefineProperty
+    ("WIN32_EXECUTABLE", cmProperty::TARGET, 
+     "Used to specify Windows executable with a WinMain entry point.",
+     "This can be set to indicate that a target is a Windows executable "
+     "in contrast to a console application for example. This changes "
+     "how the executable will be linked.");
+
+
+  // define some properties without documentation
+  cm->DefineProperty("DEBUG_OUTPUT_NAME", cmProperty::TARGET,0,0);
+  cm->DefineProperty("RELEASE_OUTPUT_NAME", cmProperty::TARGET,0,0);
+  cm->DefineProperty("LINK_FLAGS_DEBUG", cmProperty::TARGET,0,0);
 }
 
 void cmTarget::SetType(TargetType type, const char* name)
@@ -60,6 +285,9 @@ void cmTarget::SetMakefile(cmMakefile* mf)
   // Set our makefile.
   this->Makefile = mf;
 
+  // set the cmake instance of the properties
+  this->Properties.SetCMakeInstance(mf->GetCMakeInstance());
+
   // Setup default property values.
   this->SetPropertyDefault("INSTALL_NAME_DIR", "");
   this->SetPropertyDefault("INSTALL_RPATH", "");
@@ -332,6 +560,8 @@ void cmTarget::GenerateSourceFilesFromSourceLists( cmMakefile &mf)
     if (!done)
       {
       cmSourceFile file;
+      file.GetProperties().
+        SetCMakeInstance(this->Makefile->GetCMakeInstance());
       file.SetProperty("ABSTRACT","0");
       file.SetName(temps.c_str(), mf.GetCurrentDirectory(),
                    mf.GetSourceExtensions(),
@@ -841,7 +1071,8 @@ void cmTarget::SetProperty(const char* prop, const char* value)
     {
     value = "NOTFOUND";
     }
-  this->Properties[prop] = value;
+
+  this->Properties.SetProperty(prop, value, cmProperty::TARGET);
 }
 
 const char* cmTarget::GetDirectory(const char* config)
@@ -924,6 +1155,12 @@ void cmTarget::GetTargetVersion(int& major, int& minor)
 }
 
 const char *cmTarget::GetProperty(const char* prop)
+{
+  return this->GetProperty(prop, cmProperty::TARGET);
+}
+
+const char *cmTarget::GetProperty(const char* prop,
+                                  cmProperty::ScopeType scope)
 {
   // watch for special "computed" properties that are dependent on other
   // properties or variables, always recompute them
@@ -984,25 +1221,21 @@ const char *cmTarget::GetProperty(const char* prop)
       }
     return 0;
     }
-      
-  std::map<cmStdString,cmStdString>::const_iterator i = 
-    this->Properties.find(prop);
-  if (i != this->Properties.end())
+  
+  bool chain = false;
+  const char *retVal = 
+    this->Properties.GetPropertyValue(prop, scope, chain);
+  if (chain)
     {
-    return i->second.c_str();
+    return this->Makefile->GetProperty(prop,scope);
     }
-  return 0;
+
+  return retVal;    
 }
 
 bool cmTarget::GetPropertyAsBool(const char* prop)
 {
-  std::map<cmStdString,cmStdString>::const_iterator i = 
-    this->Properties.find(prop);
-  if (i != this->Properties.end())
-    {
-    return cmSystemTools::IsOn(i->second.c_str());
-    }
-  return false;
+  return cmSystemTools::IsOn(this->GetProperty(prop));
 }
 
 const char* cmTarget::GetLinkerLanguage(cmGlobalGenerator* gg)

+ 11 - 1
Source/cmTarget.h

@@ -18,7 +18,9 @@
 #define cmTarget_h
 
 #include "cmCustomCommand.h"
+#include "cmPropertyMap.h"
 
+class cmake;
 class cmMakefile;
 class cmSourceFile;
 class cmGlobalGenerator;
@@ -165,6 +167,7 @@ public:
   ///! Set/Get a property of this target file
   void SetProperty(const char *prop, const char *value);
   const char *GetProperty(const char *prop);
+  const char *GetProperty(const char *prop, cmProperty::ScopeType scope);
   bool GetPropertyAsBool(const char *prop);
 
   /** Get the directory in which this target will be built.  If the
@@ -249,6 +252,12 @@ public:
   std::string GetInstallNameDirForBuildTree(const char* config);
   std::string GetInstallNameDirForInstallTree(const char* config);
 
+  // Get the properties
+  cmPropertyMap &GetProperties() { return this->Properties; };
+
+  // Define the properties
+  static void DefineProperties(cmake *cm);
+
 private:
   /**
    * A list of direct dependencies. Use in conjunction with DependencyMap.
@@ -320,6 +329,7 @@ private:
   // Use a makefile variable to set a default for the given property.
   // If the variable is not defined use the given default instead.
   void SetPropertyDefault(const char* property, const char* default_value);
+
 private:
   std::string Name;
   std::vector<cmCustomCommand> PreBuildCommands;
@@ -342,7 +352,7 @@ private:
   std::string Location;
   std::set<cmStdString> Utilities;
   bool RecordDependencies; 
-  std::map<cmStdString,cmStdString> Properties;
+  cmPropertyMap Properties;
   LinkLibraryVectorType OriginalLinkLibraries;
 
   // The cmMakefile instance that owns this target.  This should

+ 50 - 13
Source/cmTest.cxx

@@ -17,9 +17,12 @@
 #include "cmTest.h"
 #include "cmSystemTools.h"
 
+#include "cmake.h"
+#include "cmMakefile.h"
 
 cmTest::cmTest() 
 {
+  this->Makefile = 0;
 }
 
 cmTest::~cmTest()
@@ -52,24 +55,18 @@ void cmTest::SetArguments(const std::vector<cmStdString>& args)
 
 const char *cmTest::GetProperty(const char* prop) const
 {
-  std::map<cmStdString,cmStdString>::const_iterator i = 
-    this->Properties.find(prop);
-  if (i != this->Properties.end())
+  bool chain = false;
+  const char *retVal = 
+    this->Properties.GetPropertyValue(prop, cmProperty::TEST, chain);
+  if (chain)
     {
-    return i->second.c_str();
+    return this->Makefile->GetProperty(prop,cmProperty::TEST);
     }
-  return 0;
 }
 
 bool cmTest::GetPropertyAsBool(const char* prop) const
 {
-  std::map<cmStdString,cmStdString>::const_iterator i = 
-    this->Properties.find(prop);
-  if (i != this->Properties.end())
-    {
-    return cmSystemTools::IsOn(i->second.c_str());
-    }
-  return false;
+  return cmSystemTools::IsOn(this->GetProperty(prop));
 }
 
 void cmTest::SetProperty(const char* prop, const char* value)
@@ -82,6 +79,46 @@ void cmTest::SetProperty(const char* prop, const char* value)
     {
     value = "NOTFOUND";
     }
-  this->Properties[prop] = value;
+
+  this->Properties.SetProperty(prop, value, cmProperty::TEST);
+}
+
+//----------------------------------------------------------------------------
+void cmTest::SetMakefile(cmMakefile* mf)
+{
+  // Set our makefile.
+  this->Makefile = mf;
+  this->Properties.SetCMakeInstance(mf->GetCMakeInstance());
 }
 
+// define properties
+void cmTest::DefineProperties(cmake *cm)
+{
+  // define properties
+  cm->DefineProperty
+    ("FAIL_REGULAR_EXPRESSION", cmProperty::TEST, 
+     "If the output matches this regular expression tes test will fail.",
+     "If set, if the output matches one of "
+     "specified regular expressions, the test will fail."
+     "For example: PASS_REGULAR_EXPRESSION \"[^a-z]Error;ERROR;Failed\"");
+
+  cm->DefineProperty
+    ("MEASUREMENT", cmProperty::TEST, 
+     "Specify a DART meansurement and value to be reported for a test.",
+     "If set to a name then that name will be reported to DART as a "
+     "named measurement with a value of 1. You may also specify a value "
+     "by setting MEASUREMENT to \"measurement=value\".");
+
+  cm->DefineProperty
+    ("PASS_REGULAR_EXPRESSION", cmProperty::TEST, 
+     "The output must match this regular expression for the test to pass.",
+     "If set, the test output will be checked "
+     "against the specified regular expressions and at least one of the"
+     " regular expressions has to match, otherwise the test will fail.");
+
+  cm->DefineProperty
+    ("WILL_FAIL", cmProperty::TEST, 
+     "If set to true, this will invert the pass/fail flag of the test.",
+     "This property can be used for tests that are expected to fail and "
+     "return a non zero return code.");
+}

+ 15 - 5
Source/cmTest.h

@@ -18,6 +18,8 @@
 #define cmTest_h
 
 #include "cmCustomCommand.h"
+#include "cmPropertyMap.h"
+class cmMakefile;
 
 /** \class cmTest
  * \brief Represent a test
@@ -52,16 +54,24 @@ public:
   void SetProperty(const char *prop, const char *value);
   const char *GetProperty(const char *prop) const;
   bool GetPropertyAsBool(const char *prop) const;
-  const std::map<cmStdString,cmStdString>& GetProperties() const
-    {
-    return this->Properties;
-    }
+  cmPropertyMap &GetProperties() { return this->Properties; };
     
+  // Define the properties
+  static void DefineProperties(cmake *cm);
+
+  ///! Set the cmMakefile that owns this test
+  void SetMakefile(cmMakefile *mf);
+  cmMakefile *GetMakefile() { return this->Makefile;};
+
 private:
-  std::map<cmStdString,cmStdString> Properties;
+  cmPropertyMap Properties;
   cmStdString Name;
   cmStdString Command;
   std::vector<cmStdString> Args;
+
+  // The cmMakefile instance that owns this target.  This should
+  // always be set.
+  cmMakefile* Makefile;  
 };
 
 #endif

+ 4 - 0
Source/cmVTKMakeInstantiatorCommand.cxx

@@ -164,6 +164,8 @@ cmVTKMakeInstantiatorCommand
   
   // Add the generated source file into the source list.
   cmSourceFile file;
+  file.GetProperties().SetCMakeInstance
+    (this->Makefile->GetCMakeInstance());
   file.SetProperty("WRAP_EXCLUDE","1");
   file.SetProperty("ABSTRACT","0");
   file.SetName(fileName.c_str(), filePath.c_str(),
@@ -204,6 +206,8 @@ cmVTKMakeInstantiatorCommand
       
       // Add the generated source file into the source list.
       cmSourceFile file;
+      file.GetProperties().SetCMakeInstance
+        (this->Makefile->GetCMakeInstance());
       file.SetProperty("WRAP_EXCLUDE","1");
       file.SetProperty("ABSTRACT","0");
       file.SetName(fileName.c_str(), filePath.c_str(),

+ 2 - 0
Source/cmVTKWrapJavaCommand.cxx

@@ -70,6 +70,8 @@ bool cmVTKWrapJavaCommand::InitialPass(std::vector<std::string> const& argsIn)
     if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE"))
       {
       cmSourceFile file;
+      file.GetProperties().SetCMakeInstance
+        (this->Makefile->GetCMakeInstance());
       if (curr)
         {
         file.SetProperty("ABSTRACT",curr->GetProperty("ABSTRACT"));

+ 4 - 0
Source/cmVTKWrapPythonCommand.cxx

@@ -70,6 +70,8 @@ bool cmVTKWrapPythonCommand::InitialPass(std::vector<std::string> const&
     if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE"))
       {
       cmSourceFile file;
+      file.GetProperties().SetCMakeInstance
+        (this->Makefile->GetCMakeInstance());
       if (curr)
         {
         file.SetProperty("ABSTRACT",curr->GetProperty("ABSTRACT"));
@@ -90,6 +92,8 @@ bool cmVTKWrapPythonCommand::InitialPass(std::vector<std::string> const&
     }
   
   cmSourceFile cfile;
+  cfile.GetProperties().SetCMakeInstance
+    (this->Makefile->GetCMakeInstance());
   cfile.SetProperty("ABSTRACT","0");
   this->CreateInitFile(res);
   cfile.SetName(initName.c_str(), this->Makefile->GetCurrentOutputDirectory(),

+ 4 - 0
Source/cmVTKWrapTclCommand.cxx

@@ -106,6 +106,8 @@ bool cmVTKWrapTclCommand::InitialPass(std::vector<std::string> const& argsIn)
       if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE"))
         {
         cmSourceFile file;
+        file.GetProperties().SetCMakeInstance
+          (this->Makefile->GetCMakeInstance());
         std::string srcDir = cdir;
         if (curr)
           {
@@ -128,6 +130,8 @@ bool cmVTKWrapTclCommand::InitialPass(std::vector<std::string> const& argsIn)
       }
     // add the init file
     cmSourceFile cfile;
+    cfile.GetProperties().SetCMakeInstance
+      (this->Makefile->GetCMakeInstance());
     cfile.SetProperty("ABSTRACT","0");
     std::string newName = this->LibraryName;
     newName += "Init";

+ 2 - 1
Source/cmWhileCommand.cxx

@@ -81,7 +81,8 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf)
   if(!cmSystemTools::Strucmp(lff.Name.c_str(),"endwhile"))
     {
     if (lff.Arguments == this->Args
-        || mf.IsOn("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS"))
+        || cmSystemTools::IsOn
+        (mf.GetPropertyOrDefinition("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS")))
       {
       return true;
       }

+ 140 - 0
Source/cmake.cxx

@@ -23,7 +23,9 @@
 #include "cmCommand.h"
 #include "cmFileTimeComparison.h"
 #include "cmGeneratedFileStream.h"
+#include "cmSourceFile.h"
 #include "cmVersion.h"
+#include "cmTest.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 # include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
@@ -116,6 +118,14 @@ cmake::cmake()
   this->ClearBuildSystem = false;
   this->FileComparison = new cmFileTimeComparison;
 
+  this->Properties.SetCMakeInstance(this);
+
+  // initialize properties
+  cmSourceFile::DefineProperties(this);
+  cmTarget::DefineProperties(this);
+  cmMakefile::DefineProperties(this);
+  cmTest::DefineProperties(this);
+
 #ifdef __APPLE__
   struct rlimit rlp;
   if(!getrlimit(RLIMIT_STACK, &rlp))
@@ -1990,6 +2000,28 @@ void cmake::GetCommandDocumentation(
   v.push_back(empty);
 }
 
+void cmake::GetPropertiesDocumentation(std::vector<cmDocumentationEntry>& v)
+{
+  // get the properties for cmake
+  
+  // get them for any generators
+
+  // get them for Directories
+  this->DirectoryProperties.GetPropertiesDocumentation(v);
+
+  // get them for targets
+  this->TargetProperties.GetPropertiesDocumentation(v);
+  
+  // get them for source files
+  this->SourceFileProperties.GetPropertiesDocumentation(v);
+  
+  // get them for tests
+  this->TestProperties.GetPropertiesDocumentation(v);
+
+  cmDocumentationEntry empty = {0,0,0};
+  v.push_back(empty);
+}
+
 void cmake::GetGeneratorDocumentation(std::vector<cmDocumentationEntry>& v)
 {
   for(RegisteredGeneratorsMap::const_iterator i = this->Generators.begin();
@@ -2766,3 +2798,111 @@ int cmake::ExecuteLinkScript(std::vector<std::string>& args)
   // Return the final resulting return value.
   return result;
 }
+
+void cmake::DefineProperty(const char *name, cmProperty::ScopeType scope,
+                           const char *ShortDescription,
+                           const char *FullDescription,
+                           bool chained)
+{
+  switch (scope)
+    {
+    case cmProperty::GLOBAL:
+      this->GlobalProperties.DefineProperty(name,scope,ShortDescription,
+                                            FullDescription, chained);
+      break;
+    case cmProperty::TARGET:
+      this->TargetProperties.DefineProperty(name,scope,ShortDescription,
+                                            FullDescription, chained);
+      break;
+    case cmProperty::SOURCE_FILE:
+      this->SourceFileProperties.DefineProperty(name,scope,ShortDescription,
+                                                FullDescription, chained);
+      break;
+    case cmProperty::DIRECTORY:
+      this->DirectoryProperties.DefineProperty(name,scope,ShortDescription,
+                                               FullDescription, chained);
+      break;
+    case cmProperty::TEST:
+      this->TestProperties.DefineProperty(name,scope,ShortDescription,
+                                          FullDescription, chained);
+      break;
+    }
+}
+
+bool cmake::IsPropertyDefined(const char *name, cmProperty::ScopeType scope)
+{
+  switch (scope)
+    {
+    case cmProperty::GLOBAL:
+      return this->GlobalProperties.IsPropertyDefined(name);
+      break;
+    case cmProperty::TARGET:
+      return this->TargetProperties.IsPropertyDefined(name);
+      break;
+    case cmProperty::SOURCE_FILE:
+      return this->SourceFileProperties.IsPropertyDefined(name);
+      break;
+    case cmProperty::DIRECTORY:
+      return this->DirectoryProperties.IsPropertyDefined(name);
+      break;
+    case cmProperty::TEST:
+      return this->TestProperties.IsPropertyDefined(name);
+      break;
+    }
+
+  return false;
+}
+
+bool cmake::IsPropertyChained(const char *name, cmProperty::ScopeType scope)
+{
+  switch (scope)
+    {
+    case cmProperty::GLOBAL:
+      return this->GlobalProperties.IsPropertyChained(name);
+      break;
+    case cmProperty::TARGET:
+      return this->TargetProperties.IsPropertyChained(name);
+      break;
+    case cmProperty::SOURCE_FILE:
+      return this->SourceFileProperties.IsPropertyChained(name);
+      break;
+    case cmProperty::DIRECTORY:
+      return this->DirectoryProperties.IsPropertyChained(name);
+      break;  
+    case cmProperty::TEST:
+      return this->DirectoryProperties.IsPropertyChained(name);
+      break;
+  }
+
+  return false;
+}
+
+void cmake::SetProperty(const char* prop, const char* value)
+{
+  if (!prop)
+    {
+    return;
+    }
+  if (!value)
+    {
+    value = "NOTFOUND";
+    }
+
+  this->Properties.SetProperty(prop, value, cmProperty::TARGET);
+}
+
+const char *cmake::GetProperty(const char* prop)
+{
+  return this->GetProperty(prop, cmProperty::GLOBAL);
+}
+
+const char *cmake::GetProperty(const char* prop, cmProperty::ScopeType scope)
+{
+  bool chain = false;
+  return this->Properties.GetPropertyValue(prop, scope, chain);
+}
+
+bool cmake::GetPropertyAsBool(const char* prop)
+{
+  return cmSystemTools::IsOn(this->GetProperty(prop));
+}

+ 29 - 0
Source/cmake.h

@@ -41,6 +41,8 @@
 #define cmake_h
 
 #include "cmSystemTools.h"
+#include "cmPropertyDefinitionMap.h"
+#include "cmPropertyMap.h"
 
 class cmGlobalGenerator;
 class cmLocalGenerator;
@@ -235,8 +237,18 @@ class cmake
   cmVariableWatch* GetVariableWatch() { return this->VariableWatch; }
 
   void GetCommandDocumentation(std::vector<cmDocumentationEntry>&) const;
+  void GetPropertiesDocumentation(std::vector<cmDocumentationEntry>&);
   void GetGeneratorDocumentation(std::vector<cmDocumentationEntry>&);
 
+  ///! Set/Get a property of this target file
+  void SetProperty(const char *prop, const char *value);
+  const char *GetProperty(const char *prop);
+  const char *GetProperty(const char *prop, cmProperty::ScopeType scope);
+  bool GetPropertyAsBool(const char *prop);
+
+  // Get the properties
+  cmPropertyMap &GetProperties() { return this->Properties; };
+
   ///! Do all the checks before running configure
   int DoPreConfigureChecks();
 
@@ -278,7 +290,24 @@ class cmake
   bool GetDebugOutput() { return this->DebugOutput; }
   void DebugOutputOn() { this->DebugOutput = true;}
 
+  // Define a property
+  void DefineProperty(const char *name, cmProperty::ScopeType scope,
+                      const char *ShortDescription,
+                      const char *FullDescription,
+                      bool chain = false);
+
+  // Is a property defined?
+  bool IsPropertyDefined(const char *name, cmProperty::ScopeType scope);
+  bool IsPropertyChained(const char *name, cmProperty::ScopeType scope);
+
 protected:
+  cmPropertyMap Properties;
+  cmPropertyDefinitionMap TargetProperties;
+  cmPropertyDefinitionMap SourceFileProperties;
+  cmPropertyDefinitionMap DirectoryProperties;
+  cmPropertyDefinitionMap TestProperties;
+  cmPropertyDefinitionMap GlobalProperties;
+  
   typedef cmGlobalGenerator* (*CreateGeneratorFunctionType)();
   typedef std::map<cmStdString,
                    CreateGeneratorFunctionType> RegisteredGeneratorsMap;

+ 11 - 0
Source/cmakemain.cxx

@@ -18,6 +18,7 @@
 #include "cmCacheManager.h"
 #include "cmListFileCache.h"
 #include "cmakewizard.h"
+#include "cmSourceFile.h"
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
 #include "cmDynamicLoader.h"
@@ -100,6 +101,13 @@ static const cmDocumentationEntry cmDocumentationOptions[] =
    "The list contains all modules for which help may be obtained by using "
    "the --help-module argument followed by a module name.  If a file is "
    "specified, the help is written into it."},
+  {"--help-property prop [file]", 
+   "Print help for a single property and exit.",
+   "Full documentation specific to the given module is displayed."},
+  {"--help-property-list [file]", "List available properties and exit.",
+   "The list contains all properties for which help may be obtained by using "
+   "the --help-property argument followed by a property name.  If a file is "
+   "specified, the help is written into it."},
   {0,0,0}
 };
 
@@ -157,8 +165,10 @@ int do_cmake(int ac, char** av)
     hcm.AddCMakePaths(av[0]);
     doc.SetCMakeRoot(hcm.GetCacheDefinition("CMAKE_ROOT"));
     std::vector<cmDocumentationEntry> commands;
+    std::vector<cmDocumentationEntry> properties;
     std::vector<cmDocumentationEntry> generators;
     hcm.GetCommandDocumentation(commands);
+    hcm.GetPropertiesDocumentation(properties);
     hcm.GetGeneratorDocumentation(generators);
     doc.SetName("cmake");
     doc.SetNameSection(cmDocumentationName);
@@ -167,6 +177,7 @@ int do_cmake(int ac, char** av)
     doc.SetGeneratorsSection(&generators[0]);
     doc.SetOptionsSection(cmDocumentationOptions);
     doc.SetCommandsSection(&commands[0]);
+    doc.SetPropertiesSection(&properties[0]);
     doc.SetSeeAlsoList(cmDocumentationSeeAlso);
     int result = doc.PrintRequestedDocumentation(std::cout)? 0:1;
     

+ 2 - 0
Tests/Complex/Library/CMakeLists.txt

@@ -45,6 +45,8 @@ ADD_LIBRARY(CMakeTestLibraryShared SHARED ${SharedLibrarySources})
 ADD_LIBRARY(CMakeTestModule MODULE moduleFile.c)
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DTEST_C_FLAGS")
 ADD_LIBRARY(CMakeTestCLibraryShared SHARED testConly.c)
+DEFINE_PROPERTY(FOO TARGET "a test property"
+  "A simple etst proerty that means nothign and is used for nothing" 0)
 SET_TARGET_PROPERTIES(CMakeTestCLibraryShared PROPERTIES FOO BAR)
 IF(NOT BEOS)  # No libm on BeOS.
   SET_TARGET_PROPERTIES(CMakeTestCLibraryShared PROPERTIES LINK_FLAGS "-lm")

+ 2 - 0
Tests/ComplexOneConfig/Library/CMakeLists.txt

@@ -45,6 +45,8 @@ ADD_LIBRARY(CMakeTestLibraryShared SHARED ${SharedLibrarySources})
 ADD_LIBRARY(CMakeTestModule MODULE moduleFile.c)
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DTEST_C_FLAGS")
 ADD_LIBRARY(CMakeTestCLibraryShared SHARED testConly.c)
+DEFINE_PROPERTY(FOO TARGET "a test property"
+  "A simple etst proerty that means nothign and is used for nothing" 0)
 SET_TARGET_PROPERTIES(CMakeTestCLibraryShared PROPERTIES FOO BAR)
 IF(NOT BEOS)  # No libm on BeOS.
   SET_TARGET_PROPERTIES(CMakeTestCLibraryShared PROPERTIES LINK_FLAGS "-lm")

+ 2 - 0
Tests/ComplexRelativePaths/Library/CMakeLists.txt

@@ -45,6 +45,8 @@ ADD_LIBRARY(CMakeTestLibraryShared SHARED ${SharedLibrarySources})
 ADD_LIBRARY(CMakeTestModule MODULE moduleFile.c)
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DTEST_C_FLAGS")
 ADD_LIBRARY(CMakeTestCLibraryShared SHARED testConly.c)
+DEFINE_PROPERTY(FOO TARGET "a test property"
+  "A simple etst proerty that means nothign and is used for nothing" 0)
 SET_TARGET_PROPERTIES(CMakeTestCLibraryShared PROPERTIES FOO BAR)
 IF(NOT BEOS)  # No libm on BeOS.
   SET_TARGET_PROPERTIES(CMakeTestCLibraryShared PROPERTIES LINK_FLAGS "-lm")

+ 8 - 2
Tests/LoadCommand/CMakeCommands/cmTestCommand.c

@@ -99,18 +99,24 @@ static int CCONV InitialPass(void *inf, void *mf, int argc, char *argv[])
     }
   info->CAPI->AddDefineFlag(mf, "-DADDED_DEFINITION");
 
-  source_file = info->CAPI->CreateSourceFile();
+  source_file = info->CAPI->CreateNewSourceFile(mf);
   cstr = info->CAPI->SourceFileGetSourceName(source_file);
   sprintf(buffer, "Shold be empty (source file name): [%s]", cstr);
   info->CAPI->DisplaySatus(mf, buffer);
   cstr = info->CAPI->SourceFileGetFullPath(source_file);
-  sprintf(buffer, "Shold be empty (source file full path): [%s]", cstr);
+  sprintf(buffer, "Should be empty (source file full path): [%s]", cstr);
   info->CAPI->DisplaySatus(mf, buffer);
+  info->CAPI->DefineSourceFileProperty(mf,"SOME_PROPERTY","unused old prop",
+                                       "This property is no longer used",
+                                       0);
   if ( info->CAPI->SourceFileGetPropertyAsBool(source_file, "SOME_PROPERTY") )
     {
     info->CAPI->SetError(mf, "Property SOME_PROPERTY should not be defined");
     return 0;
     }
+  info->CAPI->DefineSourceFileProperty(mf,"SOME_PROPERTY2","nice prop",
+                                       "This property is for testing.",
+                                       0);
   info->CAPI->SourceFileSetProperty(source_file, "SOME_PROPERTY2", "HERE");
   cstr = info->CAPI->SourceFileGetProperty(source_file, "ABSTRACT");
   sprintf(buffer, "Should be 0 (source file abstract property): [%p]", cstr);

+ 8 - 2
Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c

@@ -99,18 +99,24 @@ static int CCONV InitialPass(void *inf, void *mf, int argc, char *argv[])
     }
   info->CAPI->AddDefineFlag(mf, "-DADDED_DEFINITION");
 
-  source_file = info->CAPI->CreateSourceFile();
+  source_file = info->CAPI->CreateNewSourceFile(mf);
   cstr = info->CAPI->SourceFileGetSourceName(source_file);
   sprintf(buffer, "Shold be empty (source file name): [%s]", cstr);
   info->CAPI->DisplaySatus(mf, buffer);
   cstr = info->CAPI->SourceFileGetFullPath(source_file);
-  sprintf(buffer, "Shold be empty (source file full path): [%s]", cstr);
+  sprintf(buffer, "Should be empty (source file full path): [%s]", cstr);
   info->CAPI->DisplaySatus(mf, buffer);
+  info->CAPI->DefineSourceFileProperty(mf,"SOME_PROPERTY","unused old prop",
+                                       "This property is no longer used",
+                                       0);
   if ( info->CAPI->SourceFileGetPropertyAsBool(source_file, "SOME_PROPERTY") )
     {
     info->CAPI->SetError(mf, "Property SOME_PROPERTY should not be defined");
     return 0;
     }
+  info->CAPI->DefineSourceFileProperty(mf,"SOME_PROPERTY2","nice prop",
+                                       "This property is for testing.",
+                                       0);
   info->CAPI->SourceFileSetProperty(source_file, "SOME_PROPERTY2", "HERE");
   cstr = info->CAPI->SourceFileGetProperty(source_file, "ABSTRACT");
   sprintf(buffer, "Should be 0 (source file abstract property): [%p]", cstr);