[Cmake-commits] [cmake-commits] king committed CMakeLists.txt 1.418 1.419 cmDefinitions.cxx NONE 1.1 cmDefinitions.h NONE 1.1 cmMakefile.cxx 1.513 1.514 cmMakefile.h 1.255 1.256

cmake-commits at cmake.org cmake-commits at cmake.org
Wed Jul 22 14:22:47 EDT 2009


Update of /cvsroot/CMake/CMake/Source
In directory public:/mounts/ram/cvs-serv12345/Source

Modified Files:
	CMakeLists.txt cmMakefile.cxx cmMakefile.h 
Added Files:
	cmDefinitions.cxx cmDefinitions.h 
Log Message:
ENH: Improve dynamic variable scope implementation

Previously each new variable scope (subdirectory or function call) in
the CMake language created a complete copy of the key->value definition
map.  This avoids the copy using transitive lookups up the scope stack.
Results of queries answered by parents are stored locally to maintain
locality of reference.

The class cmDefinitions replaces cmMakefile::DefinitionsMap, and is
aware of its enclosing scope.  Each scope stores only the definitions
set (or unset!) inside it relative to the enclosing scope.


--- NEW FILE: cmDefinitions.h ---
/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmDefinitions.h,v $
  Language:  C++
  Date:      $Date: 2009-07-22 18:22:45 $
  Version:   $Revision: 1.1 $

  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 cmDefinitions_h
#define cmDefinitions_h

#include "cmStandardIncludes.h"

/** \class cmDefinitions
 * \brief Store a scope of variable definitions for CMake language.
 *
 * This stores the state of variable definitions (set or unset) for
 * one scope.  Sets are always local.  Gets search parent scopes
 * transitively and save results locally.
 */
class cmDefinitions
{
public:
  /** Construct with the given parent scope.  */
  cmDefinitions(cmDefinitions* parent = 0);

  /** Reset object as if newly constructed.  */
  void Reset(cmDefinitions* parent = 0);

  /** Returns the parent scope, if any.  */
  cmDefinitions* GetParent() const { return this->Up; }

  /** Get the value associated with a key; null if none.
      Store the result locally if it came from a parent.  */
  const char* Get(const char* key);

  /** Set (or unset if null) a value associated with a key.  */
  const char* Set(const char* key, const char* value);

  /** Compute the closure of all defined keys with values.
      This flattens the scope.  The result has no parent.  */
  cmDefinitions Closure() const;

  /** Compute the set of all defined keys.  */
  std::set<cmStdString> ClosureKeys() const;

private:
  // String with existence boolean.
  struct Def: public cmStdString
  {
    Def(): cmStdString(), Exists(false) {}
    Def(const char* v): cmStdString(v?v:""), Exists(v?true:false) {}
    Def(Def const& d): cmStdString(d), Exists(d.Exists) {}
    bool Exists;
  };
  static Def NoDef;

  // Parent scope, if any.
  cmDefinitions* Up;

  // Local definitions, set or unset.
  typedef std::map<cmStdString, Def> MapType;
  MapType Map;

  // Internal query and update methods.
  Def const& GetInternal(const char* key);
  Def const& SetInternal(const char* key, Def const& def);

  // Implementation of Closure() method.
  struct ClosureTag {};
  cmDefinitions(ClosureTag const&, cmDefinitions const* root);
  void ClosureImpl(std::set<cmStdString>& undefined,
                   cmDefinitions const* defs);

  // Implementation of ClosureKeys() method.
  void ClosureKeys(std::set<cmStdString>& defined,
                   std::set<cmStdString>& undefined) const;
};

#endif

Index: CMakeLists.txt
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/CMakeLists.txt,v
retrieving revision 1.418
retrieving revision 1.419
diff -C 2 -d -r1.418 -r1.419
*** CMakeLists.txt	10 Jul 2009 15:07:44 -0000	1.418
--- CMakeLists.txt	22 Jul 2009 18:22:45 -0000	1.419
***************
*** 117,120 ****
--- 117,122 ----
    cmCustomCommand.cxx
    cmCustomCommand.h
+   cmDefinitions.cxx
+   cmDefinitions.h
    cmDepends.cxx
    cmDepends.h

--- NEW FILE: cmDefinitions.cxx ---
/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmDefinitions.cxx,v $
  Language:  C++
  Date:      $Date: 2009-07-22 18:22:45 $
  Version:   $Revision: 1.1 $

  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 "cmDefinitions.h"

//----------------------------------------------------------------------------
cmDefinitions::Def cmDefinitions::NoDef;

//----------------------------------------------------------------------------
cmDefinitions::cmDefinitions(cmDefinitions* parent): Up(parent)
{
}

//----------------------------------------------------------------------------
void cmDefinitions::Reset(cmDefinitions* parent)
{
  this->Up = parent;
  this->Map.clear();
}

//----------------------------------------------------------------------------
cmDefinitions::Def const&
cmDefinitions::GetInternal(const char* key)
{
  MapType::const_iterator i = this->Map.find(key);
  if(i != this->Map.end())
    {
    return i->second;
    }
  else if(cmDefinitions* up = this->Up)
    {
    // Query the parent scope and store the result locally.
    Def def = up->GetInternal(key);
    return this->Map.insert(MapType::value_type(key, def)).first->second;
    }
  return this->NoDef;
}

//----------------------------------------------------------------------------
cmDefinitions::Def const&
cmDefinitions::SetInternal(const char* key, Def const& def)
{
  if(this->Up || def.Exists)
    {
    // In lower scopes we store keys, defined or not.
    MapType::iterator i = this->Map.find(key);
    if(i == this->Map.end())
      {
      i = this->Map.insert(MapType::value_type(key, def)).first;
      }
    else
      {
      i->second = def;
      }
    return i->second;
    }
  else
    {
    // In the top-most scope we need not store undefined keys.
    this->Map.erase(key);
    return this->NoDef;
    }
}

//----------------------------------------------------------------------------
const char* cmDefinitions::Get(const char* key)
{
  Def const& def = this->GetInternal(key);
  return def.Exists? def.c_str() : 0;
}

//----------------------------------------------------------------------------
const char* cmDefinitions::Set(const char* key, const char* value)
{
  Def const& def = this->SetInternal(key, Def(value));
  return def.Exists? def.c_str() : 0;
}

//----------------------------------------------------------------------------
cmDefinitions cmDefinitions::Closure() const
{
  return cmDefinitions(ClosureTag(), this);
}

//----------------------------------------------------------------------------
cmDefinitions::cmDefinitions(ClosureTag const&, cmDefinitions const* root):
  Up(0)
{
  std::set<cmStdString> undefined;
  this->ClosureImpl(undefined, root);
}

//----------------------------------------------------------------------------
void cmDefinitions::ClosureImpl(std::set<cmStdString>& undefined,
                                cmDefinitions const* defs)
{
  // Consider local definitions.
  for(MapType::const_iterator mi = defs->Map.begin();
      mi != defs->Map.end(); ++mi)
    {
    // Use this key if it is not already set or unset.
    if(this->Map.find(mi->first) == this->Map.end() &&
       undefined.find(mi->first) == undefined.end())
      {
      if(mi->second.Exists)
        {
        this->Map.insert(*mi);
        }
      else
        {
        undefined.insert(mi->first);
        }
      }
    }

  // Traverse parents.
  if(cmDefinitions const* up = defs->Up)
    {
    this->ClosureImpl(undefined, up);
    }
}

//----------------------------------------------------------------------------
std::set<cmStdString> cmDefinitions::ClosureKeys() const
{
  std::set<cmStdString> defined;
  std::set<cmStdString> undefined;
  this->ClosureKeys(defined, undefined);
  return defined;
}

//----------------------------------------------------------------------------
void cmDefinitions::ClosureKeys(std::set<cmStdString>& defined,
                                std::set<cmStdString>& undefined) const
{
  // Consider local definitions.
  for(MapType::const_iterator mi = this->Map.begin();
      mi != this->Map.end(); ++mi)
    {
    // Use this key if it is not already set or unset.
    if(defined.find(mi->first) == defined.end() &&
       undefined.find(mi->first) == undefined.end())
      {
      std::set<cmStdString>& m = mi->second.Exists? defined : undefined;
      m.insert(mi->first);
      }
    }

  // Traverse parents.
  if(cmDefinitions const* up = this->Up)
    {
    up->ClosureKeys(defined, undefined);
    }
}

Index: cmMakefile.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmMakefile.h,v
retrieving revision 1.255
retrieving revision 1.256
diff -C 2 -d -r1.255 -r1.256
*** cmMakefile.h	17 Jun 2009 17:40:08 -0000	1.255
--- cmMakefile.h	22 Jul 2009 18:22:45 -0000	1.256
***************
*** 57,60 ****
--- 57,62 ----
  class cmMakefile
  {
+   class Internals;
+   cmsys::auto_ptr<Internals> Internal;
  public:
    /**
***************
*** 793,797 ****
    cmPropertyMap &GetProperties() { return this->Properties; };
  
-   typedef std::map<cmStdString, cmStdString> DefinitionMap;
    ///! Initialize a makefile from its parent
    void InitializeFromParent();
--- 795,798 ----
***************
*** 890,894 ****
  #endif
  
-   std::vector<DefinitionMap> DefinitionStack;
    std::vector<cmCommand*> UsedCommands;
    cmLocalGenerator* LocalGenerator;
--- 891,894 ----
***************
*** 925,930 ****
  
    std::map<cmStdString, bool> SubDirectoryOrder;
-   // used in AddDefinition for performance improvement
-   DefinitionMap::key_type  TemporaryDefinitionKey;
  
    cmsys::RegularExpression cmDefineRegex;
--- 925,928 ----

Index: cmMakefile.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmMakefile.cxx,v
retrieving revision 1.513
retrieving revision 1.514
diff -C 2 -d -r1.513 -r1.514
*** cmMakefile.cxx	17 Jul 2009 14:05:54 -0000	1.513
--- cmMakefile.cxx	22 Jul 2009 18:22:45 -0000	1.514
***************
*** 34,37 ****
--- 34,38 ----
  #include "cmInstallGenerator.h"
  #include "cmTestGenerator.h"
+ #include "cmDefinitions.h"
  #include "cmake.h"
  #include <stdlib.h> // required for atoi
***************
*** 41,50 ****
  #include <cmsys/auto_ptr.hxx>
  
  #include <ctype.h> // for isspace
  
  // default is not to be building executables
! cmMakefile::cmMakefile()
  {
!   this->DefinitionStack.push_back(DefinitionMap());
  
    // Setup the default include file regular expression (match everything).
--- 42,58 ----
  #include <cmsys/auto_ptr.hxx>
  
+ #include <stack>
  #include <ctype.h> // for isspace
  
+ class cmMakefile::Internals
+ {
+ public:
+   std::stack<cmDefinitions, std::list<cmDefinitions> > VarStack;
+ };
+ 
  // default is not to be building executables
! cmMakefile::cmMakefile(): Internal(new Internals)
  {
!   this->Internal->VarStack.push(cmDefinitions());
  
    // Setup the default include file regular expression (match everything).
***************
*** 86,91 ****
  }
  
! cmMakefile::cmMakefile(const cmMakefile& mf)
  {
    this->Prefix = mf.Prefix;
    this->AuxSourceDirectories = mf.AuxSourceDirectories;
--- 94,101 ----
  }
  
! cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals)
  {
+   this->Internal->VarStack.push(mf.Internal->VarStack.top().Closure());
+ 
    this->Prefix = mf.Prefix;
    this->AuxSourceDirectories = mf.AuxSourceDirectories;
***************
*** 118,122 ****
  #endif
  
-   this->DefinitionStack.push_back(mf.DefinitionStack.back());
    this->LocalGenerator = mf.LocalGenerator;
    this->FunctionBlockers = mf.FunctionBlockers;
--- 128,131 ----
***************
*** 124,128 ****
    this->MacrosMap = mf.MacrosMap;
    this->SubDirectoryOrder = mf.SubDirectoryOrder;
-   this->TemporaryDefinitionKey = mf.TemporaryDefinitionKey;
    this->Properties = mf.Properties;
    this->PreOrder = mf.PreOrder;
--- 133,136 ----
***************
*** 1422,1426 ****
  
    // copy the definitions
!   this->DefinitionStack.front() = parent->DefinitionStack.back();
  
    // copy include paths
--- 1430,1434 ----
  
    // copy the definitions
!   this->Internal->VarStack.top().Reset(&parent->Internal->VarStack.top());
  
    // copy include paths
***************
*** 1641,1646 ****
  #endif
  
!   this->TemporaryDefinitionKey = name;
!   this->DefinitionStack.back()[this->TemporaryDefinitionKey] = value;
  
  #ifdef CMAKE_BUILD_WITH_CMAKE
--- 1649,1653 ----
  #endif
  
!   this->Internal->VarStack.top().Set(name, value);
  
  #ifdef CMAKE_BUILD_WITH_CMAKE
***************
*** 1648,1652 ****
    if ( vv )
      {
!     vv->VariableAccessed(this->TemporaryDefinitionKey,
                           cmVariableWatch::VARIABLE_MODIFIED_ACCESS,
                           value,
--- 1655,1659 ----
    if ( vv )
      {
!     vv->VariableAccessed(name,
                           cmVariableWatch::VARIABLE_MODIFIED_ACCESS,
                           value,
***************
*** 1697,1701 ****
    this->GetCacheManager()->AddCacheEntry(name, val, doc, type);
    // if there was a definition then remove it
!   this->DefinitionStack.back().erase( DefinitionMap::key_type(name));
  }
  
--- 1704,1708 ----
    this->GetCacheManager()->AddCacheEntry(name, val, doc, type);
    // if there was a definition then remove it
!   this->Internal->VarStack.top().Set(name, 0);
  }
  
***************
*** 1703,1720 ****
  void cmMakefile::AddDefinition(const char* name, bool value)
  {
!   if(value)
!     {
!     this->DefinitionStack.back()
!       .erase( DefinitionMap::key_type(name));
!     this->DefinitionStack.back()
!       .insert(DefinitionMap::value_type(name, "ON"));
!     }
!   else
!     {
!     this->DefinitionStack.back()
!       .erase( DefinitionMap::key_type(name));
!     this->DefinitionStack.back()
!       .insert(DefinitionMap::value_type(name, "OFF"));
!     }
  #ifdef CMAKE_BUILD_WITH_CMAKE
    cmVariableWatch* vv = this->GetVariableWatch();
--- 1710,1714 ----
  void cmMakefile::AddDefinition(const char* name, bool value)
  {
!   this->Internal->VarStack.top().Set(name, value? "ON" : "OFF");
  #ifdef CMAKE_BUILD_WITH_CMAKE
    cmVariableWatch* vv = this->GetVariableWatch();
***************
*** 1746,1750 ****
  void cmMakefile::RemoveDefinition(const char* name)
  {
!   this->DefinitionStack.back().erase(DefinitionMap::key_type(name));
  #ifdef CMAKE_BUILD_WITH_CMAKE
    cmVariableWatch* vv = this->GetVariableWatch();
--- 1740,1744 ----
  void cmMakefile::RemoveDefinition(const char* name)
  {
!   this->Internal->VarStack.top().Set(name, 0);
  #ifdef CMAKE_BUILD_WITH_CMAKE
    cmVariableWatch* vv = this->GetVariableWatch();
***************
*** 2088,2099 ****
  bool cmMakefile::IsDefinitionSet(const char* name) const
  {
!   const char* def = 0;
!   DefinitionMap::const_iterator pos = 
!     this->DefinitionStack.back().find(name);
!   if(pos != this->DefinitionStack.back().end())
!     {
!     def = (*pos).second.c_str();
!     }
!   else
      {
      def = this->GetCacheManager()->GetCacheValue(name);
--- 2082,2087 ----
  bool cmMakefile::IsDefinitionSet(const char* name) const
  {
!   const char* def = this->Internal->VarStack.top().Get(name);
!   if(!def)
      {
      def = this->GetCacheManager()->GetCacheValue(name);
***************
*** 2122,2133 ****
      }
  #endif
!   const char* def = 0;
!   DefinitionMap::const_iterator pos = 
!     this->DefinitionStack.back().find(name);
!   if(pos != this->DefinitionStack.back().end())
!     {
!     def = (*pos).second.c_str();
!     }
!   else
      {
      def = this->GetCacheManager()->GetCacheValue(name);
--- 2110,2115 ----
      }
  #endif
!   const char* def = this->Internal->VarStack.top().Get(name);
!   if(!def)
      {
      def = this->GetCacheManager()->GetCacheValue(name);
***************
*** 2145,2153 ****
        {
        // are unknown access allowed
!       DefinitionMap::const_iterator pos2 =
!         this->DefinitionStack.back()
!         .find("CMAKE_ALLOW_UNKNOWN_VARIABLE_READ_ACCESS");
!       if (pos2 != this->DefinitionStack.back().end() &&
!           cmSystemTools::IsOn((*pos2).second.c_str()))
          {
          vv->VariableAccessed(name,
--- 2127,2133 ----
        {
        // are unknown access allowed
!       const char* allow = this->Internal->VarStack.top()
!         .Get("CMAKE_ALLOW_UNKNOWN_VARIABLE_READ_ACCESS");
!       if(cmSystemTools::IsOn(allow))
          {
          vv->VariableAccessed(name,
***************
*** 2178,2190 ****
  ::GetDefinitions(int cacheonly /* = 0 */) const
  {
!   std::map<cmStdString, int> definitions;
    if ( !cacheonly )
      {
!     DefinitionMap::const_iterator it;
!     for ( it = this->DefinitionStack.back().begin();
!           it != this->DefinitionStack.back().end(); it ++ )
!       {
!       definitions[it->first] = 1;
!       }
      }
    cmCacheManager::CacheIterator cit =
--- 2158,2165 ----
  ::GetDefinitions(int cacheonly /* = 0 */) const
  {
!   std::set<cmStdString> definitions;
    if ( !cacheonly )
      {
!     definitions = this->Internal->VarStack.top().ClosureKeys();
      }
    cmCacheManager::CacheIterator cit =
***************
*** 2192,2204 ****
    for ( cit.Begin(); !cit.IsAtEnd(); cit.Next() )
      {
!     definitions[cit.GetName()] = 1;
      }
  
    std::vector<std::string> res;
  
!   std::map<cmStdString, int>::iterator fit;
    for ( fit = definitions.begin(); fit != definitions.end(); fit ++ )
      {
!     res.push_back(fit->first);
      }
    return res;
--- 2167,2179 ----
    for ( cit.Begin(); !cit.IsAtEnd(); cit.Next() )
      {
!     definitions.insert(cit.GetName());
      }
  
    std::vector<std::string> res;
  
!   std::set<cmStdString>::iterator fit;
    for ( fit = definitions.begin(); fit != definitions.end(); fit ++ )
      {
!     res.push_back(*fit);
      }
    return res;
***************
*** 3388,3404 ****
  void cmMakefile::PushScope()
  {
!   // Get the index of the next stack entry.
!   std::vector<DefinitionMap>::size_type index = this->DefinitionStack.size();
! 
!   // Allocate a new stack entry.
!   this->DefinitionStack.push_back(DefinitionMap());
! 
!   // Copy the previous top to the new top.
!   this->DefinitionStack[index] = this->DefinitionStack[index-1];
  }
  
  void cmMakefile::PopScope()
  {
!   this->DefinitionStack.pop_back();
  }
  
--- 3363,3373 ----
  void cmMakefile::PushScope()
  {
!   cmDefinitions* parent = &this->Internal->VarStack.top();
!   this->Internal->VarStack.push(cmDefinitions(parent));
  }
  
  void cmMakefile::PopScope()
  {
!   this->Internal->VarStack.pop();
  }
  
***************
*** 3410,3440 ****
      }
  
!   // multiple scopes in this directory?
!   if (this->DefinitionStack.size() > 1)
!     {
!     if(varDef)
!       {
!       this->DefinitionStack[this->DefinitionStack.size()-2][var] = varDef;
!       }
!     else
!       {
!       this->DefinitionStack[this->DefinitionStack.size()-2].erase(var);
!       }
!     }
!   // otherwise do the parent (if one exists)
!   else if (this->LocalGenerator->GetParent())
      {
!     cmMakefile *parent = this->LocalGenerator->GetParent()->GetMakefile();
!     if (parent)
!       {
!       if(varDef)
!         {
!         parent->AddDefinition(var,varDef);
!         }
!       else
!         {
!         parent->RemoveDefinition(var);
!         }
!       }
      }
  }
--- 3379,3390 ----
      }
  
!   cmDefinitions& cur = this->Internal->VarStack.top();
!   if(cmDefinitions* up = cur.GetParent())
      {
!     // First localize the definition in the current scope.
!     cur.Get(var);
! 
!     // Now update the definition in the parent scope.
!     up->Set(var, varDef);
      }
  }



More information about the Cmake-commits mailing list