Sfoglia il codice sorgente

Merge topic 'refactor-cmLocalGenerator'

ce167b54 cmMakefile: Handle CMP0014 before configuring the generator.
7baef756 cmLocalGenerator: Assert that there is a parent.
63255342 cmMakefile: Remove redundant variable set.
894961af cmMakefile: Use the state to determine the parent directory.
115e9199 Use new top-level check abstraction.
c5059c90 cmLocalGenerator: Add abstraction to check if top-level.
b17686d2 cmGlobalGenerator: Move some flags from cmLocalGenerator.
ed41a8e7 cmLocalGenerator: Port loops to cmState::Snapshot.
48a9e91b cmState: Add an accessor for Parent snapshot and a validity check.
e7f7c2e2 cmLocalGenerator: Convert two recursive methods to loops.
c5cb3a73 cmLocalGenerator: Get project directories from the cmState.
76b59831 cmLocalGenerator: Initialize state before creating cmMakefile.
34c9ee2e cmLocalGenerator: Require a global generator in the constructor.
3837c483 Tests: Add case for 'ctest' run with bad CTestTestfile
b317b38d cmGlobalBorlandMakefileGenerator: Do not inherit from NMake generator
94867698 Don't use a cmLocalGenerator instance to call static methods.
...
Brad King 10 anni fa
parent
commit
2e4ea0c055
52 ha cambiato i file con 401 aggiunte e 360 eliminazioni
  1. 4 4
      Source/cmCoreTryCompile.cxx
  2. 30 1
      Source/cmCustomCommandGenerator.cxx
  3. 2 3
      Source/cmGlobalBorlandMakefileGenerator.cxx
  4. 1 1
      Source/cmGlobalBorlandMakefileGenerator.h
  5. 8 3
      Source/cmGlobalGenerator.cxx
  6. 7 0
      Source/cmGlobalGenerator.h
  7. 1 2
      Source/cmGlobalGhsMultiGenerator.cxx
  8. 3 4
      Source/cmGlobalJOMMakefileGenerator.cxx
  9. 2 4
      Source/cmGlobalMSYSMakefileGenerator.cxx
  10. 3 4
      Source/cmGlobalMinGWMakefileGenerator.cxx
  11. 3 4
      Source/cmGlobalNMakeMakefileGenerator.cxx
  12. 4 3
      Source/cmGlobalNinjaGenerator.cxx
  13. 3 5
      Source/cmGlobalUnixMakefileGenerator3.cxx
  14. 2 5
      Source/cmGlobalVisualStudio10Generator.cxx
  15. 2 5
      Source/cmGlobalVisualStudio11Generator.cxx
  16. 2 5
      Source/cmGlobalVisualStudio12Generator.cxx
  17. 2 5
      Source/cmGlobalVisualStudio14Generator.cxx
  18. 1 3
      Source/cmGlobalVisualStudio6Generator.cxx
  19. 1 2
      Source/cmGlobalVisualStudio71Generator.cxx
  20. 1 2
      Source/cmGlobalVisualStudio7Generator.cxx
  21. 1 2
      Source/cmGlobalVisualStudio8Generator.cxx
  22. 1 2
      Source/cmGlobalVisualStudio9Generator.cxx
  23. 2 0
      Source/cmGlobalVisualStudioGenerator.cxx
  24. 5 6
      Source/cmGlobalWatcomWMakeGenerator.cxx
  25. 1 3
      Source/cmGlobalXCodeGenerator.cxx
  26. 4 5
      Source/cmIfCommand.cxx
  27. 143 146
      Source/cmLocalGenerator.cxx
  28. 17 16
      Source/cmLocalGenerator.h
  29. 3 2
      Source/cmLocalGhsMultiGenerator.cxx
  30. 1 1
      Source/cmLocalGhsMultiGenerator.h
  31. 5 12
      Source/cmLocalNinjaGenerator.cxx
  32. 1 4
      Source/cmLocalNinjaGenerator.h
  33. 17 16
      Source/cmLocalUnixMakefileGenerator3.cxx
  34. 2 31
      Source/cmLocalUnixMakefileGenerator3.h
  35. 3 2
      Source/cmLocalVisualStudio10Generator.cxx
  36. 2 1
      Source/cmLocalVisualStudio10Generator.h
  37. 3 2
      Source/cmLocalVisualStudio6Generator.cxx
  38. 2 1
      Source/cmLocalVisualStudio6Generator.h
  39. 3 2
      Source/cmLocalVisualStudio7Generator.cxx
  40. 2 1
      Source/cmLocalVisualStudio7Generator.h
  41. 3 4
      Source/cmLocalVisualStudioGenerator.cxx
  42. 2 1
      Source/cmLocalVisualStudioGenerator.h
  43. 3 2
      Source/cmLocalXCodeGenerator.cxx
  44. 1 1
      Source/cmLocalXCodeGenerator.h
  45. 41 20
      Source/cmMakefile.cxx
  46. 2 2
      Source/cmMakefileTargetGenerator.cxx
  47. 1 1
      Source/cmProjectCommand.cxx
  48. 21 0
      Source/cmState.cxx
  49. 3 0
      Source/cmState.h
  50. 7 9
      Source/cmTestGenerator.cxx
  51. 4 0
      Tests/RunCMake/CTestCommandLine/BadCTestTestfile-stderr.txt
  52. 13 0
      Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake

+ 4 - 4
Source/cmCoreTryCompile.cxx

@@ -242,8 +242,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
       }
 
     // Detect languages to enable.
-    cmLocalGenerator* lg = this->Makefile->GetLocalGenerator();
-    cmGlobalGenerator* gg = lg->GetGlobalGenerator();
+    cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
     std::set<std::string> testLangs;
     for(std::vector<std::string>::iterator si = sources.begin();
         si != sources.end(); ++si)
@@ -323,7 +322,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
       std::string langFlags = "CMAKE_" + *li + "_FLAGS";
       const char* flags = this->Makefile->GetDefinition(langFlags);
       fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li->c_str(),
-              lg->EscapeForCMake(flags?flags:"").c_str());
+              cmLocalGenerator::EscapeForCMake(flags?flags:"").c_str());
       fprintf(fout, "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}"
               " ${COMPILE_DEFINITIONS}\")\n", li->c_str(), li->c_str());
       }
@@ -356,7 +355,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
         const char* exeLinkFlags =
           this->Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS");
         fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n",
-                lg->EscapeForCMake(exeLinkFlags?exeLinkFlags:"").c_str());
+                cmLocalGenerator::EscapeForCMake(
+                    exeLinkFlags ? exeLinkFlags : "").c_str());
         } break;
       }
     fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS}"

+ 30 - 1
Source/cmCustomCommandGenerator.cxx

@@ -50,6 +50,35 @@ std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
   return this->GE->Parse(argv0)->Evaluate(this->Makefile, this->Config);
 }
 
+//----------------------------------------------------------------------------
+std::string escapeForShellOldStyle(const std::string& str)
+{
+  std::string result;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  // if there are spaces
+  std::string temp = str;
+  if (temp.find(" ") != std::string::npos &&
+      temp.find("\"")==std::string::npos)
+    {
+    result = "\"";
+    result += str;
+    result += "\"";
+    return result;
+    }
+  return str;
+#else
+  for(const char* ch = str.c_str(); *ch != '\0'; ++ch)
+    {
+    if(*ch == ' ')
+      {
+      result += '\\';
+      }
+    result += *ch;
+    }
+  return result;
+#endif
+}
+
 //----------------------------------------------------------------------------
 void
 cmCustomCommandGenerator
@@ -63,7 +92,7 @@ cmCustomCommandGenerator
     cmd += " ";
     if(this->OldStyle)
       {
-      cmd += this->LG->EscapeForShellOldStyle(arg);
+      cmd += escapeForShellOldStyle(arg);
       }
     else
       {

+ 2 - 3
Source/cmGlobalBorlandMakefileGenerator.cxx

@@ -21,6 +21,7 @@ cmGlobalBorlandMakefileGenerator::cmGlobalBorlandMakefileGenerator()
   this->ForceUnixPaths = false;
   this->ToolSupportsColor = true;
   this->UseLinkScript = false;
+  this->WindowsShell = true;
 }
 
 
@@ -41,13 +42,11 @@ cmLocalGenerator *cmGlobalBorlandMakefileGenerator::CreateLocalGenerator(
     cmLocalGenerator* parent)
 {
   cmLocalUnixMakefileGenerator3* lg =
-      new cmLocalUnixMakefileGenerator3(parent);
+      new cmLocalUnixMakefileGenerator3(this, parent);
   lg->SetIncludeDirective("!include");
-  lg->SetWindowsShell(true);
   lg->SetDefineWindowsNULL(true);
   lg->SetMakefileVariableSize(32);
   lg->SetPassMakeflags(true);
-  lg->SetGlobalGenerator(this);
   lg->SetUnixCD(false);
   lg->SetMakeCommandEscapeTargetTwice(true);
   lg->SetBorlandMakeCurlyHack(true);

+ 1 - 1
Source/cmGlobalBorlandMakefileGenerator.h

@@ -19,7 +19,7 @@
  *
  * cmGlobalBorlandMakefileGenerator manages nmake build process for a tree
  */
-class cmGlobalBorlandMakefileGenerator : public cmGlobalNMakeMakefileGenerator
+class cmGlobalBorlandMakefileGenerator : public cmGlobalUnixMakefileGenerator3
 {
 public:
   cmGlobalBorlandMakefileGenerator();

+ 8 - 3
Source/cmGlobalGenerator.cxx

@@ -71,6 +71,13 @@ cmGlobalGenerator::cmGlobalGenerator()
   this->ExtraGenerator = 0;
   this->CurrentLocalGenerator = 0;
   this->TryCompileOuterMakefile = 0;
+
+  this->WindowsShell = false;
+  this->WindowsVSIDE = false;
+  this->WatcomWMake = false;
+  this->MinGWMake = false;
+  this->NMake = false;
+  this->MSYSShell = false;
 }
 
 cmGlobalGenerator::~cmGlobalGenerator()
@@ -1877,9 +1884,7 @@ void cmGlobalGenerator::EnableInstallTarget()
 cmLocalGenerator *
 cmGlobalGenerator::CreateLocalGenerator(cmLocalGenerator *parent)
 {
-  cmLocalGenerator *lg = new cmLocalGenerator(parent);
-  lg->SetGlobalGenerator(this);
-  return lg;
+  return new cmLocalGenerator(this, parent);
 }
 
 void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen,

+ 7 - 0
Source/cmGlobalGenerator.h

@@ -354,6 +354,13 @@ public:
   cmFileLockPool& GetFileLockPool() { return FileLockPool; }
 #endif
 
+  bool WindowsShell;
+  bool WindowsVSIDE;
+  bool WatcomWMake;
+  bool MinGWMake;
+  bool NMake;
+  bool MSYSShell;
+
 protected:
   virtual void Generate();
 

+ 1 - 2
Source/cmGlobalGhsMultiGenerator.cxx

@@ -35,8 +35,7 @@ cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator()
 cmLocalGenerator *
 cmGlobalGhsMultiGenerator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
-  cmLocalGenerator *lg = new cmLocalGhsMultiGenerator(parent);
-  lg->SetGlobalGenerator(this);
+  cmLocalGenerator *lg = new cmLocalGhsMultiGenerator(this, parent);
   this->SetCurrentLocalGenerator(lg);
   return lg;
 }

+ 3 - 4
Source/cmGlobalJOMMakefileGenerator.cxx

@@ -19,6 +19,8 @@ cmGlobalJOMMakefileGenerator::cmGlobalJOMMakefileGenerator()
   this->ForceUnixPaths = false;
   this->ToolSupportsColor = true;
   this->UseLinkScript = false;
+  this->WindowsShell = true;
+  this->NMake = true;
 }
 
 void cmGlobalJOMMakefileGenerator
@@ -49,14 +51,11 @@ cmLocalGenerator *
 cmGlobalJOMMakefileGenerator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
   cmLocalUnixMakefileGenerator3* lg
-      = new cmLocalUnixMakefileGenerator3(parent);
+      = new cmLocalUnixMakefileGenerator3(this, parent);
   lg->SetDefineWindowsNULL(true);
-  lg->SetWindowsShell(true);
   lg->SetMakeSilentFlag("/nologo");
-  lg->SetGlobalGenerator(this);
   lg->SetIgnoreLibPrefix(true);
   lg->SetPassMakeflags(true);
-  lg->SetNMake(true);
   lg->SetUnixCD(false);
   return lg;
 }

+ 2 - 4
Source/cmGlobalMSYSMakefileGenerator.cxx

@@ -21,6 +21,7 @@ cmGlobalMSYSMakefileGenerator::cmGlobalMSYSMakefileGenerator()
   this->ForceUnixPaths = true;
   this->ToolSupportsColor = true;
   this->UseLinkScript = false;
+  this->MSYSShell = true;
 }
 
 std::string
@@ -97,10 +98,7 @@ cmLocalGenerator *
 cmGlobalMSYSMakefileGenerator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
   cmLocalUnixMakefileGenerator3* lg =
-      new cmLocalUnixMakefileGenerator3(parent);
-  lg->SetWindowsShell(false);
-  lg->SetMSYSShell(true);
-  lg->SetGlobalGenerator(this);
+      new cmLocalUnixMakefileGenerator3(this, parent);
   lg->SetIgnoreLibPrefix(true);
   lg->SetPassMakeflags(false);
   lg->SetUnixCD(true);

+ 3 - 4
Source/cmGlobalMinGWMakefileGenerator.cxx

@@ -19,6 +19,8 @@ cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator()
   this->ForceUnixPaths = true;
   this->ToolSupportsColor = true;
   this->UseLinkScript = true;
+  this->WindowsShell = true;
+  this->MinGWMake = true;
 }
 
 void cmGlobalMinGWMakefileGenerator
@@ -61,13 +63,10 @@ cmLocalGenerator *
 cmGlobalMinGWMakefileGenerator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
   cmLocalUnixMakefileGenerator3* lg =
-      new cmLocalUnixMakefileGenerator3(parent);
-  lg->SetWindowsShell(true);
-  lg->SetGlobalGenerator(this);
+      new cmLocalUnixMakefileGenerator3(this, parent);
   lg->SetIgnoreLibPrefix(true);
   lg->SetPassMakeflags(false);
   lg->SetUnixCD(true);
-  lg->SetMinGWMake(true);
   return lg;
 }
 

+ 3 - 4
Source/cmGlobalNMakeMakefileGenerator.cxx

@@ -19,6 +19,8 @@ cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator()
   this->ForceUnixPaths = false;
   this->ToolSupportsColor = true;
   this->UseLinkScript = false;
+  this->WindowsShell = true;
+  this->NMake = true;
 }
 
 void cmGlobalNMakeMakefileGenerator
@@ -49,14 +51,11 @@ cmLocalGenerator *
 cmGlobalNMakeMakefileGenerator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
   cmLocalUnixMakefileGenerator3* lg =
-      new cmLocalUnixMakefileGenerator3(parent);
+      new cmLocalUnixMakefileGenerator3(this, parent);
   lg->SetDefineWindowsNULL(true);
-  lg->SetWindowsShell(true);
   lg->SetMakeSilentFlag("/nologo");
-  lg->SetGlobalGenerator(this);
   lg->SetIgnoreLibPrefix(true);
   lg->SetPassMakeflags(true);
-  lg->SetNMake(true);
   lg->SetUnixCD(false);
   return lg;
 }

+ 4 - 3
Source/cmGlobalNinjaGenerator.cxx

@@ -488,6 +488,9 @@ cmGlobalNinjaGenerator::cmGlobalNinjaGenerator()
   , ComputingUnknownDependencies(false)
   , PolicyCMP0058(cmPolicies::WARN)
 {
+#ifdef _WIN32
+  this->WindowsShell = true;
+#endif
   // // Ninja is not ported to non-Unix OS yet.
   // this->ForceUnixPaths = true;
   this->FindMakeProgramFile = "CMakeNinjaFindMake.cmake";
@@ -500,9 +503,7 @@ cmGlobalNinjaGenerator::cmGlobalNinjaGenerator()
 cmLocalGenerator*
 cmGlobalNinjaGenerator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
-  cmLocalGenerator* lg = new cmLocalNinjaGenerator(parent);
-  lg->SetGlobalGenerator(this);
-  return lg;
+  return new cmLocalNinjaGenerator(this, parent);
 }
 
 void cmGlobalNinjaGenerator

+ 3 - 5
Source/cmGlobalUnixMakefileGenerator3.cxx

@@ -56,9 +56,7 @@ void cmGlobalUnixMakefileGenerator3
 cmLocalGenerator *
 cmGlobalUnixMakefileGenerator3::CreateLocalGenerator(cmLocalGenerator* parent)
 {
-  cmLocalGenerator* lg = new cmLocalUnixMakefileGenerator3(parent);
-  lg->SetGlobalGenerator(this);
-  return lg;
+  return new cmLocalUnixMakefileGenerator3(this, parent);
 }
 
 //----------------------------------------------------------------------------
@@ -524,7 +522,7 @@ cmGlobalUnixMakefileGenerator3
                        cmLocalUnixMakefileGenerator3* lg)
 {
   // Only subdirectories need these rules.
-  if(!lg->GetParent())
+  if(lg->IsRootMakefile())
     {
     return;
     }
@@ -1029,7 +1027,7 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule
       static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
     // for the passed in makefile or if this is the top Makefile wripte out
     // the targets
-    if (lg2 == lg || !lg->GetParent())
+    if (lg2 == lg || lg->IsRootMakefile())
       {
       // for each target Generate the rule files for each target.
       cmTargets& targets = lg2->GetMakefile()->GetTargets();

+ 2 - 5
Source/cmGlobalVisualStudio10Generator.cxx

@@ -311,11 +311,8 @@ void cmGlobalVisualStudio10Generator::WriteSLNHeader(std::ostream& fout)
 cmLocalGenerator *
 cmGlobalVisualStudio10Generator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
-  cmLocalVisualStudio10Generator* lg =
-    new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS10,
-                                       parent);
-  lg->SetGlobalGenerator(this);
-  return lg;
+  return new cmLocalVisualStudio10Generator(
+    cmLocalVisualStudioGenerator::VS10, this, parent);
 }
 
 //----------------------------------------------------------------------------

+ 2 - 5
Source/cmGlobalVisualStudio11Generator.cxx

@@ -240,11 +240,8 @@ void cmGlobalVisualStudio11Generator::WriteSLNHeader(std::ostream& fout)
 cmLocalGenerator *
 cmGlobalVisualStudio11Generator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
-  cmLocalVisualStudio10Generator* lg =
-    new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS11,
-                                       parent);
-  lg->SetGlobalGenerator(this);
-  return lg;
+  return new cmLocalVisualStudio10Generator(
+    cmLocalVisualStudioGenerator::VS11, this, parent);
 }
 
 //----------------------------------------------------------------------------

+ 2 - 5
Source/cmGlobalVisualStudio12Generator.cxx

@@ -220,11 +220,8 @@ void cmGlobalVisualStudio12Generator::WriteSLNHeader(std::ostream& fout)
 cmLocalGenerator *
 cmGlobalVisualStudio12Generator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
-  cmLocalVisualStudio10Generator* lg =
-    new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS12,
-                                       parent);
-  lg->SetGlobalGenerator(this);
-  return lg;
+  return new cmLocalVisualStudio10Generator(
+    cmLocalVisualStudioGenerator::VS12, this, parent);
 }
 
 //----------------------------------------------------------------------------

+ 2 - 5
Source/cmGlobalVisualStudio14Generator.cxx

@@ -131,9 +131,6 @@ void cmGlobalVisualStudio14Generator::WriteSLNHeader(std::ostream& fout)
 cmLocalGenerator *
 cmGlobalVisualStudio14Generator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
-  cmLocalVisualStudio10Generator* lg =
-    new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS14,
-                                       parent);
-  lg->SetGlobalGenerator(this);
-  return lg;
+  return new cmLocalVisualStudio10Generator(
+    cmLocalVisualStudioGenerator::VS14, this, parent);
 }

+ 1 - 3
Source/cmGlobalVisualStudio6Generator.cxx

@@ -173,9 +173,7 @@ cmGlobalVisualStudio6Generator::GenerateBuildCommand(
 cmLocalGenerator *
 cmGlobalVisualStudio6Generator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
-  cmLocalGenerator *lg = new cmLocalVisualStudio6Generator(parent);
-  lg->SetGlobalGenerator(this);
-  return lg;
+  return new cmLocalVisualStudio6Generator(this, parent);
 }
 
 

+ 1 - 2
Source/cmGlobalVisualStudio71Generator.cxx

@@ -30,9 +30,8 @@ cmGlobalVisualStudio71Generator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
   cmLocalVisualStudio7Generator *lg =
     new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS71,
-                                      parent);
+                                      this, parent);
   lg->SetExtraFlagTable(this->GetExtraFlagTableVS7());
-  lg->SetGlobalGenerator(this);
   return lg;
 }
 

+ 1 - 2
Source/cmGlobalVisualStudio7Generator.cxx

@@ -255,9 +255,8 @@ cmGlobalVisualStudio7Generator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
   cmLocalVisualStudio7Generator *lg =
     new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS7,
-                                      parent);
+                                      this, parent);
   lg->SetExtraFlagTable(this->GetExtraFlagTableVS7());
-  lg->SetGlobalGenerator(this);
   return lg;
 }
 

+ 1 - 2
Source/cmGlobalVisualStudio8Generator.cxx

@@ -130,9 +130,8 @@ cmGlobalVisualStudio8Generator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
   cmLocalVisualStudio7Generator *lg =
     new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS8,
-                                      parent);
+                                      this, parent);
   lg->SetExtraFlagTable(this->GetExtraFlagTableVS8());
-  lg->SetGlobalGenerator(this);
   return lg;
 }
 

+ 1 - 2
Source/cmGlobalVisualStudio9Generator.cxx

@@ -119,9 +119,8 @@ cmGlobalVisualStudio9Generator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
   cmLocalVisualStudio7Generator *lg
     = new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS9,
-                                        parent);
+                                        this, parent);
   lg->SetExtraFlagTable(this->GetExtraFlagTableVS8());
-  lg->SetGlobalGenerator(this);
   return lg;
 }
 

+ 2 - 0
Source/cmGlobalVisualStudioGenerator.cxx

@@ -23,6 +23,8 @@
 //----------------------------------------------------------------------------
 cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator()
 {
+  this->WindowsShell = true;
+  this->WindowsVSIDE = true;
 }
 
 //----------------------------------------------------------------------------

+ 5 - 6
Source/cmGlobalWatcomWMakeGenerator.cxx

@@ -22,6 +22,10 @@ cmGlobalWatcomWMakeGenerator::cmGlobalWatcomWMakeGenerator()
   this->ToolSupportsColor = true;
   this->NeedSymbolicMark = true;
   this->EmptyRuleHackCommand = "@cd .";
+#ifdef _WIN32
+  this->WindowsShell = true;
+#endif
+  this->WatcomWMake = true;
 }
 
 void cmGlobalWatcomWMakeGenerator
@@ -45,14 +49,9 @@ cmLocalGenerator *
 cmGlobalWatcomWMakeGenerator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
   cmLocalUnixMakefileGenerator3* lg
-      = new cmLocalUnixMakefileGenerator3(parent);
+      = new cmLocalUnixMakefileGenerator3(this, parent);
   lg->SetDefineWindowsNULL(true);
-#ifdef _WIN32
-  lg->SetWindowsShell(true);
-#endif
-  lg->SetWatcomWMake(true);
   lg->SetMakeSilentFlag("-h");
-  lg->SetGlobalGenerator(this);
   lg->SetIgnoreLibPrefix(true);
   lg->SetPassMakeflags(false);
   lg->SetUnixCD(false);

+ 1 - 3
Source/cmGlobalXCodeGenerator.cxx

@@ -371,9 +371,7 @@ cmGlobalXCodeGenerator::GenerateBuildCommand(
 cmLocalGenerator *
 cmGlobalXCodeGenerator::CreateLocalGenerator(cmLocalGenerator* parent)
 {
-  cmLocalGenerator *lg = new cmLocalXCodeGenerator(parent);
-  lg->SetGlobalGenerator(this);
-  return lg;
+  return new cmLocalXCodeGenerator(this, parent);
 }
 
 //----------------------------------------------------------------------------

+ 4 - 5
Source/cmIfCommand.cxx

@@ -20,15 +20,14 @@
 
 
 static std::string cmIfCommandError(
-  cmMakefile* mf, std::vector<cmExpandedCommandArgument> const& args)
+  std::vector<cmExpandedCommandArgument> const& args)
 {
-  cmLocalGenerator* lg = mf->GetLocalGenerator();
   std::string err = "given arguments:\n ";
   for(std::vector<cmExpandedCommandArgument>::const_iterator i = args.begin();
       i != args.end(); ++i)
     {
     err += " ";
-    err += lg->EscapeForCMake(i->GetValue());
+    err += cmLocalGenerator::EscapeForCMake(i->GetValue());
     }
   err += "\n";
   return err;
@@ -118,7 +117,7 @@ IsFunctionBlocked(const cmListFileFunction& lff,
 
             if (!errorString.empty())
               {
-              std::string err = cmIfCommandError(&mf, expandedArguments);
+              std::string err = cmIfCommandError(expandedArguments);
               err += errorString;
               mf.IssueMessage(messType, err);
               if (messType == cmake::FATAL_ERROR)
@@ -206,7 +205,7 @@ bool cmIfCommand
 
   if (!errorString.empty())
     {
-    std::string err = cmIfCommandError(this->Makefile, expandedArguments);
+    std::string err = cmIfCommandError(expandedArguments);
     err += errorString;
     if (status == cmake::FATAL_ERROR)
       {

+ 143 - 146
Source/cmLocalGenerator.cxx

@@ -43,20 +43,24 @@
 #include <StorageDefs.h>
 #endif
 
-cmLocalGenerator::cmLocalGenerator(cmLocalGenerator* parent)
+cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg,
+                                   cmLocalGenerator* parent)
 {
-  this->Makefile = 0; // moved to after set on global
+  this->GlobalGenerator = gg;
   this->Parent = parent;
   if (parent)
     {
     parent->AddChild(this);
+    this->StateSnapshot =
+        this->GetState()->CreateSnapshot(parent->StateSnapshot);
+    }
+  else
+    {
+    this->StateSnapshot =
+        this->GetState()->CreateSnapshot(cmState::Snapshot(this->GetState()));
     }
-  this->WindowsShell = false;
-  this->WindowsVSIDE = false;
-  this->WatcomWMake = false;
-  this->MinGWMake = false;
-  this->NMake = false;
-  this->MSYSShell = false;
+  this->Makefile = new cmMakefile(this);
+
   this->LinkScriptShell = false;
   this->IgnoreLibPrefix = false;
   this->UseRelativePaths = false;
@@ -73,6 +77,11 @@ cmLocalGenerator::~cmLocalGenerator()
   delete this->Makefile;
 }
 
+bool cmLocalGenerator::IsRootMakefile() const
+{
+  return !this->GetParent();
+}
+
 //----------------------------------------------------------------------------
 class cmLocalGeneratorCurrent
 {
@@ -105,7 +114,7 @@ void cmLocalGenerator::Configure()
   static_cast<void>(clg);
 
   // make sure the CMakeFiles dir is there
-  std::string filesDir = this->Makefile->GetCurrentBinaryDirectory();
+  std::string filesDir = this->StateSnapshot.GetCurrentBinaryDirectory();
   filesDir += cmake::GetCMakeFilesDirectory();
   cmSystemTools::MakeDirectory(filesDir.c_str());
 
@@ -181,48 +190,10 @@ void cmLocalGenerator::ComputeObjectMaxPath()
 void cmLocalGenerator::ReadInputFile()
 {
   // Look for the CMakeLists.txt file.
-  std::string currentStart = this->Makefile->GetCurrentSourceDirectory();
+  std::string currentStart = this->StateSnapshot.GetCurrentSourceDirectory();
   currentStart += "/CMakeLists.txt";
-  if(cmSystemTools::FileExists(currentStart.c_str(), true))
-    {
-    this->Makefile->ProcessBuildsystemFile(currentStart.c_str());
-    return;
-    }
-
-  if(!this->Parent)
-    {
-    return;
-    }
-
-  // The file is missing.  Check policy CMP0014.
-  cmMakefile* mf = this->Parent->GetMakefile();
-  std::ostringstream e;
-  e << "The source directory\n"
-    << "  " << this->Makefile->GetCurrentSourceDirectory() << "\n"
-    << "does not contain a CMakeLists.txt file.";
-  switch (mf->GetPolicyStatus(cmPolicies::CMP0014))
-    {
-    case cmPolicies::WARN:
-      // Print the warning.
-      e << "\n"
-        << "CMake does not support this case but it used "
-        << "to work accidentally and is being allowed for "
-        << "compatibility."
-        << "\n"
-        << cmPolicies::GetPolicyWarning(cmPolicies::CMP0014);
-      mf->IssueMessage(cmake::AUTHOR_WARNING, e.str());
-    case cmPolicies::OLD:
-      // OLD behavior does not warn.
-      return;
-    case cmPolicies::REQUIRED_IF_USED:
-    case cmPolicies::REQUIRED_ALWAYS:
-      e << "\n"
-        << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0014);
-    case cmPolicies::NEW:
-      // NEW behavior prints the error.
-      mf->IssueMessage(cmake::FATAL_ERROR, e.str());
-      break;
-    }
+  assert(cmSystemTools::FileExists(currentStart.c_str(), true));
+  this->Makefile->ProcessBuildsystemFile(currentStart.c_str());
 }
 
 void cmLocalGenerator::SetupPathConversions()
@@ -231,31 +202,23 @@ void cmLocalGenerator::SetupPathConversions()
   // Convert
   std::string outdir;
   outdir =
-    cmSystemTools::CollapseFullPath(this->Makefile->GetHomeDirectory());
+    cmSystemTools::CollapseFullPath(this->GetState()->GetSourceDirectory());
   cmSystemTools::SplitPath(outdir, this->HomeDirectoryComponents);
-  outdir =
-    cmSystemTools::CollapseFullPath(
-                                this->Makefile->GetCurrentSourceDirectory());
+  outdir = cmSystemTools::CollapseFullPath(
+      this->StateSnapshot.GetCurrentSourceDirectory());
   cmSystemTools::SplitPath(outdir, this->StartDirectoryComponents);
 
   outdir = cmSystemTools::CollapseFullPath
-    (this->Makefile->GetHomeOutputDirectory());
+    (this->GetState()->GetBinaryDirectory());
   cmSystemTools::SplitPath(outdir,
                            this->HomeOutputDirectoryComponents);
 
   outdir = cmSystemTools::CollapseFullPath
-    (this->Makefile->GetCurrentBinaryDirectory());
+    (this->StateSnapshot.GetCurrentBinaryDirectory());
   cmSystemTools::SplitPath(outdir,
                            this->StartOutputDirectoryComponents);
 }
 
-
-void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg)
-{
-  this->GlobalGenerator = gg;
-  this->Makefile = new cmMakefile(this);
-}
-
 void cmLocalGenerator::ConfigureFinalPass()
 {
   this->Makefile->ConfigureFinalPass();
@@ -300,7 +263,7 @@ void cmLocalGenerator::GenerateTestFiles()
   const std::string& config =
     this->Makefile->GetConfigurations(configurationTypes, false);
 
-  std::string file = this->Makefile->GetCurrentBinaryDirectory();
+  std::string file = this->StateSnapshot.GetCurrentBinaryDirectory();
   file += "/";
   file += "CTestTestfile.cmake";
 
@@ -309,9 +272,9 @@ void cmLocalGenerator::GenerateTestFiles()
 
   fout << "# CMake generated Testfile for " << std::endl
        << "# Source directory: "
-       << this->Makefile->GetCurrentSourceDirectory() << std::endl
+       << this->StateSnapshot.GetCurrentSourceDirectory() << std::endl
        << "# Build directory: "
-       << this->Makefile->GetCurrentBinaryDirectory() << std::endl
+       << this->StateSnapshot.GetCurrentBinaryDirectory() << std::endl
        << "# " << std::endl
        << "# This file includes the relevant testing commands "
        << "required for " << std::endl
@@ -425,9 +388,9 @@ void cmLocalGenerator::GenerateInstallRules()
     }
 
   // Create the install script file.
-  std::string file = this->Makefile->GetCurrentBinaryDirectory();
-  std::string homedir = this->Makefile->GetHomeOutputDirectory();
-  std::string currdir = this->Makefile->GetCurrentBinaryDirectory();
+  std::string file = this->StateSnapshot.GetCurrentBinaryDirectory();
+  std::string homedir = this->GetState()->GetBinaryDirectory();
+  std::string currdir = this->StateSnapshot.GetCurrentBinaryDirectory();
   cmSystemTools::ConvertToUnixSlashes(file);
   cmSystemTools::ConvertToUnixSlashes(homedir);
   cmSystemTools::ConvertToUnixSlashes(currdir);
@@ -442,7 +405,7 @@ void cmLocalGenerator::GenerateInstallRules()
 
   // Write the header.
   fout << "# Install script for directory: "
-       << this->Makefile->GetCurrentSourceDirectory()
+       << this->StateSnapshot.GetCurrentSourceDirectory()
        << std::endl << std::endl;
   fout << "# Set the install prefix" << std::endl
        << "if(NOT DEFINED CMAKE_INSTALL_PREFIX)" << std::endl
@@ -577,6 +540,16 @@ void cmLocalGenerator::GenerateTargetManifest()
     }
 }
 
+cmState* cmLocalGenerator::GetState() const
+{
+  return this->GlobalGenerator->GetCMakeInstance()->GetState();
+}
+
+cmState::Snapshot cmLocalGenerator::GetStateSnapshot() const
+{
+  return this->StateSnapshot;
+}
+
 void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname,
                                                     const std::string& lang,
                                                     cmSourceFile& source,
@@ -651,7 +624,7 @@ void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname,
     source.GetFullPath(),
     commandLines,
     comment.c_str(),
-    this->Makefile->GetCurrentBinaryDirectory()
+    this->StateSnapshot.GetCurrentBinaryDirectory()
     );
 }
 
@@ -673,12 +646,12 @@ void cmLocalGenerator::AddBuildTargetRule(const std::string& llang,
        !sf->GetPropertyAsBool("EXTERNAL_OBJECT"))
       {
       std::string dir_max;
-      dir_max += this->Makefile->GetCurrentBinaryDirectory();
+      dir_max += this->StateSnapshot.GetCurrentBinaryDirectory();
       dir_max += "/";
       std::string obj = this->GetObjectFileNameWithoutTarget(*sf, dir_max);
       if(!obj.empty())
         {
-        std::string ofname = this->Makefile->GetCurrentBinaryDirectory();
+        std::string ofname = this->StateSnapshot.GetCurrentBinaryDirectory();
         ofname += "/";
         ofname += obj;
         objVector.push_back(ofname);
@@ -748,7 +721,7 @@ void cmLocalGenerator::AddBuildTargetRule(const std::string& llang,
     "",
     commandLines,
     comment.c_str(),
-    this->Makefile->GetCurrentBinaryDirectory()
+    this->StateSnapshot.GetCurrentBinaryDirectory()
     );
   this->Makefile->GetSource(targetFullPath);
   target.Target->AddSource(targetFullPath);
@@ -1242,7 +1215,7 @@ cmLocalGenerator::ConvertToOutputForExistingCommon(const std::string& remote,
   // If this is a windows shell, the result has a space, and the path
   // already exists, we can use a short-path to reference it without a
   // space.
-  if(this->WindowsShell && result.find(' ') != result.npos &&
+  if(this->GlobalGenerator->WindowsShell && result.find(' ') != result.npos &&
      cmSystemTools::FileExists(remote.c_str()))
     {
     std::string tmp;
@@ -1552,19 +1525,19 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
   if(includeBinaryDir)
     {
     if(emitted.find(
-                this->Makefile->GetCurrentBinaryDirectory()) == emitted.end())
+        this->StateSnapshot.GetCurrentBinaryDirectory()) == emitted.end())
       {
-      dirs.push_back(this->Makefile->GetCurrentBinaryDirectory());
-      emitted.insert(this->Makefile->GetCurrentBinaryDirectory());
+      dirs.push_back(this->StateSnapshot.GetCurrentBinaryDirectory());
+      emitted.insert(this->StateSnapshot.GetCurrentBinaryDirectory());
       }
     }
   if(includeSourceDir)
     {
     if(emitted.find(
-                this->Makefile->GetCurrentSourceDirectory()) == emitted.end())
+        this->StateSnapshot.GetCurrentSourceDirectory()) == emitted.end())
       {
-      dirs.push_back(this->Makefile->GetCurrentSourceDirectory());
-      emitted.insert(this->Makefile->GetCurrentSourceDirectory());
+      dirs.push_back(this->StateSnapshot.GetCurrentSourceDirectory());
+      emitted.insert(this->StateSnapshot.GetCurrentSourceDirectory());
       }
     }
 
@@ -1606,8 +1579,8 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
   // it is requested by the project.
   if(this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"))
     {
-    const char* topSourceDir = this->Makefile->GetHomeDirectory();
-    const char* topBinaryDir = this->Makefile->GetHomeOutputDirectory();
+    const char* topSourceDir = this->GetState()->GetSourceDirectory();
+    const char* topBinaryDir = this->GetState()->GetBinaryDirectory();
     for(std::vector<std::string>::const_iterator i = includes.begin();
         i != includes.end(); ++i)
       {
@@ -2165,7 +2138,7 @@ bool cmLocalGenerator::GetRealDependency(const std::string& inName,
 
   // Treat the name as relative to the source directory in which it
   // was given.
-  dep = this->Makefile->GetCurrentSourceDirectory();
+  dep = this->StateSnapshot.GetCurrentSourceDirectory();
   dep += "/";
   dep += inName;
   return true;
@@ -2614,7 +2587,7 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines,
     {
     // Append the definition with proper escaping.
     std::string def = dflag;
-    if(this->WatcomWMake)
+    if(this->GlobalGenerator->WatcomWMake)
       {
       // The Watcom compiler does its own command line parsing instead
       // of using the windows shell rules.  Definitions are one of
@@ -2717,10 +2690,10 @@ const char* cmLocalGenerator::GetRelativeRootPath(RelativeRoot relroot)
 {
   switch (relroot)
     {
-    case HOME:         return this->Makefile->GetHomeDirectory();
-    case START:        return this->Makefile->GetCurrentSourceDirectory();
-    case HOME_OUTPUT:  return this->Makefile->GetHomeOutputDirectory();
-    case START_OUTPUT: return this->Makefile->GetCurrentBinaryDirectory();
+    case HOME:         return this->GetState()->GetSourceDirectory();
+    case START:        return this->StateSnapshot.GetCurrentSourceDirectory();
+    case HOME_OUTPUT:  return this->GetState()->GetBinaryDirectory();
+    case START_OUTPUT: return this->StateSnapshot.GetCurrentBinaryDirectory();
     default: break;
     }
   return 0;
@@ -2793,7 +2766,7 @@ std::string cmLocalGenerator::ConvertToOutputFormat(const std::string& source,
         // For the MSYS shell convert drive letters to posix paths, so
     // that c:/some/path becomes /c/some/path.  This is needed to
     // avoid problems with the shell path translation.
-    if(this->MSYSShell && !this->LinkScriptShell)
+    if(this->GlobalGenerator->MSYSShell && !this->LinkScriptShell)
       {
       if(result.size() > 2 && result[1] == ':')
         {
@@ -2801,7 +2774,7 @@ std::string cmLocalGenerator::ConvertToOutputFormat(const std::string& source,
         result[0] = '/';
         }
       }
-    if(this->WindowsShell)
+    if(this->GlobalGenerator->WindowsShell)
       {
       std::replace(result.begin(), result.end(), '/', '\\');
       }
@@ -2841,41 +2814,69 @@ std::string cmLocalGenerator::Convert(RelativeRoot remote,
 //----------------------------------------------------------------------------
 std::string cmLocalGenerator::FindRelativePathTopSource()
 {
-  // Relative path conversion within a single tree managed by CMake is
-  // safe.  We can use our parent relative path top if and only if
-  // this is a subdirectory of that top.
-  if(cmLocalGenerator* parent = this->GetParent())
+  cmState::Snapshot snapshot = this->StateSnapshot;
+  std::vector<cmState::Snapshot> snapshots;
+  snapshots.push_back(snapshot);
+  while (true)
     {
-    std::string parentTop = parent->FindRelativePathTopSource();
-    if(cmSystemTools::IsSubDirectory(
-         this->Makefile->GetCurrentSourceDirectory(), parentTop))
+    snapshot = snapshot.GetParent();
+    if (snapshot.IsValid())
+      {
+      snapshots.push_back(snapshot);
+      }
+    else
+      {
+      break;
+      }
+    }
+
+  std::string result = snapshots.front().GetCurrentSourceDirectory();
+
+  for (std::vector<cmState::Snapshot>::const_iterator it =
+       snapshots.begin() + 1; it != snapshots.end(); ++it)
+  {
+    std::string currentSource = it->GetCurrentSourceDirectory();
+    if(cmSystemTools::IsSubDirectory(result, currentSource))
       {
-      return parentTop;
+      result = currentSource;
       }
     }
 
-  // Otherwise this directory itself is the new top.
-  return this->Makefile->GetCurrentSourceDirectory();
+  return result;
 }
 
 //----------------------------------------------------------------------------
 std::string cmLocalGenerator::FindRelativePathTopBinary()
 {
-  // Relative path conversion within a single tree managed by CMake is
-  // safe.  We can use our parent relative path top if and only if
-  // this is a subdirectory of that top.
-  if(cmLocalGenerator* parent = this->GetParent())
+  cmState::Snapshot snapshot = this->StateSnapshot;
+  std::vector<cmState::Snapshot> snapshots;
+  snapshots.push_back(snapshot);
+  while (true)
     {
-    std::string parentTop = parent->FindRelativePathTopBinary();
-    if(cmSystemTools::IsSubDirectory(
-         this->Makefile->GetCurrentBinaryDirectory(), parentTop))
+    snapshot = snapshot.GetParent();
+    if (snapshot.IsValid())
+      {
+      snapshots.push_back(snapshot);
+      }
+    else
+      {
+      break;
+      }
+    }
+
+  std::string result = snapshots.front().GetCurrentBinaryDirectory();
+
+  for (std::vector<cmState::Snapshot>::const_iterator it =
+       snapshots.begin() + 1; it != snapshots.end(); ++it)
+  {
+    std::string currentBinary = it->GetCurrentBinaryDirectory();
+    if(cmSystemTools::IsSubDirectory(result, currentBinary))
       {
-      return parentTop;
+      result = currentBinary;
       }
     }
 
-  // Otherwise this directory itself is the new top.
-  return this->Makefile->GetCurrentBinaryDirectory();
+  return result;
 }
 
 //----------------------------------------------------------------------------
@@ -3284,6 +3285,31 @@ void cmLocalGenerator::ComputeObjectFilenames(
 
 }
 
+bool cmLocalGenerator::IsWindowsShell() const
+{
+  return this->GlobalGenerator->WindowsShell;
+}
+
+bool cmLocalGenerator::IsWatcomWMake() const
+{
+  return this->GlobalGenerator->WatcomWMake;
+}
+
+bool cmLocalGenerator::IsMinGWMake() const
+{
+  return this->GlobalGenerator->MinGWMake;
+}
+
+bool cmLocalGenerator::IsNMake() const
+{
+  return this->GlobalGenerator->NMake;
+}
+
+void cmLocalGenerator::SetConfiguredCMP0014(bool configured)
+{
+  this->Configured = configured;
+}
+
 //----------------------------------------------------------------------------
 std::string
 cmLocalGenerator
@@ -3391,35 +3417,6 @@ cmLocalGenerator
   return source.GetLanguage();
 }
 
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::EscapeForShellOldStyle(const std::string& str)
-{
-  std::string result;
-#if defined(_WIN32) && !defined(__CYGWIN__)
-  // if there are spaces
-  std::string temp = str;
-  if (temp.find(" ") != std::string::npos &&
-      temp.find("\"")==std::string::npos)
-    {
-    result = "\"";
-    result += str;
-    result += "\"";
-    return result;
-    }
-  return str;
-#else
-  for(const char* ch = str.c_str(); *ch != '\0'; ++ch)
-    {
-    if(*ch == ' ')
-      {
-      result += '\\';
-      }
-    result += *ch;
-    }
-  return result;
-#endif
-}
-
 //----------------------------------------------------------------------------
 static bool cmLocalGeneratorIsShellOperator(const std::string& str)
 {
@@ -3456,7 +3453,7 @@ std::string cmLocalGenerator::EscapeForShell(const std::string& str,
 
   // Compute the flags for the target shell environment.
   int flags = 0;
-  if(this->WindowsVSIDE)
+  if(this->GlobalGenerator->WindowsVSIDE)
     {
     flags |= cmsysSystem_Shell_Flag_VSIDE;
     }
@@ -3476,27 +3473,27 @@ std::string cmLocalGenerator::EscapeForShell(const std::string& str,
     {
     flags |= cmsysSystem_Shell_Flag_WatcomQuote;
     }
-  if(this->WatcomWMake)
+  if(this->GlobalGenerator->WatcomWMake)
     {
     flags |= cmsysSystem_Shell_Flag_WatcomWMake;
     }
-  if(this->MinGWMake)
+  if(this->GlobalGenerator->MinGWMake)
     {
     flags |= cmsysSystem_Shell_Flag_MinGWMake;
     }
-  if(this->NMake)
+  if(this->GlobalGenerator->NMake)
     {
     flags |= cmsysSystem_Shell_Flag_NMake;
     }
 
   // Compute the buffer size needed.
-  int size = (this->WindowsShell ?
+  int size = (this->GlobalGenerator->WindowsShell ?
               cmsysSystem_Shell_GetArgumentSizeForWindows(str.c_str(), flags) :
               cmsysSystem_Shell_GetArgumentSizeForUnix(str.c_str(), flags));
 
   // Compute the shell argument itself.
   std::vector<char> arg(size);
-  if(this->WindowsShell)
+  if(this->GlobalGenerator->WindowsShell)
     {
     cmsysSystem_Shell_GetArgumentForWindows(str.c_str(), &arg[0], flags);
     }

+ 17 - 16
Source/cmLocalGenerator.h

@@ -13,6 +13,7 @@
 #define cmLocalGenerator_h
 
 #include "cmStandardIncludes.h"
+#include "cmState.h"
 
 class cmMakefile;
 class cmGlobalGenerator;
@@ -33,9 +34,12 @@ class cmCustomCommandGenerator;
 class cmLocalGenerator
 {
 public:
-  cmLocalGenerator(cmLocalGenerator* parent);
+  cmLocalGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent);
   virtual ~cmLocalGenerator();
 
+  /// @return whether we are processing the top CMakeLists.txt file.
+  bool IsRootMakefile() const;
+
   /**
    * Generate the makefile for this directory.
    */
@@ -88,8 +92,8 @@ public:
   const cmGlobalGenerator *GetGlobalGenerator() const {
     return this->GlobalGenerator; }
 
-  ///! Set the Global Generator, done on creation by the GlobalGenerator
-  void SetGlobalGenerator(cmGlobalGenerator *gg);
+  cmState* GetState() const;
+  cmState::Snapshot GetStateSnapshot() const;
 
   /**
    * Convert something to something else. This is a centralized conversion
@@ -298,9 +302,6 @@ public:
                              bool forEcho = false,
                              bool useWatcomQuote = false);
 
-  /** Backwards-compatibility version of EscapeForShell.  */
-  std::string EscapeForShellOldStyle(const std::string& str);
-
   /** Escape the given string as an argument in a CMake script.  */
   static std::string EscapeForCMake(const std::string& str);
 
@@ -385,6 +386,13 @@ public:
                         std::map<cmSourceFile const*, std::string>& mapping,
                         cmGeneratorTarget const* gt = 0);
 
+  bool IsWindowsShell() const;
+  bool IsWatcomWMake() const;
+  bool IsMinGWMake() const;
+  bool IsNMake() const;
+
+  void SetConfiguredCMP0014(bool configured);
+
 protected:
   ///! put all the libraries for a target on into the given stream
   virtual void OutputLinkLibraries(std::string& linkLibraries,
@@ -448,10 +456,8 @@ protected:
   void ReadInputFile();
 
   cmMakefile *Makefile;
+  cmState::Snapshot StateSnapshot;
   cmGlobalGenerator *GlobalGenerator;
-  // members used for relative path function ConvertToMakefilePath
-  std::string RelativePathToSourceDir;
-  std::string RelativePathToBinaryDir;
   std::vector<std::string> HomeDirectoryComponents;
   std::vector<std::string> StartDirectoryComponents;
   std::vector<std::string> HomeOutputDirectoryComponents;
@@ -461,18 +467,13 @@ protected:
   std::map<std::string, std::string> UniqueObjectNamesMap;
   std::string::size_type ObjectPathMax;
   std::set<std::string> ObjectMaxPathViolations;
-  bool WindowsShell;
-  bool WindowsVSIDE;
-  bool WatcomWMake;
-  bool MinGWMake;
-  bool NMake;
-  bool ForceUnixPath;
-  bool MSYSShell;
+
   bool LinkScriptShell;
   bool UseRelativePaths;
   bool IgnoreLibPrefix;
   bool Configured;
   bool EmitUniversalBinaryFlags;
+
   // Hack for ExpandRuleVariable until object-oriented version is
   // committed.
   std::string TargetImplib;

+ 3 - 2
Source/cmLocalGhsMultiGenerator.cxx

@@ -16,8 +16,9 @@
 #include "cmGhsMultiTargetGenerator.h"
 #include "cmGeneratedFileStream.h"
 
-cmLocalGhsMultiGenerator::cmLocalGhsMultiGenerator(cmLocalGenerator* parent)
-  : cmLocalGenerator(parent)
+cmLocalGhsMultiGenerator::cmLocalGhsMultiGenerator(cmGlobalGenerator* gg,
+                                                   cmLocalGenerator* parent)
+  : cmLocalGenerator(gg, parent)
 {
 }
 

+ 1 - 1
Source/cmLocalGhsMultiGenerator.h

@@ -25,7 +25,7 @@ class cmGeneratedFileStream;
 class cmLocalGhsMultiGenerator : public cmLocalGenerator
 {
 public:
-  cmLocalGhsMultiGenerator(cmLocalGenerator* parent);
+  cmLocalGhsMultiGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent);
 
   virtual ~cmLocalGhsMultiGenerator();
 

+ 5 - 12
Source/cmLocalNinjaGenerator.cxx

@@ -22,14 +22,12 @@
 
 #include <assert.h>
 
-cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmLocalGenerator* parent)
-  : cmLocalGenerator(parent)
+cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
+                                             cmLocalGenerator* parent)
+  : cmLocalGenerator(gg, parent)
   , ConfigName("")
   , HomeRelativeOutputPath("")
 {
-#ifdef _WIN32
-  this->WindowsShell = true;
-#endif
   this->TargetImplib = "$TARGET_IMPLIB";
 }
 
@@ -50,7 +48,7 @@ void cmLocalNinjaGenerator::Generate()
 #endif
 
   // We do that only once for the top CMakeLists.txt file.
-  if(this->isRootMakefile())
+  if(this->IsRootMakefile())
     {
     this->WriteBuildFileTop();
 
@@ -181,11 +179,6 @@ cmake* cmLocalNinjaGenerator::GetCMakeInstance()
   return this->GetGlobalGenerator()->GetCMakeInstance();
 }
 
-bool cmLocalNinjaGenerator::isRootMakefile() const
-{
-  return !this->GetParent();
-}
-
 void cmLocalNinjaGenerator::WriteBuildFileTop()
 {
   // For the build file.
@@ -314,7 +307,7 @@ void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os)
     << "# Write statements declared in CMakeLists.txt:" << std::endl
     << "# " << this->Makefile->GetCurrentListFile() << std::endl
     ;
-  if(this->isRootMakefile())
+  if(this->IsRootMakefile())
     os << "# Which is the root file." << std::endl;
   cmGlobalNinjaGenerator::WriteDivider(os);
   os << std::endl;

+ 1 - 4
Source/cmLocalNinjaGenerator.h

@@ -32,7 +32,7 @@ class cmLocalNinjaGenerator : public cmLocalGenerator
 {
 public:
   /// Default constructor.
-  cmLocalNinjaGenerator(cmLocalGenerator* parent);
+  cmLocalNinjaGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent);
 
   /// Destructor.
   virtual ~cmLocalNinjaGenerator();
@@ -59,9 +59,6 @@ public:
   std::string const& GetConfigName() const
   { return this->ConfigName; }
 
-  /// @return whether we are processing the top CMakeLists.txt file.
-  bool isRootMakefile() const;
-
   /// @returns the relative path between the HomeOutputDirectory and this
   /// local generators StartOutputDirectory.
   std::string GetHomeRelativeOutputPath() const

+ 17 - 16
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -80,10 +80,9 @@ static std::string cmSplitExtension(std::string const& in, std::string& base)
 
 //----------------------------------------------------------------------------
 cmLocalUnixMakefileGenerator3::
-cmLocalUnixMakefileGenerator3(cmLocalGenerator* parent)
-  : cmLocalGenerator(parent)
+cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, cmLocalGenerator* parent)
+  : cmLocalGenerator(gg, parent)
 {
-  this->WindowsShell = false;
   this->IncludeDirective = "include";
   this->MakefileVariableSize = 0;
   this->IgnoreLibPrefix = false;
@@ -679,7 +678,7 @@ cmLocalUnixMakefileGenerator3
 
   // Write the list of commands.
   os << cmWrap("\t", commands, "", "\n") << "\n";
-  if(symbolic && !this->WatcomWMake)
+  if(symbolic && !this->IsWatcomWMake())
     {
     os << ".PHONY : " << cmMakeSafe(tgt) << "\n";
     }
@@ -696,7 +695,7 @@ std::string
 cmLocalUnixMakefileGenerator3
 ::ConvertShellCommand(std::string const& cmd, RelativeRoot root)
 {
-  if(this->WatcomWMake &&
+  if(this->IsWatcomWMake() &&
      cmSystemTools::FileIsFullPath(cmd.c_str()) &&
      cmd.find_first_of("( )") != cmd.npos)
     {
@@ -730,7 +729,7 @@ cmLocalUnixMakefileGenerator3
       << "NULL=nul\n"
       << "!ENDIF\n";
     }
-  if(this->WindowsShell)
+  if(this->IsWindowsShell())
     {
      makefileStream
        << "SHELL = cmd.exe\n"
@@ -798,7 +797,8 @@ cmLocalUnixMakefileGenerator3
     makefileStream, "Disable implicit rules so canonical targets will work.",
     ".SUFFIXES", no_depends, no_commands, false);
 
-  if(!this->NMake && !this->WatcomWMake && !this->BorlandMakeCurlyHack)
+  if(!this->IsNMake()
+      && !this->IsWatcomWMake() && !this->BorlandMakeCurlyHack)
     {
     // turn off RCS and SCCS automatic stuff from gmake
     makefileStream
@@ -810,7 +810,7 @@ cmLocalUnixMakefileGenerator3
   depends.push_back(".hpux_make_needs_suffix_list");
   this->WriteMakeRule(makefileStream, 0,
                       ".SUFFIXES", depends, no_commands, false);
-  if(this->WatcomWMake)
+  if(this->IsWatcomWMake())
     {
     // Switch on WMake feature, if an error or interrupt occurs during
     // makefile processing, the current target being made may be deleted
@@ -828,7 +828,7 @@ cmLocalUnixMakefileGenerator3
       << "VERBOSE = 1\n"
       << "\n";
     }
-  if(this->WatcomWMake)
+  if(this->IsWatcomWMake())
     {
     makefileStream <<
       "!ifndef VERBOSE\n"
@@ -962,7 +962,7 @@ cmLocalUnixMakefileGenerator3
 void cmLocalUnixMakefileGenerator3::AppendFlags(std::string& flags,
                                                 const std::string& newFlags)
 {
-  if(this->WatcomWMake && !newFlags.empty())
+  if(this->IsWatcomWMake() && !newFlags.empty())
     {
     std::string newf = newFlags;
     if(newf.find("\\\"") != newf.npos)
@@ -1112,7 +1112,7 @@ cmLocalUnixMakefileGenerator3
       //
       bool useCall = false;
 
-      if (this->WindowsShell)
+      if (this->IsWindowsShell())
         {
         std::string suffix;
         if (cmd.size() > 4)
@@ -1179,7 +1179,7 @@ cmLocalUnixMakefileGenerator3
           {
           cmd = "call " + cmd;
           }
-        else if (this->NMake && cmd[0]=='"')
+        else if (this->IsNMake() && cmd[0]=='"')
           {
           cmd = "echo >nul && " + cmd;
           }
@@ -1261,7 +1261,7 @@ cmLocalUnixMakefileGenerator3
         f != files.end(); ++f)
       {
       std::string fc = this->Convert(*f,START_OUTPUT,UNCHANGED);
-      fout << "  " << this->EscapeForCMake(fc) << "\n";
+      fout << "  " << cmLocalGenerator::EscapeForCMake(fc) << "\n";
       }
     fout << ")\n";
     }
@@ -2060,7 +2060,7 @@ void cmLocalUnixMakefileGenerator3
           di != defines.end(); ++di)
         {
         cmakefileStream
-          << "  " << this->EscapeForCMake(*di) << "\n";
+          << "  " << cmLocalGenerator::EscapeForCMake(*di) << "\n";
         }
       cmakefileStream
         << "  )\n";
@@ -2113,7 +2113,8 @@ void cmLocalUnixMakefileGenerator3
     for(std::vector<std::string>::const_iterator tri = transformRules.begin();
         tri != transformRules.end(); ++tri)
       {
-      cmakefileStream << "  " << this->EscapeForCMake(*tri) << "\n";
+      cmakefileStream << "  "
+          << cmLocalGenerator::EscapeForCMake(*tri) << "\n";
       }
     cmakefileStream
       << "  )\n";
@@ -2343,7 +2344,7 @@ void cmLocalUnixMakefileGenerator3
   // used by NMake and Borland make does not support "cd /d" so this
   // feature simply cannot work with them (Borland make does not even
   // support changing the drive letter with just "d:").
-  const char* cd_cmd = this->MinGWMake? "cd /d " : "cd ";
+  const char* cd_cmd = this->IsMinGWMake() ? "cd /d " : "cd ";
 
   if(!this->UnixCD)
     {

+ 2 - 31
Source/cmLocalUnixMakefileGenerator3.h

@@ -34,7 +34,8 @@ class cmSourceFile;
 class cmLocalUnixMakefileGenerator3 : public cmLocalGenerator
 {
 public:
-  cmLocalUnixMakefileGenerator3(cmLocalGenerator* parent);
+  cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg,
+                                cmLocalGenerator* parent);
   virtual ~cmLocalUnixMakefileGenerator3();
 
   /**
@@ -79,36 +80,6 @@ public:
   void SetMakeSilentFlag(const std::string& s) { this->MakeSilentFlag = s; }
   std::string &GetMakeSilentFlag() { return this->MakeSilentFlag; }
 
-  /**
-   * Set to true if the shell being used is the windows shell.
-   * This controls if statements in the makefile and the SHELL variable.
-   * The default is false.
-   */
-  void SetWindowsShell(bool v)  {this->WindowsShell = v;}
-
-  /**
-   * Set to true if the make tool being used is Watcom WMake.
-   */
-  void SetWatcomWMake(bool v)  {this->WatcomWMake = v;}
-
-  /**
-   * Set to true if the make tool being used is MinGW Make.
-   */
-  void SetMinGWMake(bool v)  {this->MinGWMake = v;}
-  bool IsMinGWMake() const { return this->MinGWMake; }
-
-  /**
-   * Set to true if the make tool being used is NMake.
-   */
-  void SetNMake(bool v)  {this->NMake = v;}
-
-  /**
-   * Set to true if the shell being used is the MSYS shell.
-   * This controls if statements in the makefile and the SHELL variable.
-   * The default is false.
-   */
-  void SetMSYSShell(bool v)  {this->MSYSShell = v;}
-
   /**
    * If set to true, then NULL is set to nil for non Windows_NT.
    * This uses make syntax used by nmake and borland.

+ 3 - 2
Source/cmLocalVisualStudio10Generator.cxx

@@ -62,8 +62,9 @@ class cmVS10XMLParser : public cmXMLParser
 
 //----------------------------------------------------------------------------
 cmLocalVisualStudio10Generator
-::cmLocalVisualStudio10Generator(VSVersion v, cmLocalGenerator* parent):
-  cmLocalVisualStudio7Generator(v, parent)
+::cmLocalVisualStudio10Generator(VSVersion v, cmGlobalGenerator* gg,
+                                 cmLocalGenerator* parent):
+  cmLocalVisualStudio7Generator(v, gg, parent)
 {
 }
 

+ 2 - 1
Source/cmLocalVisualStudio10Generator.h

@@ -25,7 +25,8 @@ class cmLocalVisualStudio10Generator : public cmLocalVisualStudio7Generator
 {
 public:
   ///! Set cache only and recurse to false by default.
-  cmLocalVisualStudio10Generator(VSVersion v, cmLocalGenerator* parent);
+  cmLocalVisualStudio10Generator(VSVersion v, cmGlobalGenerator* gg,
+                                 cmLocalGenerator* parent);
 
   virtual ~cmLocalVisualStudio10Generator();
 

+ 3 - 2
Source/cmLocalVisualStudio6Generator.cxx

@@ -24,8 +24,9 @@
 #include <cmsys/FStream.hxx>
 
 cmLocalVisualStudio6Generator
-::cmLocalVisualStudio6Generator(cmLocalGenerator* parent):
-  cmLocalVisualStudioGenerator(VS6, parent)
+::cmLocalVisualStudio6Generator(cmGlobalGenerator* gg,
+                                cmLocalGenerator* parent):
+  cmLocalVisualStudioGenerator(VS6, gg, parent)
 {
 }
 

+ 2 - 1
Source/cmLocalVisualStudio6Generator.h

@@ -29,7 +29,8 @@ class cmLocalVisualStudio6Generator : public cmLocalVisualStudioGenerator
 {
 public:
   ///! Set cache only and recurse to false by default.
-  cmLocalVisualStudio6Generator(cmLocalGenerator* parent);
+  cmLocalVisualStudio6Generator(cmGlobalGenerator* gg,
+                                cmLocalGenerator* parent);
 
   virtual ~cmLocalVisualStudio6Generator();
 

+ 3 - 2
Source/cmLocalVisualStudio7Generator.cxx

@@ -55,8 +55,9 @@ static void cmConvertToWindowsSlash(std::string& s)
 
 //----------------------------------------------------------------------------
 cmLocalVisualStudio7Generator
-::cmLocalVisualStudio7Generator(VSVersion v, cmLocalGenerator* parent):
-  cmLocalVisualStudioGenerator(v, parent)
+::cmLocalVisualStudio7Generator(VSVersion v, cmGlobalGenerator* gg,
+                                cmLocalGenerator* parent):
+  cmLocalVisualStudioGenerator(v, gg, parent)
 {
   this->ExtraFlagTable = 0;
   this->Internal = new cmLocalVisualStudio7GeneratorInternals(this);

+ 2 - 1
Source/cmLocalVisualStudio7Generator.h

@@ -35,7 +35,8 @@ class cmLocalVisualStudio7Generator : public cmLocalVisualStudioGenerator
 {
 public:
   ///! Set cache only and recurse to false by default.
-  cmLocalVisualStudio7Generator(VSVersion v, cmLocalGenerator* parent);
+  cmLocalVisualStudio7Generator(VSVersion v, cmGlobalGenerator* gg,
+                                cmLocalGenerator* parent);
 
   virtual ~cmLocalVisualStudio7Generator();
 

+ 3 - 4
Source/cmLocalVisualStudioGenerator.cxx

@@ -19,11 +19,10 @@
 
 //----------------------------------------------------------------------------
 cmLocalVisualStudioGenerator
-::cmLocalVisualStudioGenerator(VSVersion v, cmLocalGenerator* parent)
-  : cmLocalGenerator(parent)
+::cmLocalVisualStudioGenerator(VSVersion v, cmGlobalGenerator* gg,
+                               cmLocalGenerator* parent)
+  : cmLocalGenerator(gg, parent)
 {
-  this->WindowsShell = true;
-  this->WindowsVSIDE = true;
   this->Version = v;
 }
 

+ 2 - 1
Source/cmLocalVisualStudioGenerator.h

@@ -45,7 +45,8 @@ public:
     VS14 = 140
   };
 
-  cmLocalVisualStudioGenerator(VSVersion v, cmLocalGenerator* parent);
+  cmLocalVisualStudioGenerator(VSVersion v, cmGlobalGenerator* gg,
+                               cmLocalGenerator* parent);
   virtual ~cmLocalVisualStudioGenerator();
 
   /** Construct a script from the given list of command lines.  */

+ 3 - 2
Source/cmLocalXCodeGenerator.cxx

@@ -15,8 +15,9 @@
 #include "cmMakefile.h"
 
 //----------------------------------------------------------------------------
-cmLocalXCodeGenerator::cmLocalXCodeGenerator(cmLocalGenerator* parent)
-  : cmLocalGenerator(parent)
+cmLocalXCodeGenerator::cmLocalXCodeGenerator(cmGlobalGenerator* gg,
+                                             cmLocalGenerator* parent)
+  : cmLocalGenerator(gg, parent)
 {
   // the global generator does this, so do not
   // put these flags into the language flags

+ 1 - 1
Source/cmLocalXCodeGenerator.h

@@ -24,7 +24,7 @@ class cmLocalXCodeGenerator : public cmLocalGenerator
 {
 public:
   ///! Set cache only and recurse to false by default.
-  cmLocalXCodeGenerator(cmLocalGenerator* parent);
+  cmLocalXCodeGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent);
 
   virtual ~cmLocalXCodeGenerator();
   virtual std::string GetTargetDirectory(cmTarget const& target) const;

+ 41 - 20
Source/cmMakefile.cxx

@@ -153,27 +153,13 @@ public:
 cmMakefile::cmMakefile(cmLocalGenerator* localGenerator)
   : Internal(new Internals),
     LocalGenerator(localGenerator),
-    StateSnapshot(localGenerator->GetGlobalGenerator()
-                                ->GetCMakeInstance()->GetState())
+    StateSnapshot(localGenerator->GetStateSnapshot())
 {
   this->Internal->PushDefinitions();
   this->Internal->VarInitStack.push(std::set<std::string>());
   this->Internal->VarUsageStack.push(std::set<std::string>());
   this->Internal->IsSourceFileTryCompile = false;
 
-  if (this->LocalGenerator->GetParent())
-    {
-    cmMakefile* parentMf = this->LocalGenerator->GetParent()->GetMakefile();
-    this->StateSnapshot =
-        this->GetState()->CreateSnapshot(parentMf->StateSnapshot);
-    }
-  else
-    {
-    this->StateSnapshot =
-        this->GetState()->CreateSnapshot(this->StateSnapshot);
-    }
-
-
   // Initialize these first since AddDefaultDefinitions calls AddDefinition
   this->WarnUnused = false;
   this->CheckSystemVars = false;
@@ -212,7 +198,6 @@ cmMakefile::cmMakefile(cmLocalGenerator* localGenerator)
   this->HeaderFileExtensions.push_back( "txx" );
 
   this->DefineFlags = " ";
-  this->LocalGenerator = localGenerator;
 
   this->AddDefaultDefinitions();
 
@@ -1657,12 +1642,47 @@ void cmMakefile::InitializeFromParent()
 void cmMakefile::ConfigureSubDirectory(cmLocalGenerator *lg2)
 {
   lg2->GetMakefile()->InitializeFromParent();
+  std::string currentStart = lg2->GetMakefile()->GetCurrentSourceDirectory();
   if (this->GetCMakeInstance()->GetDebugOutput())
     {
     std::string msg="   Entering             ";
-    msg += lg2->GetMakefile()->GetCurrentSourceDirectory();
+    msg += currentStart;
     cmSystemTools::Message(msg.c_str());
     }
+
+  currentStart += "/CMakeLists.txt";
+  if(!cmSystemTools::FileExists(currentStart.c_str(), true))
+    {
+    // The file is missing.  Check policy CMP0014.
+    std::ostringstream e;
+    e << "The source directory\n"
+      << "  " << currentStart << "\n"
+      << "does not contain a CMakeLists.txt file.";
+    switch (this->GetPolicyStatus(cmPolicies::CMP0014))
+      {
+      case cmPolicies::WARN:
+        // Print the warning.
+        e << "\n"
+          << "CMake does not support this case but it used "
+          << "to work accidentally and is being allowed for "
+          << "compatibility."
+          << "\n"
+          << cmPolicies::GetPolicyWarning(cmPolicies::CMP0014);
+        this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+      case cmPolicies::OLD:
+        // OLD behavior does not warn.
+        break;
+      case cmPolicies::REQUIRED_IF_USED:
+      case cmPolicies::REQUIRED_ALWAYS:
+        e << "\n"
+          << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0014);
+      case cmPolicies::NEW:
+        // NEW behavior prints the error.
+        this->IssueMessage(cmake::FATAL_ERROR, e.str());
+      }
+    lg2->SetConfiguredCMP0014(true);
+    return;
+    }
   // finally configure the subdir
   lg2->Configure();
   if (this->GetCMakeInstance()->GetDebugOutput())
@@ -4131,11 +4151,12 @@ const char *cmMakefile::GetProperty(const std::string& prop,
   output = "";
   if (prop == "PARENT_DIRECTORY")
     {
-    if(cmLocalGenerator* plg = this->LocalGenerator->GetParent())
+    cmState::Snapshot parent = this->StateSnapshot.GetParent();
+    if(parent.IsValid())
       {
-      output = plg->GetMakefile()->GetCurrentSourceDirectory();
+      return parent.GetCurrentSourceDirectory();
       }
-    return output.c_str();
+    return "";
     }
   else if (prop == "INCLUDE_REGULAR_EXPRESSION" )
     {

+ 2 - 2
Source/cmMakefileTargetGenerator.cxx

@@ -1118,8 +1118,8 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
         pi != this->MultipleOutputPairs.end(); ++pi)
       {
       *this->InfoFileStream
-        << "  " << this->LocalGenerator->EscapeForCMake(pi->first)
-        << " "  << this->LocalGenerator->EscapeForCMake(pi->second)
+        << "  " << cmLocalGenerator::EscapeForCMake(pi->first)
+        << " "  << cmLocalGenerator::EscapeForCMake(pi->second)
         << "\n";
       }
     *this->InfoFileStream << "  )\n\n";

+ 1 - 1
Source/cmProjectCommand.cxx

@@ -53,7 +53,7 @@ bool cmProjectCommand
   // CMAKE_PROJECT_NAME will match PROJECT_NAME, and cmake --build
   // will work.
   if(!this->Makefile->GetDefinition("CMAKE_PROJECT_NAME")
-     || (this->Makefile->GetLocalGenerator()->GetParent() == 0) )
+     || (this->Makefile->GetLocalGenerator()->IsRootMakefile()))
     {
     this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", args[0].c_str());
     this->Makefile->AddCacheDefinition

+ 21 - 0
Source/cmState.cxx

@@ -522,3 +522,24 @@ void cmState::Snapshot::SetCurrentBinaryDirectory(std::string const& dir)
     cmSystemTools::CollapseFullPath(
         this->State->OutputLocations[this->Position]);
 }
+
+bool cmState::Snapshot::IsValid() const
+{
+  return this->State ? true : false;
+}
+
+cmState::Snapshot cmState::Snapshot::GetParent() const
+{
+  Snapshot snapshot;
+  if (!this->State)
+    {
+    return snapshot;
+    }
+  PositionType parentPos = this->State->ParentPositions[this->Position];
+  if (parentPos > 0)
+    {
+    snapshot = Snapshot(this->State, parentPos);
+    }
+
+  return snapshot;
+}

+ 3 - 0
Source/cmState.h

@@ -36,6 +36,9 @@ public:
     const char* GetCurrentBinaryDirectory() const;
     void SetCurrentBinaryDirectory(std::string const& dir);
 
+    bool IsValid() const;
+    Snapshot GetParent() const;
+
   private:
     friend class cmState;
     cmState* State;

+ 7 - 9
Source/cmTestGenerator.cxx

@@ -82,7 +82,6 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
   // be translated.
   std::string exe = command[0];
   cmMakefile* mf = this->Test->GetMakefile();
-  cmLocalGenerator* lg = mf->GetLocalGenerator();
   cmTarget* target = mf->FindTargetToUse(exe);
   if(target && target->GetType() == cmTarget::EXECUTABLE)
     {
@@ -98,13 +97,13 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
       cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs);
       std::string emulatorExe(emulatorWithArgs[0]);
       cmSystemTools::ConvertToUnixSlashes(emulatorExe);
-      os << lg->EscapeForCMake(emulatorExe) << " ";
+      os << cmLocalGenerator::EscapeForCMake(emulatorExe) << " ";
       for(std::vector<std::string>::const_iterator ei =
           emulatorWithArgs.begin()+1;
           ei != emulatorWithArgs.end();
           ++ei)
         {
-        os << lg->EscapeForCMake(*ei) << " ";
+        os << cmLocalGenerator::EscapeForCMake(*ei) << " ";
         }
       }
     }
@@ -116,11 +115,12 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
     }
 
   // Generate the command line with full escapes.
-  os << lg->EscapeForCMake(exe);
+  os << cmLocalGenerator::EscapeForCMake(exe);
   for(std::vector<std::string>::const_iterator ci = command.begin()+1;
       ci != command.end(); ++ci)
     {
-    os << " " << lg->EscapeForCMake(ge.Parse(*ci)->Evaluate(mf, config));
+    os << " " << cmLocalGenerator::EscapeForCMake(
+                                         ge.Parse(*ci)->Evaluate(mf, config));
     }
 
   // Finish the test command.
@@ -136,7 +136,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
         i != pm.end(); ++i)
       {
       os << " " << i->first
-         << " " << lg->EscapeForCMake(
+         << " " << cmLocalGenerator::EscapeForCMake(
            ge.Parse(i->second.GetValue())->Evaluate(mf, config));
       }
     os << ")" << std::endl;
@@ -197,8 +197,6 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout,
   fout << ")" << std::endl;
 
   // Output properties for the test.
-  cmMakefile* mf = this->Test->GetMakefile();
-  cmLocalGenerator* lg = mf->GetLocalGenerator();
   cmPropertyMap& pm = this->Test->GetProperties();
   if(!pm.empty())
     {
@@ -208,7 +206,7 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout,
         i != pm.end(); ++i)
       {
       fout << " " << i->first
-           << " " << lg->EscapeForCMake(i->second.GetValue());
+           << " " << cmLocalGenerator::EscapeForCMake(i->second.GetValue());
       }
     fout << ")" << std::endl;
     }

+ 4 - 0
Tests/RunCMake/CTestCommandLine/BadCTestTestfile-stderr.txt

@@ -0,0 +1,4 @@
+^CMake Error at CTestTestfile.cmake:[0-9]+ \(subdirs\):
+  subdirs called with incorrect number of arguments
++
+No tests were found!!!$

+ 13 - 0
Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake

@@ -26,3 +26,16 @@ function(run_repeat_until_fail_tests)
     )
 endfunction()
 run_repeat_until_fail_tests()
+
+function(run_BadCTestTestfile)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/BadCTestTestfile)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+  file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" "
+subdirs()
+")
+
+  run_cmake_command(BadCTestTestfile ${CMAKE_CTEST_COMMAND})
+endfunction()
+run_BadCTestTestfile()