Browse Source

Merge topic 'refactor-cmLocalGenerator'

fa9eb814 cmLocalGenerator: Remove redundant path access.
1933f3d1 cmLocalGenerator: Remove redundant path conversions.
9e4b6cc2 cmState: Store computed relative paths to to current directories.
991f5e49 cmState::Snapshot: Store components for current directories.
57bdc1a2 cmState: Compute and store directory components.
Brad King 10 years ago
parent
commit
be248ab435

+ 2 - 0
Source/CPack/cmCPackGenerator.cxx

@@ -711,6 +711,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
           }
           }
 
 
         cmake cm;
         cmake cm;
+        cm.SetHomeDirectory("");
+        cm.SetHomeOutputDirectory("");
         cm.AddCMakePaths();
         cm.AddCMakePaths();
         cm.SetProgressCallback(cmCPackGeneratorProgress, this);
         cm.SetProgressCallback(cmCPackGeneratorProgress, this);
         cmGlobalGenerator gg;
         cmGlobalGenerator gg;

+ 2 - 0
Source/CPack/cpack.cxx

@@ -198,6 +198,8 @@ int main (int argc, char const* const* argv)
     "Read CPack config file: " << cpackConfigFile << std::endl);
     "Read CPack config file: " << cpackConfigFile << std::endl);
 
 
   cmake cminst;
   cmake cminst;
+  cminst.SetHomeDirectory("");
+  cminst.SetHomeOutputDirectory("");
   cminst.GetState()->RemoveUnscriptableCommands();
   cminst.GetState()->RemoveUnscriptableCommands();
   cmGlobalGenerator cmgg;
   cmGlobalGenerator cmgg;
   cmgg.SetCMakeInstance(&cminst);
   cmgg.SetCMakeInstance(&cminst);

+ 2 - 0
Source/CTest/cmCTestBuildAndTestHandler.cxx

@@ -204,6 +204,8 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
     }
     }
 
 
   cmake cm;
   cmake cm;
+  cm.SetHomeDirectory("");
+  cm.SetHomeOutputDirectory("");
   std::string cmakeOutString;
   std::string cmakeOutString;
   cmCTestBuildAndTestCaptureRAII captureRAII(cm, cmakeOutString);
   cmCTestBuildAndTestCaptureRAII captureRAII(cm, cmakeOutString);
   static_cast<void>(captureRAII);
   static_cast<void>(captureRAII);

+ 2 - 0
Source/CTest/cmCTestLaunch.cxx

@@ -750,6 +750,8 @@ int cmCTestLaunch::Main(int argc, const char* const argv[])
 void cmCTestLaunch::LoadConfig()
 void cmCTestLaunch::LoadConfig()
 {
 {
   cmake cm;
   cmake cm;
+  cm.SetHomeDirectory("");
+  cm.SetHomeOutputDirectory("");
   cmGlobalGenerator gg;
   cmGlobalGenerator gg;
   gg.SetCMakeInstance(&cm);
   gg.SetCMakeInstance(&cm);
   cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator());
   cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator());

+ 2 - 0
Source/CTest/cmCTestScriptHandler.cxx

@@ -336,6 +336,8 @@ void cmCTestScriptHandler::CreateCMake()
     delete this->LocalGenerator;
     delete this->LocalGenerator;
     }
     }
   this->CMake = new cmake;
   this->CMake = new cmake;
+  this->CMake->SetHomeDirectory("");
+  this->CMake->SetHomeOutputDirectory("");
   this->CMake->AddCMakePaths();
   this->CMake->AddCMakePaths();
   this->GlobalGenerator = new cmGlobalGenerator;
   this->GlobalGenerator = new cmGlobalGenerator;
   this->GlobalGenerator->SetCMakeInstance(this->CMake);
   this->GlobalGenerator->SetCMakeInstance(this->CMake);

+ 2 - 0
Source/CTest/cmCTestTestHandler.cxx

@@ -1571,6 +1571,8 @@ void cmCTestTestHandler::GetListOfTests()
   cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
   cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
     "Constructing a list of tests" << std::endl, this->Quiet);
     "Constructing a list of tests" << std::endl, this->Quiet);
   cmake cm;
   cmake cm;
+  cm.SetHomeDirectory("");
+  cm.SetHomeOutputDirectory("");
   cmGlobalGenerator gg;
   cmGlobalGenerator gg;
   gg.SetCMakeInstance(&cm);
   gg.SetCMakeInstance(&cm);
   cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator());
   cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator());

+ 2 - 0
Source/CursesDialog/ccmake.cxx

@@ -104,6 +104,8 @@ int main(int argc, char const* const* argv)
   if(doc.CheckOptions(argc, argv))
   if(doc.CheckOptions(argc, argv))
     {
     {
     cmake hcm;
     cmake hcm;
+    hcm.SetHomeDirectory("");
+    hcm.SetHomeOutputDirectory("");
     hcm.AddCMakePaths();
     hcm.AddCMakePaths();
     std::vector<cmDocumentationEntry> generators;
     std::vector<cmDocumentationEntry> generators;
     hcm.GetGeneratorDocumentation(generators);
     hcm.GetGeneratorDocumentation(generators);

+ 2 - 0
Source/QtDialog/CMakeSetup.cxx

@@ -64,6 +64,8 @@ int main(int argc, char** argv)
     {
     {
     // Construct and print requested documentation.
     // Construct and print requested documentation.
     cmake hcm;
     cmake hcm;
+    hcm.SetHomeDirectory("");
+    hcm.SetHomeOutputDirectory("");
     hcm.AddCMakePaths();
     hcm.AddCMakePaths();
 
 
     std::vector<cmDocumentationEntry> generators;
     std::vector<cmDocumentationEntry> generators;

+ 2 - 0
Source/cmCTest.cxx

@@ -510,6 +510,8 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
     }
     }
 
 
   cmake cm;
   cmake cm;
+  cm.SetHomeDirectory("");
+  cm.SetHomeOutputDirectory("");
   cmGlobalGenerator gg;
   cmGlobalGenerator gg;
   gg.SetCMakeInstance(&cm);
   gg.SetCMakeInstance(&cm);
   cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator());
   cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator());

+ 2 - 0
Source/cmGraphVizWriter.cxx

@@ -65,6 +65,8 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
                                     const char* fallbackSettingsFileName)
                                     const char* fallbackSettingsFileName)
 {
 {
   cmake cm;
   cmake cm;
+  cm.SetHomeDirectory("");
+  cm.SetHomeOutputDirectory("");
   cmGlobalGenerator ggi;
   cmGlobalGenerator ggi;
   ggi.SetCMakeInstance(&cm);
   ggi.SetCMakeInstance(&cm);
   cmsys::auto_ptr<cmLocalGenerator> lg(ggi.MakeLocalGenerator());
   cmsys::auto_ptr<cmLocalGenerator> lg(ggi.MakeLocalGenerator());

+ 13 - 149
Source/cmLocalGenerator.cxx

@@ -65,8 +65,6 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg,
   this->UseRelativePaths = false;
   this->UseRelativePaths = false;
   this->Configured = false;
   this->Configured = false;
   this->EmitUniversalBinaryFlags = true;
   this->EmitUniversalBinaryFlags = true;
-  this->RelativePathsConfigured = false;
-  this->PathConversionsSetup = false;
   this->BackwardsCompatibility = 0;
   this->BackwardsCompatibility = 0;
   this->BackwardsCompatibilityFinal = false;
   this->BackwardsCompatibilityFinal = false;
 }
 }
@@ -195,29 +193,6 @@ void cmLocalGenerator::ReadInputFile()
   this->Makefile->ProcessBuildsystemFile(currentStart.c_str());
   this->Makefile->ProcessBuildsystemFile(currentStart.c_str());
 }
 }
 
 
-void cmLocalGenerator::SetupPathConversions()
-{
-  // Setup the current output directory components for use by
-  // Convert
-  std::string outdir;
-  outdir =
-    cmSystemTools::CollapseFullPath(this->GetState()->GetSourceDirectory());
-  cmSystemTools::SplitPath(outdir, this->HomeDirectoryComponents);
-  outdir = cmSystemTools::CollapseFullPath(
-      this->StateSnapshot.GetCurrentSourceDirectory());
-  cmSystemTools::SplitPath(outdir, this->StartDirectoryComponents);
-
-  outdir = cmSystemTools::CollapseFullPath
-    (this->GetState()->GetBinaryDirectory());
-  cmSystemTools::SplitPath(outdir,
-                           this->HomeOutputDirectoryComponents);
-
-  outdir = cmSystemTools::CollapseFullPath
-    (this->StateSnapshot.GetCurrentBinaryDirectory());
-  cmSystemTools::SplitPath(outdir,
-                           this->StartOutputDirectoryComponents);
-}
-
 void cmLocalGenerator::ConfigureFinalPass()
 void cmLocalGenerator::ConfigureFinalPass()
 {
 {
   this->Makefile->ConfigureFinalPass();
   this->Makefile->ConfigureFinalPass();
@@ -389,12 +364,8 @@ void cmLocalGenerator::GenerateInstallRules()
   // Create the install script file.
   // Create the install script file.
   std::string file = this->StateSnapshot.GetCurrentBinaryDirectory();
   std::string file = this->StateSnapshot.GetCurrentBinaryDirectory();
   std::string homedir = this->GetState()->GetBinaryDirectory();
   std::string homedir = this->GetState()->GetBinaryDirectory();
-  std::string currdir = this->StateSnapshot.GetCurrentBinaryDirectory();
-  cmSystemTools::ConvertToUnixSlashes(file);
-  cmSystemTools::ConvertToUnixSlashes(homedir);
-  cmSystemTools::ConvertToUnixSlashes(currdir);
   int toplevel_install = 0;
   int toplevel_install = 0;
-  if ( currdir == homedir )
+  if (file == homedir)
     {
     {
     toplevel_install = 1;
     toplevel_install = 1;
     }
     }
@@ -2704,13 +2675,6 @@ std::string cmLocalGenerator::Convert(const std::string& source,
                                       OutputFormat output,
                                       OutputFormat output,
                                       bool optional)
                                       bool optional)
 {
 {
-  // Make sure the relative path conversion components are set.
-  if(!this->PathConversionsSetup)
-    {
-    this->SetupPathConversions();
-    this->PathConversionsSetup = true;
-    }
-
   // Convert the path to a relative path.
   // Convert the path to a relative path.
   std::string result = source;
   std::string result = source;
 
 
@@ -2720,25 +2684,23 @@ std::string cmLocalGenerator::Convert(const std::string& source,
       {
       {
       case HOME:
       case HOME:
         //result = cmSystemTools::CollapseFullPath(result.c_str());
         //result = cmSystemTools::CollapseFullPath(result.c_str());
-        result = this->ConvertToRelativePath(this->HomeDirectoryComponents,
-                                             result);
+        result = this->ConvertToRelativePath(
+            this->GetState()->GetSourceDirectoryComponents(), result);
         break;
         break;
       case START:
       case START:
         //result = cmSystemTools::CollapseFullPath(result.c_str());
         //result = cmSystemTools::CollapseFullPath(result.c_str());
-        result = this->ConvertToRelativePath(this->StartDirectoryComponents,
-                                             result);
+        result = this->ConvertToRelativePath(
+            this->StateSnapshot.GetCurrentSourceDirectoryComponents(), result);
         break;
         break;
       case HOME_OUTPUT:
       case HOME_OUTPUT:
         //result = cmSystemTools::CollapseFullPath(result.c_str());
         //result = cmSystemTools::CollapseFullPath(result.c_str());
-        result =
-          this->ConvertToRelativePath(this->HomeOutputDirectoryComponents,
-                                      result);
+        result = this->ConvertToRelativePath(
+            this->GetState()->GetBinaryDirectoryComponents(), result);
         break;
         break;
       case START_OUTPUT:
       case START_OUTPUT:
         //result = cmSystemTools::CollapseFullPath(result.c_str());
         //result = cmSystemTools::CollapseFullPath(result.c_str());
-        result =
-          this->ConvertToRelativePath(this->StartOutputDirectoryComponents,
-                                      result);
+        result = this->ConvertToRelativePath(
+            this->StateSnapshot.GetCurrentBinaryDirectoryComponents(), result);
         break;
         break;
       case FULL:
       case FULL:
         result = cmSystemTools::CollapseFullPath(result);
         result = cmSystemTools::CollapseFullPath(result);
@@ -2810,97 +2772,6 @@ std::string cmLocalGenerator::Convert(RelativeRoot remote,
     }
     }
 }
 }
 
 
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::FindRelativePathTopSource()
-{
-  cmState::Snapshot snapshot = this->StateSnapshot;
-  std::vector<cmState::Snapshot> snapshots;
-  snapshots.push_back(snapshot);
-  while (true)
-    {
-    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))
-      {
-      result = currentSource;
-      }
-    }
-
-  return result;
-}
-
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::FindRelativePathTopBinary()
-{
-  cmState::Snapshot snapshot = this->StateSnapshot;
-  std::vector<cmState::Snapshot> snapshots;
-  snapshots.push_back(snapshot);
-  while (true)
-    {
-    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))
-      {
-      result = currentBinary;
-      }
-    }
-
-  return result;
-}
-
-//----------------------------------------------------------------------------
-void cmLocalGenerator::ConfigureRelativePaths()
-{
-  // Relative path conversion inside the source tree is not used to
-  // construct relative paths passed to build tools so it is safe to
-  // even when the source is a network path.
-  std::string source = this->FindRelativePathTopSource();
-  this->RelativePathTopSource = source;
-
-  // The current working directory on Windows cannot be a network
-  // path.  Therefore relative paths cannot work when the binary tree
-  // is a network path.
-  std::string binary = this->FindRelativePathTopBinary();
-  if(binary.size() < 2 || binary.substr(0, 2) != "//")
-    {
-    this->RelativePathTopBinary = binary;
-    }
-  else
-    {
-    this->RelativePathTopBinary = "";
-    }
-}
-
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 static bool cmLocalGeneratorNotAbove(const char* a, const char* b)
 static bool cmLocalGeneratorNotAbove(const char* a, const char* b)
 {
 {
@@ -2926,26 +2797,19 @@ cmLocalGenerator::ConvertToRelativePath(const std::vector<std::string>& local,
     return in_remote;
     return in_remote;
     }
     }
 
 
-  // Make sure relative path conversion is configured.
-  if(!this->RelativePathsConfigured)
-    {
-    this->ConfigureRelativePaths();
-    this->RelativePathsConfigured = true;
-    }
-
   if(!force)
   if(!force)
     {
     {
     // Skip conversion if the path and local are not both in the source
     // Skip conversion if the path and local are not both in the source
     // or both in the binary tree.
     // or both in the binary tree.
     std::string local_path = cmSystemTools::JoinPath(local);
     std::string local_path = cmSystemTools::JoinPath(local);
     if(!((cmLocalGeneratorNotAbove(local_path.c_str(),
     if(!((cmLocalGeneratorNotAbove(local_path.c_str(),
-                                   this->RelativePathTopBinary.c_str()) &&
+              this->StateSnapshot.GetRelativePathTopBinary()) &&
           cmLocalGeneratorNotAbove(in_remote.c_str(),
           cmLocalGeneratorNotAbove(in_remote.c_str(),
-                                   this->RelativePathTopBinary.c_str())) ||
+              this->StateSnapshot.GetRelativePathTopBinary())) ||
          (cmLocalGeneratorNotAbove(local_path.c_str(),
          (cmLocalGeneratorNotAbove(local_path.c_str(),
-                                   this->RelativePathTopSource.c_str()) &&
+              this->StateSnapshot.GetRelativePathTopSource()) &&
           cmLocalGeneratorNotAbove(in_remote.c_str(),
           cmLocalGeneratorNotAbove(in_remote.c_str(),
-                                   this->RelativePathTopSource.c_str()))))
+              this->StateSnapshot.GetRelativePathTopSource()))))
       {
       {
       return in_remote;
       return in_remote;
       }
       }

+ 0 - 19
Source/cmLocalGenerator.h

@@ -440,11 +440,6 @@ protected:
                                               std::string const& dir_max);
                                               std::string const& dir_max);
   void ComputeObjectMaxPath();
   void ComputeObjectMaxPath();
 
 
-  void ConfigureRelativePaths();
-  std::string FindRelativePathTopSource();
-  std::string FindRelativePathTopBinary();
-  void SetupPathConversions();
-
   virtual std::string ConvertToLinkReference(std::string const& lib,
   virtual std::string ConvertToLinkReference(std::string const& lib,
                                              OutputFormat format = SHELL);
                                              OutputFormat format = SHELL);
 
 
@@ -458,10 +453,6 @@ protected:
   cmMakefile *Makefile;
   cmMakefile *Makefile;
   cmState::Snapshot StateSnapshot;
   cmState::Snapshot StateSnapshot;
   cmGlobalGenerator *GlobalGenerator;
   cmGlobalGenerator *GlobalGenerator;
-  std::vector<std::string> HomeDirectoryComponents;
-  std::vector<std::string> StartDirectoryComponents;
-  std::vector<std::string> HomeOutputDirectoryComponents;
-  std::vector<std::string> StartOutputDirectoryComponents;
   cmLocalGenerator* Parent;
   cmLocalGenerator* Parent;
   std::vector<cmLocalGenerator*> Children;
   std::vector<cmLocalGenerator*> Children;
   std::map<std::string, std::string> UniqueObjectNamesMap;
   std::map<std::string, std::string> UniqueObjectNamesMap;
@@ -477,16 +468,6 @@ protected:
   // committed.
   // committed.
   std::string TargetImplib;
   std::string TargetImplib;
 
 
-  // The top-most directories for relative path conversion.  Both the
-  // source and destination location of a relative path conversion
-  // must be underneath one of these directories (both under source or
-  // both under binary) in order for the relative path to be evaluated
-  // safely by the build tools.
-  std::string RelativePathTopSource;
-  std::string RelativePathTopBinary;
-  bool RelativePathsConfigured;
-  bool PathConversionsSetup;
-
   cmIML_INT_uint64_t BackwardsCompatibility;
   cmIML_INT_uint64_t BackwardsCompatibility;
   bool BackwardsCompatibilityFinal;
   bool BackwardsCompatibilityFinal;
 private:
 private:

+ 6 - 5
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -540,9 +540,11 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
   // Setup relative path conversion tops.
   // Setup relative path conversion tops.
   infoFileStream
   infoFileStream
     << "# Relative path conversion top directories.\n"
     << "# Relative path conversion top directories.\n"
-    << "set(CMAKE_RELATIVE_PATH_TOP_SOURCE \"" << this->RelativePathTopSource
+    << "set(CMAKE_RELATIVE_PATH_TOP_SOURCE \""
+    << this->StateSnapshot.GetRelativePathTopSource()
     << "\")\n"
     << "\")\n"
-    << "set(CMAKE_RELATIVE_PATH_TOP_BINARY \"" << this->RelativePathTopBinary
+    << "set(CMAKE_RELATIVE_PATH_TOP_BINARY \""
+    << this->StateSnapshot.GetRelativePathTopBinary()
     << "\")\n"
     << "\")\n"
     << "\n";
     << "\n";
 
 
@@ -1610,16 +1612,15 @@ cmLocalUnixMakefileGenerator3
       }
       }
 
 
     // Setup relative path top directories.
     // Setup relative path top directories.
-    this->RelativePathsConfigured = true;
     if(const char* relativePathTopSource =
     if(const char* relativePathTopSource =
        mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE"))
        mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE"))
       {
       {
-      this->RelativePathTopSource = relativePathTopSource;
+      this->StateSnapshot.SetRelativePathTopSource(relativePathTopSource);
       }
       }
     if(const char* relativePathTopBinary =
     if(const char* relativePathTopBinary =
        mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY"))
        mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY"))
       {
       {
-      this->RelativePathTopBinary = relativePathTopBinary;
+      this->StateSnapshot.SetRelativePathTopBinary(relativePathTopBinary);
       }
       }
     }
     }
   else
   else

+ 150 - 0
Source/cmState.cxx

@@ -197,6 +197,10 @@ void cmState::Initialize()
   this->Locations.clear();
   this->Locations.clear();
   this->OutputLocations.clear();
   this->OutputLocations.clear();
   this->ParentPositions.clear();
   this->ParentPositions.clear();
+  this->CurrentSourceDirectoryComponents.clear();
+  this->CurrentBinaryDirectoryComponents.clear();
+  this->RelativePathTopSource.clear();
+  this->RelativePathTopBinary.clear();
 
 
   this->CreateSnapshot(Snapshot());
   this->CreateSnapshot(Snapshot());
   this->DefineProperty
   this->DefineProperty
@@ -458,6 +462,10 @@ void cmState::SetSourceDirectory(std::string const& sourceDirectory)
 {
 {
   this->SourceDirectory = sourceDirectory;
   this->SourceDirectory = sourceDirectory;
   cmSystemTools::ConvertToUnixSlashes(this->SourceDirectory);
   cmSystemTools::ConvertToUnixSlashes(this->SourceDirectory);
+
+  cmSystemTools::SplitPath(
+      cmSystemTools::CollapseFullPath(this->SourceDirectory),
+        this->SourceDirectoryComponents);
 }
 }
 
 
 const char* cmState::GetSourceDirectory() const
 const char* cmState::GetSourceDirectory() const
@@ -465,10 +473,19 @@ const char* cmState::GetSourceDirectory() const
   return this->SourceDirectory.c_str();
   return this->SourceDirectory.c_str();
 }
 }
 
 
+std::vector<std::string> const& cmState::GetSourceDirectoryComponents() const
+{
+  return this->SourceDirectoryComponents;
+}
+
 void cmState::SetBinaryDirectory(std::string const& binaryDirectory)
 void cmState::SetBinaryDirectory(std::string const& binaryDirectory)
 {
 {
   this->BinaryDirectory = binaryDirectory;
   this->BinaryDirectory = binaryDirectory;
   cmSystemTools::ConvertToUnixSlashes(this->BinaryDirectory);
   cmSystemTools::ConvertToUnixSlashes(this->BinaryDirectory);
+
+  cmSystemTools::SplitPath(
+      cmSystemTools::CollapseFullPath(this->BinaryDirectory),
+        this->BinaryDirectoryComponents);
 }
 }
 
 
 const char* cmState::GetBinaryDirectory() const
 const char* cmState::GetBinaryDirectory() const
@@ -476,12 +493,103 @@ const char* cmState::GetBinaryDirectory() const
   return this->BinaryDirectory.c_str();
   return this->BinaryDirectory.c_str();
 }
 }
 
 
+std::vector<std::string> const& cmState::GetBinaryDirectoryComponents() const
+{
+  return this->BinaryDirectoryComponents;
+}
+
+void cmState::Snapshot::ComputeRelativePathTopSource()
+{
+  // Relative path conversion inside the source tree is not used to
+  // construct relative paths passed to build tools so it is safe to use
+  // even when the source is a network path.
+
+  cmState::Snapshot snapshot = *this;
+  std::vector<cmState::Snapshot> snapshots;
+  snapshots.push_back(snapshot);
+  while (true)
+    {
+    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))
+      {
+      result = currentSource;
+      }
+    }
+  this->State->RelativePathTopSource[this->Position] = result;
+}
+
+void cmState::Snapshot::ComputeRelativePathTopBinary()
+{
+  cmState::Snapshot snapshot = *this;
+  std::vector<cmState::Snapshot> snapshots;
+  snapshots.push_back(snapshot);
+  while (true)
+    {
+    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))
+      {
+      result = currentBinary;
+      }
+    }
+
+  // The current working directory on Windows cannot be a network
+  // path.  Therefore relative paths cannot work when the binary tree
+  // is a network path.
+  if(result.size() < 2 || result.substr(0, 2) != "//")
+    {
+    this->State->RelativePathTopBinary[this->Position] = result;
+    }
+  else
+    {
+    this->State->RelativePathTopBinary[this->Position] = "";
+    }
+}
+
 cmState::Snapshot cmState::CreateSnapshot(Snapshot originSnapshot)
 cmState::Snapshot cmState::CreateSnapshot(Snapshot originSnapshot)
 {
 {
   PositionType pos = this->ParentPositions.size();
   PositionType pos = this->ParentPositions.size();
   this->ParentPositions.push_back(originSnapshot.Position);
   this->ParentPositions.push_back(originSnapshot.Position);
   this->Locations.resize(this->Locations.size() + 1);
   this->Locations.resize(this->Locations.size() + 1);
   this->OutputLocations.resize(this->OutputLocations.size() + 1);
   this->OutputLocations.resize(this->OutputLocations.size() + 1);
+  this->CurrentSourceDirectoryComponents.resize(
+      this->CurrentSourceDirectoryComponents.size() + 1);
+  this->CurrentBinaryDirectoryComponents.resize(
+      this->CurrentBinaryDirectoryComponents.size() + 1);
+  this->RelativePathTopSource.resize(this->RelativePathTopSource.size() + 1);
+  this->RelativePathTopBinary.resize(this->RelativePathTopBinary.size() + 1);
   return cmState::Snapshot(this, pos);
   return cmState::Snapshot(this, pos);
 }
 }
 
 
@@ -505,6 +613,11 @@ void cmState::Snapshot::SetCurrentSourceDirectory(std::string const& dir)
       this->State->Locations[this->Position]);
       this->State->Locations[this->Position]);
   this->State->Locations[this->Position] =
   this->State->Locations[this->Position] =
     cmSystemTools::CollapseFullPath(this->State->Locations[this->Position]);
     cmSystemTools::CollapseFullPath(this->State->Locations[this->Position]);
+
+  cmSystemTools::SplitPath(
+      this->State->Locations[this->Position],
+      this->State->CurrentSourceDirectoryComponents[this->Position]);
+  this->ComputeRelativePathTopSource();
 }
 }
 
 
 const char* cmState::Snapshot::GetCurrentBinaryDirectory() const
 const char* cmState::Snapshot::GetCurrentBinaryDirectory() const
@@ -521,6 +634,43 @@ void cmState::Snapshot::SetCurrentBinaryDirectory(std::string const& dir)
   this->State->OutputLocations[this->Position] =
   this->State->OutputLocations[this->Position] =
     cmSystemTools::CollapseFullPath(
     cmSystemTools::CollapseFullPath(
         this->State->OutputLocations[this->Position]);
         this->State->OutputLocations[this->Position]);
+
+  cmSystemTools::SplitPath(
+      this->State->OutputLocations[this->Position],
+      this->State->CurrentBinaryDirectoryComponents[this->Position]);
+  this->ComputeRelativePathTopBinary();
+}
+
+std::vector<std::string> const&
+cmState::Snapshot::GetCurrentSourceDirectoryComponents()
+{
+  return this->State->CurrentSourceDirectoryComponents[this->Position];
+}
+
+std::vector<std::string> const&
+cmState::Snapshot::GetCurrentBinaryDirectoryComponents()
+{
+  return this->State->CurrentBinaryDirectoryComponents[this->Position];
+}
+
+const char* cmState::Snapshot::GetRelativePathTopSource() const
+{
+  return this->State->RelativePathTopSource[this->Position].c_str();
+}
+
+const char* cmState::Snapshot::GetRelativePathTopBinary() const
+{
+  return this->State->RelativePathTopBinary[this->Position].c_str();
+}
+
+void cmState::Snapshot::SetRelativePathTopSource(const char* dir)
+{
+  this->State->RelativePathTopSource[this->Position] = dir;
+}
+
+void cmState::Snapshot::SetRelativePathTopBinary(const char* dir)
+{
+  this->State->RelativePathTopBinary[this->Position] = dir;
 }
 }
 
 
 bool cmState::Snapshot::IsValid() const
 bool cmState::Snapshot::IsValid() const

+ 28 - 0
Source/cmState.h

@@ -36,9 +36,21 @@ public:
     const char* GetCurrentBinaryDirectory() const;
     const char* GetCurrentBinaryDirectory() const;
     void SetCurrentBinaryDirectory(std::string const& dir);
     void SetCurrentBinaryDirectory(std::string const& dir);
 
 
+    std::vector<std::string> const& GetCurrentSourceDirectoryComponents();
+    std::vector<std::string> const& GetCurrentBinaryDirectoryComponents();
+
+    const char* GetRelativePathTopSource() const;
+    const char* GetRelativePathTopBinary() const;
+    void SetRelativePathTopSource(const char* dir);
+    void SetRelativePathTopBinary(const char* dir);
+
     bool IsValid() const;
     bool IsValid() const;
     Snapshot GetParent() const;
     Snapshot GetParent() const;
 
 
+  private:
+    void ComputeRelativePathTopSource();
+    void ComputeRelativePathTopBinary();
+
   private:
   private:
     friend class cmState;
     friend class cmState;
     cmState* State;
     cmState* State;
@@ -123,6 +135,9 @@ public:
   const char* GetBinaryDirectory() const;
   const char* GetBinaryDirectory() const;
   void SetBinaryDirectory(std::string const& binaryDirectory);
   void SetBinaryDirectory(std::string const& binaryDirectory);
 
 
+  std::vector<std::string> const& GetSourceDirectoryComponents() const;
+  std::vector<std::string> const& GetBinaryDirectoryComponents() const;
+
 private:
 private:
   std::map<cmProperty::ScopeType, cmPropertyDefinitionMap> PropertyDefinitions;
   std::map<cmProperty::ScopeType, cmPropertyDefinitionMap> PropertyDefinitions;
   std::vector<std::string> EnabledLanguages;
   std::vector<std::string> EnabledLanguages;
@@ -132,6 +147,19 @@ private:
   std::vector<std::string> Locations;
   std::vector<std::string> Locations;
   std::vector<std::string> OutputLocations;
   std::vector<std::string> OutputLocations;
   std::vector<PositionType> ParentPositions;
   std::vector<PositionType> ParentPositions;
+
+  std::vector<std::vector<std::string> > CurrentSourceDirectoryComponents;
+  std::vector<std::vector<std::string> > CurrentBinaryDirectoryComponents;
+  // The top-most directories for relative path conversion.  Both the
+  // source and destination location of a relative path conversion
+  // must be underneath one of these directories (both under source or
+  // both under binary) in order for the relative path to be evaluated
+  // safely by the build tools.
+  std::vector<std::string> RelativePathTopSource;
+  std::vector<std::string> RelativePathTopBinary;
+
+  std::vector<std::string> SourceDirectoryComponents;
+  std::vector<std::string> BinaryDirectoryComponents;
   std::string SourceDirectory;
   std::string SourceDirectory;
   std::string BinaryDirectory;
   std::string BinaryDirectory;
   bool IsInTryCompile;
   bool IsInTryCompile;

+ 5 - 0
Source/cmake.cxx

@@ -1925,6 +1925,8 @@ int cmake::CheckBuildSystem()
   // Read the rerun check file and use it to decide whether to do the
   // Read the rerun check file and use it to decide whether to do the
   // global generate.
   // global generate.
   cmake cm;
   cmake cm;
+  cm.SetHomeDirectory("");
+  cm.SetHomeOutputDirectory("");
   cmGlobalGenerator gg;
   cmGlobalGenerator gg;
   gg.SetCMakeInstance(&cm);
   gg.SetCMakeInstance(&cm);
   cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator());
   cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator());
@@ -2565,6 +2567,9 @@ int cmake::Build(const std::string& dir,
                  const std::vector<std::string>& nativeOptions,
                  const std::vector<std::string>& nativeOptions,
                  bool clean)
                  bool clean)
 {
 {
+
+  this->SetHomeDirectory("");
+  this->SetHomeOutputDirectory("");
   if(!cmSystemTools::FileIsDirectory(dir))
   if(!cmSystemTools::FileIsDirectory(dir))
     {
     {
     std::cerr << "Error: " << dir << " is not a directory\n";
     std::cerr << "Error: " << dir << " is not a directory\n";

+ 6 - 0
Source/cmakemain.cxx

@@ -214,6 +214,8 @@ int do_cmake(int ac, char const* const* av)
     {
     {
     // Construct and print requested documentation.
     // Construct and print requested documentation.
     cmake hcm;
     cmake hcm;
+    hcm.SetHomeDirectory("");
+    hcm.SetHomeOutputDirectory("");
     hcm.AddCMakePaths();
     hcm.AddCMakePaths();
 
 
     // the command line args are processed here so that you can do
     // the command line args are processed here so that you can do
@@ -317,10 +319,14 @@ int do_cmake(int ac, char const* const* av)
   if (sysinfo)
   if (sysinfo)
     {
     {
     cmake cm;
     cmake cm;
+    cm.SetHomeDirectory("");
+    cm.SetHomeOutputDirectory("");
     int ret = cm.GetSystemInformation(args);
     int ret = cm.GetSystemInformation(args);
     return ret;
     return ret;
     }
     }
   cmake cm;
   cmake cm;
+  cm.SetHomeDirectory("");
+  cm.SetHomeOutputDirectory("");
   cmSystemTools::SetMessageCallback(cmakemainMessageCallback, (void *)&cm);
   cmSystemTools::SetMessageCallback(cmakemainMessageCallback, (void *)&cm);
   cm.SetProgressCallback(cmakemainProgressCallback, (void *)&cm);
   cm.SetProgressCallback(cmakemainProgressCallback, (void *)&cm);
   cm.SetWorkingMode(workingMode);
   cm.SetWorkingMode(workingMode);

+ 2 - 0
Source/ctest.cxx

@@ -160,6 +160,8 @@ int main (int argc, char const* const* argv)
     if(doc.CheckOptions(argc, argv))
     if(doc.CheckOptions(argc, argv))
       {
       {
       cmake hcm;
       cmake hcm;
+      hcm.SetHomeDirectory("");
+      hcm.SetHomeOutputDirectory("");
       hcm.AddCMakePaths();
       hcm.AddCMakePaths();
 
 
       // Construct and print requested documentation.
       // Construct and print requested documentation.