This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  e61400cafdfce42049cbd7c88cf56ddc4217b483 (commit)
       via  92d14662cd0b5adebe17c3ae0c1662fc9ee5f728 (commit)
      from  229c3f4b30b3cd49d12e2ad74fdf92c7503f0bdc (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e61400cafdfce42049cbd7c88cf56ddc4217b483
commit e61400cafdfce42049cbd7c88cf56ddc4217b483
Merge: 229c3f4 92d1466
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sat Sep 17 13:48:22 2016 -0400
Commit:     CMake Topic Stage <kwro...@kitware.com>
CommitDate: Sat Sep 17 13:48:22 2016 -0400

    Merge topic 'cleanup-Convert' into next
    
    92d14662 Revert most of this branch


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=92d14662cd0b5adebe17c3ae0c1662fc9ee5f728
commit 92d14662cd0b5adebe17c3ae0c1662fc9ee5f728
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sat Sep 17 19:47:03 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Sep 17 19:47:18 2016 +0200

    Revert most of this branch

diff --git a/Source/cmCommonTargetGenerator.cxx 
b/Source/cmCommonTargetGenerator.cxx
index fdf0b0e..6167e2c 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -47,6 +47,13 @@ std::string const& cmCommonTargetGenerator::GetConfigName() 
const
   return this->ConfigName;
 }
 
+std::string cmCommonTargetGenerator::Convert(
+  std::string const& source, cmOutputConverter::RelativeRoot relative,
+  cmOutputConverter::OutputFormat output)
+{
+  return this->LocalGenerator->Convert(source, relative, output);
+}
+
 const char* cmCommonTargetGenerator::GetFeature(const std::string& feature)
 {
   return this->GeneratorTarget->GetFeature(feature, this->ConfigName);
@@ -197,9 +204,8 @@ std::string cmCommonTargetGenerator::GetManifests()
   std::vector<std::string> manifests;
   for (std::vector<cmSourceFile const*>::iterator mi = manifest_srcs.begin();
        mi != manifest_srcs.end(); ++mi) {
-    manifests.push_back(this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetWorkingDirectory(), (*mi)->GetFullPath()),
+    manifests.push_back(this->Convert(
+      (*mi)->GetFullPath(), this->LocalGenerator->GetWorkingDirectory(),
       cmOutputConverter::SHELL));
   }
 
diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h
index 4c52fe5..b433c18 100644
--- a/Source/cmCommonTargetGenerator.h
+++ b/Source/cmCommonTargetGenerator.h
@@ -57,6 +57,10 @@ protected:
   // The windows module definition source file (.def), if any.
   cmSourceFile const* ModuleDefinitionFile;
 
+  std::string Convert(std::string const& source,
+                      cmOutputConverter::RelativeRoot relative,
+                      cmOutputConverter::OutputFormat output);
+
   void AppendFortranFormatFlags(std::string& flags,
                                 cmSourceFile const& source);
 
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index 3296ffc..fbbf42f 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -239,18 +239,19 @@ bool cmDependsC::WriteDependencies(const 
std::set<std::string>& sources,
   // written by the original local generator for this directory
   // convert the dependencies to paths relative to the home output
   // directory.  We must do the same here.
-  std::string binDir = this->LocalGenerator->GetBinaryDirectory();
-  std::string obj_i = this->LocalGenerator->ConvertToRelativePath(binDir, obj);
-  std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i.c_str());
+  std::string obj_i = this->LocalGenerator->ConvertToRelativePath(
+    obj, cmOutputConverter::HOME_OUTPUT);
+  std::string obj_m = this->LocalGenerator->ConvertToOutputFormat(
+    obj_i, cmOutputConverter::MAKERULE);
   internalDepends << obj_i << std::endl;
 
   for (std::set<std::string>::const_iterator i = dependencies.begin();
        i != dependencies.end(); ++i) {
-    makeDepends
-      << obj_m << ": "
-      << cmSystemTools::ConvertToOutputPath(
-           this->LocalGenerator->ConvertToRelativePath(binDir, *i).c_str())
-      << std::endl;
+    makeDepends << obj_m << ": "
+                << this->LocalGenerator->Convert(
+                     *i, cmOutputConverter::HOME_OUTPUT,
+                     cmOutputConverter::MAKERULE)
+                << std::endl;
     internalDepends << " " << *i << std::endl;
   }
   makeDepends << std::endl;
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index ba0617f..eb4c1ec 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -189,8 +189,6 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
     cmGeneratedFileStream fcStream(fcName.c_str());
     fcStream << "# Remove fortran modules provided by this target.\n";
     fcStream << "FILE(REMOVE";
-    std::string currentBinDir =
-      this->LocalGenerator->GetCurrentBinaryDirectory();
     for (std::set<std::string>::const_iterator i = provides.begin();
          i != provides.end(); ++i) {
       std::string mod_upper = mod_dir;
@@ -207,16 +205,16 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
       stamp += ".mod.stamp";
       fcStream << "\n";
       fcStream << "  \""
-               << this->LocalGenerator->ConvertToRelativePath(currentBinDir,
-                                                              mod_lower)
+               << this->LocalGenerator->ConvertToRelativePath(
+                    mod_lower, cmOutputConverter::START_OUTPUT)
                << "\"\n";
       fcStream << "  \""
-               << this->LocalGenerator->ConvertToRelativePath(currentBinDir,
-                                                              mod_upper)
+               << this->LocalGenerator->ConvertToRelativePath(
+                    mod_upper, cmOutputConverter::START_OUTPUT)
                << "\"\n";
       fcStream << "  \""
-               << this->LocalGenerator->ConvertToRelativePath(currentBinDir,
-                                                              stamp)
+               << this->LocalGenerator->ConvertToRelativePath(
+                    stamp, cmOutputConverter::START_OUTPUT)
                << "\"\n";
     }
     fcStream << "  )\n";
@@ -331,18 +329,19 @@ bool cmDependsFortran::WriteDependenciesReal(const char* 
obj,
   const char* src = info.Source.c_str();
 
   // Write the include dependencies to the output stream.
-  std::string binDir = this->LocalGenerator->GetBinaryDirectory();
-  std::string obj_i = this->LocalGenerator->ConvertToRelativePath(binDir, obj);
-  std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i.c_str());
+  std::string obj_i = this->LocalGenerator->ConvertToRelativePath(
+    obj, cmOutputConverter::HOME_OUTPUT);
+  std::string obj_m = this->LocalGenerator->ConvertToOutputFormat(
+    obj_i, cmOutputConverter::MAKERULE);
   internalDepends << obj_i << std::endl;
   internalDepends << " " << src << std::endl;
   for (std::set<std::string>::const_iterator i = info.Includes.begin();
        i != info.Includes.end(); ++i) {
-    makeDepends
-      << obj_m << ": "
-      << cmSystemTools::ConvertToOutputPath(
-           this->LocalGenerator->ConvertToRelativePath(binDir, *i).c_str())
-      << std::endl;
+    makeDepends << obj_m << ": "
+                << this->LocalGenerator->Convert(
+                     *i, cmOutputConverter::HOME_OUTPUT,
+                     cmOutputConverter::MAKERULE)
+                << std::endl;
     internalDepends << " " << *i << std::endl;
   }
   makeDepends << std::endl;
@@ -367,8 +366,8 @@ bool cmDependsFortran::WriteDependenciesReal(const char* 
obj,
       proxy += "/";
       proxy += *i;
       proxy += ".mod.proxy";
-      proxy = cmSystemTools::ConvertToOutputPath(
-        this->LocalGenerator->ConvertToRelativePath(binDir, proxy).c_str());
+      proxy = this->LocalGenerator->Convert(
+        proxy, cmOutputConverter::HOME_OUTPUT, cmOutputConverter::MAKERULE);
 
       // since we require some things add them to our list of requirements
       makeDepends << obj_m << ".requires: " << proxy << std::endl;
@@ -383,17 +382,17 @@ bool cmDependsFortran::WriteDependenciesReal(const char* 
obj,
     }
     if (!required->second.empty()) {
       // This module is known.  Depend on its timestamp file.
-      std::string stampFile = cmSystemTools::ConvertToOutputPath(
-        this->LocalGenerator->ConvertToRelativePath(binDir, required->second)
-          .c_str());
+      std::string stampFile = this->LocalGenerator->Convert(
+        required->second, cmOutputConverter::HOME_OUTPUT,
+        cmOutputConverter::MAKERULE);
       makeDepends << obj_m << ": " << stampFile << "\n";
     } else {
       // This module is not known to CMake.  Try to locate it where
       // the compiler will and depend on that.
       std::string module;
       if (this->FindModule(*i, module)) {
-        module = cmSystemTools::ConvertToOutputPath(
-          this->LocalGenerator->ConvertToRelativePath(binDir, module).c_str());
+        module = this->LocalGenerator->Convert(
+          module, cmOutputConverter::HOME_OUTPUT, cmOutputConverter::MAKERULE);
         makeDepends << obj_m << ": " << module << "\n";
       }
     }
@@ -406,8 +405,8 @@ bool cmDependsFortran::WriteDependenciesReal(const char* 
obj,
     proxy += "/";
     proxy += *i;
     proxy += ".mod.proxy";
-    proxy = cmSystemTools::ConvertToOutputPath(
-      this->LocalGenerator->ConvertToRelativePath(binDir, proxy).c_str());
+    proxy = this->LocalGenerator->Convert(
+      proxy, cmOutputConverter::HOME_OUTPUT, cmOutputConverter::MAKERULE);
     makeDepends << proxy << ": " << obj_m << ".provides" << std::endl;
   }
 
@@ -428,16 +427,14 @@ bool cmDependsFortran::WriteDependenciesReal(const char* 
obj,
       std::string modFile = mod_dir;
       modFile += "/";
       modFile += *i;
-      modFile = this->LocalGenerator->ConvertToOutputFormat(
-        this->LocalGenerator->ConvertToRelativePath(binDir, modFile),
-        cmOutputConverter::SHELL);
+      modFile = this->LocalGenerator->Convert(
+        modFile, cmOutputConverter::HOME_OUTPUT, cmOutputConverter::SHELL);
       std::string stampFile = stamp_dir;
       stampFile += "/";
       stampFile += m;
       stampFile += ".mod.stamp";
-      stampFile = this->LocalGenerator->ConvertToOutputFormat(
-        this->LocalGenerator->ConvertToRelativePath(binDir, stampFile),
-        cmOutputConverter::SHELL);
+      stampFile = this->LocalGenerator->Convert(
+        stampFile, cmOutputConverter::HOME_OUTPUT, cmOutputConverter::SHELL);
       makeDepends << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod " << modFile
                   << " " << stampFile;
       cmMakefile* mf = this->LocalGenerator->GetMakefile();
@@ -456,8 +453,8 @@ bool cmDependsFortran::WriteDependenciesReal(const char* 
obj,
     // the target finishes building.
     std::string driver = this->TargetDirectory;
     driver += "/build";
-    driver = cmSystemTools::ConvertToOutputPath(
-      this->LocalGenerator->ConvertToRelativePath(binDir, driver).c_str());
+    driver = this->LocalGenerator->Convert(
+      driver, cmOutputConverter::HOME_OUTPUT, cmOutputConverter::MAKERULE);
     makeDepends << driver << ": " << obj_m << ".provides.build\n";
   }
 
diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx 
b/Source/cmExportBuildAndroidMKGenerator.cxx
index d5c2fee..96080a9 100644
--- a/Source/cmExportBuildAndroidMKGenerator.cxx
+++ b/Source/cmExportBuildAndroidMKGenerator.cxx
@@ -48,7 +48,8 @@ void 
cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
   os << "LOCAL_MODULE := ";
   os << targetName << "\n";
   os << "LOCAL_SRC_FILES := ";
-  std::string path = 
cmSystemTools::ConvertToOutputPath(target->GetFullPath().c_str());
+  std::string path = target->GetLocalGenerator()->ConvertToOutputFormat(
+    target->GetFullPath(), cmOutputConverter::MAKERULE);
   os << path << "\n";
 }
 
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx 
b/Source/cmExtraEclipseCDT4Generator.cxx
index 61f2851..5a98e34 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -914,7 +914,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
     const std::vector<cmGeneratorTarget*> targets =
       (*it)->GetGeneratorTargets();
     std::string subdir = (*it)->ConvertToRelativePath(
-      this->HomeOutputDirectory, (*it)->GetCurrentBinaryDirectory());
+      (*it)->GetCurrentBinaryDirectory(), cmOutputConverter::HOME_OUTPUT);
     if (subdir == ".") {
       subdir = "";
     }
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 2ea2990..64c9870 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -2578,7 +2578,7 @@ void cmGlobalGenerator::AddRuleHash(const 
std::vector<std::string>& outputs,
   // Shorten the output name (in expected use case).
   cmOutputConverter converter(this->GetMakefiles()[0]->GetStateSnapshot());
   std::string fname = converter.ConvertToRelativePath(
-    this->GetMakefiles()[0]->GetState()->GetBinaryDirectory(), outputs[0]);
+    outputs[0], cmOutputConverter::HOME_OUTPUT);
 
   // Associate the hash with this output.
   this->RuleHashes[fname] = hash;
diff --git a/Source/cmGlobalNinjaGenerator.cxx 
b/Source/cmGlobalNinjaGenerator.cxx
index bd65366..30a05a0 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -760,8 +760,8 @@ std::string 
cmGlobalNinjaGenerator::ConvertToNinjaPath(const std::string& path)
 {
   cmLocalNinjaGenerator* ng =
     static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]);
-  std::string convPath = ng->ConvertToRelativePath(
-    this->LocalGenerators[0]->GetState()->GetBinaryDirectory(), path);
+  std::string convPath =
+    ng->ConvertToRelativePath(path, cmOutputConverter::HOME_OUTPUT);
   convPath = this->NinjaOutputPath(convPath);
 #ifdef _WIN32
   std::replace(convPath.begin(), convPath.end(), '/', '\\');
@@ -774,8 +774,8 @@ std::string 
cmGlobalNinjaGenerator::ConvertToNinjaFolderRule(
 {
   cmLocalNinjaGenerator* ng =
     static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]);
-  std::string convPath = ng->ConvertToRelativePath(
-    this->LocalGenerators[0]->GetState()->GetSourceDirectory(), path + "/all");
+  std::string convPath =
+    ng->ConvertToRelativePath(path + "/all", cmOutputConverter::HOME);
   convPath = this->NinjaOutputPath(convPath);
 #ifdef _WIN32
   std::replace(convPath.begin(), convPath.end(), '/', '\\');
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx 
b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 52ae469..d90ebf0 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -319,15 +319,18 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
   std::string cache = this->GetCMakeInstance()->GetHomeOutputDirectory();
   cache += "/CMakeCache.txt";
 
-  std::string currentBinDir = lg->GetCurrentBinaryDirectory();
   // Save the list to the cmake file.
   cmakefileStream
     << "# The top level Makefile was generated from the following files:\n"
     << "set(CMAKE_MAKEFILE_DEPENDS\n"
-    << "  \"" << lg->ConvertToRelativePath(currentBinDir, cache) << "\"\n";
+    << "  \""
+    << lg->ConvertToRelativePath(cache, cmOutputConverter::START_OUTPUT)
+    << "\"\n";
   for (std::vector<std::string>::const_iterator i = lfiles.begin();
        i != lfiles.end(); ++i) {
-    cmakefileStream << "  \"" << lg->ConvertToRelativePath(currentBinDir, *i)
+    cmakefileStream << "  \""
+                    << lg->ConvertToRelativePath(
+                         *i, cmOutputConverter::START_OUTPUT)
                     << "\"\n";
   }
   cmakefileStream << "  )\n\n";
@@ -341,14 +344,15 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
   cmakefileStream << "# The corresponding makefile is:\n"
                   << "set(CMAKE_MAKEFILE_OUTPUTS\n"
                   << "  \""
-                  << lg->ConvertToRelativePath(currentBinDir, makefileName)
+                  << lg->ConvertToRelativePath(makefileName,
+                                               cmOutputConverter::START_OUTPUT)
                   << "\"\n"
-                  << "  \"" << lg->ConvertToRelativePath(currentBinDir, check)
+                  << "  \""
+                  << lg->ConvertToRelativePath(check,
+                                               cmOutputConverter::START_OUTPUT)
                   << "\"\n";
   cmakefileStream << "  )\n\n";
 
-  const std::string binDir = lg->GetBinaryDirectory();
-
   // CMake must rerun if a byproduct is missing.
   {
     cmakefileStream << "# Byproducts of CMake generate step:\n"
@@ -357,7 +361,9 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
       lg->GetMakefile()->GetOutputFiles();
     for (std::vector<std::string>::const_iterator k = outfiles.begin();
          k != outfiles.end(); ++k) {
-      cmakefileStream << "  \"" << lg->ConvertToRelativePath(binDir, *k)
+      cmakefileStream << "  \""
+                      << lg->ConvertToRelativePath(
+                           *k, cmOutputConverter::HOME_OUTPUT)
                       << "\"\n";
     }
 
@@ -369,7 +375,9 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
       tmpStr = lg->GetCurrentBinaryDirectory();
       tmpStr += cmake::GetCMakeFilesDirectory();
       tmpStr += "/CMakeDirectoryInformation.cmake";
-      cmakefileStream << "  \"" << lg->ConvertToRelativePath(binDir, tmpStr)
+      cmakefileStream << "  \""
+                      << lg->ConvertToRelativePath(
+                           tmpStr, cmOutputConverter::HOME_OUTPUT)
                       << "\"\n";
     }
     cmakefileStream << "  )\n\n";
@@ -480,10 +488,9 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
   }
 
   // Begin the directory-level rules section.
-  std::string dir = cmSystemTools::ConvertToOutputPath(
-    lg->ConvertToRelativePath(lg->GetBinaryDirectory(),
-                              lg->GetCurrentBinaryDirectory())
-      .c_str());
+  std::string dir = lg->GetCurrentBinaryDirectory();
+  dir = lg->Convert(dir, cmOutputConverter::HOME_OUTPUT,
+                    cmOutputConverter::MAKERULE);
   lg->WriteDivider(ruleFileStream);
   ruleFileStream << "# Directory level rules for directory " << dir << "\n\n";
 
@@ -531,8 +538,7 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
       tname += "/fast";
     }
     cmOutputConverter conv(mf->GetStateSnapshot());
-    tname =
-      conv.ConvertToRelativePath(mf->GetState()->GetBinaryDirectory(), tname);
+    tname = conv.ConvertToRelativePath(tname, cmOutputConverter::HOME_OUTPUT);
     cmSystemTools::ConvertToOutputSlashes(tname);
     makeCommand.push_back(tname);
     if (this->Makefiles.empty()) {
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx 
b/Source/cmGlobalVisualStudio7Generator.cxx
index 7664b02..0dc4497 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -382,7 +382,6 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
 {
   VisualStudioFolders.clear();
 
-  std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
   for (OrderedTargetDependSet::const_iterator tt = projectTargets.begin();
        tt != projectTargets.end(); ++tt) {
     cmGeneratorTarget const* target = *tt;
@@ -406,7 +405,8 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
       if (vcprojName) {
         cmLocalGenerator* lg = target->GetLocalGenerator();
         std::string dir = lg->GetCurrentBinaryDirectory();
-        dir = root->ConvertToRelativePath(rootBinaryDir, dir.c_str());
+        dir = root->ConvertToRelativePath(dir.c_str(),
+                                          cmOutputConverter::START_OUTPUT);
         if (dir == ".") {
           dir = ""; // msbuild cannot handle ".\" prefix
         }
diff --git a/Source/cmGlobalXCodeGenerator.cxx 
b/Source/cmGlobalXCodeGenerator.cxx
index 581af3e..5653820 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -351,6 +351,13 @@ void 
cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator* root)
 {
   this->CurrentProject = root->GetProjectName();
   this->SetCurrentLocalGenerator(root);
+  cmSystemTools::SplitPath(
+    this->CurrentLocalGenerator->GetCurrentSourceDirectory(),
+    this->ProjectSourceDirectoryComponents);
+  cmSystemTools::SplitPath(
+    this->CurrentLocalGenerator->GetCurrentBinaryDirectory(),
+    this->ProjectOutputDirectoryComponents);
+
   this->CurrentXCodeHackMakefile = root->GetCurrentBinaryDirectory();
   this->CurrentXCodeHackMakefile += "/CMakeScripts";
   cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile.c_str());
@@ -889,6 +896,10 @@ void 
cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator* gen)
 {
   this->CurrentLocalGenerator = gen;
   this->CurrentMakefile = gen->GetMakefile();
+  std::string outdir = cmSystemTools::CollapseFullPath(
+    this->CurrentLocalGenerator->GetCurrentBinaryDirectory());
+  cmSystemTools::SplitPath(outdir, this->CurrentOutputDirectoryComponents);
+
   // Select the current set of configuration types.
   this->CurrentConfigurationTypes.clear();
   this->CurrentMakefile->GetConfigurations(this->CurrentConfigurationTypes);
@@ -3317,14 +3328,14 @@ std::string 
cmGlobalXCodeGenerator::RelativeToSource(const char* p)
 {
   // We force conversion because Xcode breakpoints do not work unless
   // they are in a file named relative to the source tree.
-  return this->CurrentLocalGenerator->ForceToRelativePath(
-    this->CurrentLocalGenerator->GetCurrentSourceDirectory(), p);
+  return this->CurrentLocalGenerator->ConvertToRelativePath(
+    this->ProjectSourceDirectoryComponents, p, true);
 }
 
 std::string cmGlobalXCodeGenerator::RelativeToBinary(const char* p)
 {
   return this->CurrentLocalGenerator->ConvertToRelativePath(
-    this->CurrentLocalGenerator->GetCurrentBinaryDirectory(), p);
+    this->ProjectOutputDirectoryComponents, p);
 }
 
 std::string cmGlobalXCodeGenerator::XCodeEscapePath(const std::string& p)
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index c9fc9b3..303dfa0 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -241,6 +241,9 @@ private:
   std::string CurrentXCodeHackMakefile;
   std::string CurrentProject;
   std::set<std::string> TargetDoneSet;
+  std::vector<std::string> CurrentOutputDirectoryComponents;
+  std::vector<std::string> ProjectSourceDirectoryComponents;
+  std::vector<std::string> ProjectOutputDirectoryComponents;
   std::map<std::string, cmXCodeObject*> GroupMap;
   std::map<std::string, cmXCodeObject*> GroupNameMap;
   std::map<std::string, cmXCodeObject*> TargetGroup;
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 7ab7de1..14bb81e 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -404,8 +404,8 @@ void cmListFileBacktrace::PrintTitle(std::ostream& out) 
const
   cmOutputConverter converter(this->Bottom);
   cmListFileContext lfc = *this->Cur;
   if (!this->Bottom.GetState()->GetIsInTryCompile()) {
-    lfc.FilePath = converter.ConvertToRelativePath(
-      this->Bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
+    lfc.FilePath =
+      converter.ConvertToRelativePath(lfc.FilePath, cmOutputConverter::HOME);
   }
   out << (lfc.Line ? " at " : " in ") << lfc;
 }
@@ -430,8 +430,8 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) 
const
     }
     cmListFileContext lfc = *i;
     if (!this->Bottom.GetState()->GetIsInTryCompile()) {
-      lfc.FilePath = converter.ConvertToRelativePath(
-        this->Bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
+      lfc.FilePath =
+        converter.ConvertToRelativePath(lfc.FilePath, cmOutputConverter::HOME);
     }
     out << "  " << lfc << "\n";
   }
diff --git a/Source/cmLocalCommonGenerator.cxx 
b/Source/cmLocalCommonGenerator.cxx
index 97323c9..0e79293 100644
--- a/Source/cmLocalCommonGenerator.cxx
+++ b/Source/cmLocalCommonGenerator.cxx
@@ -18,9 +18,8 @@
 
 class cmGlobalGenerator;
 
-cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg,
-                                               cmMakefile* mf,
-                                               std::string const& wd)
+cmLocalCommonGenerator::cmLocalCommonGenerator(
+  cmGlobalGenerator* gg, cmMakefile* mf, cmOutputConverter::RelativeRoot wd)
   : cmLocalGenerator(gg, mf)
   , WorkingDirectory(wd)
 {
@@ -56,9 +55,8 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags(
   // Add a module output directory flag if necessary.
   std::string mod_dir = target->GetFortranModuleDirectory();
   if (!mod_dir.empty()) {
-    mod_dir = this->ConvertToOutputFormat(
-      this->ConvertToRelativePath(this->WorkingDirectory, mod_dir),
-      cmOutputConverter::SHELL);
+    mod_dir =
+      this->Convert(mod_dir, this->WorkingDirectory, cmOutputConverter::SHELL);
   } else {
     mod_dir =
       this->Makefile->GetSafeDefinition("CMAKE_Fortran_MODDIR_DEFAULT");
diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h
index 9454739..9012afd 100644
--- a/Source/cmLocalCommonGenerator.h
+++ b/Source/cmLocalCommonGenerator.h
@@ -30,18 +30,21 @@ class cmLocalCommonGenerator : public cmLocalGenerator
 {
 public:
   cmLocalCommonGenerator(cmGlobalGenerator* gg, cmMakefile* mf,
-                         std::string const& wd);
+                         cmOutputConverter::RelativeRoot wd);
   ~cmLocalCommonGenerator() CM_OVERRIDE;
 
   std::string const& GetConfigName() { return this->ConfigName; }
 
-  std::string GetWorkingDirectory() const { return this->WorkingDirectory; }
+  cmOutputConverter::RelativeRoot GetWorkingDirectory() const
+  {
+    return this->WorkingDirectory;
+  }
 
   std::string GetTargetFortranFlags(cmGeneratorTarget const* target,
                                     std::string const& config) CM_OVERRIDE;
 
 protected:
-  std::string WorkingDirectory;
+  cmOutputConverter::RelativeRoot WorkingDirectory;
 
   void SetConfigName();
   std::string ConfigName;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 5dbe57c..a76bed3 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -177,12 +177,10 @@ void cmLocalGenerator::GenerateTestFiles()
   }
   typedef std::vector<cmState::Snapshot> vec_t;
   vec_t const& children = this->Makefile->GetStateSnapshot().GetChildren();
-  std::string parentBinDir = this->GetCurrentBinaryDirectory();
   for (vec_t::const_iterator i = children.begin(); i != children.end(); ++i) {
     // TODO: Use add_subdirectory instead?
     std::string outP = i->GetDirectory().GetCurrentBinary();
-    outP = this->ConvertToRelativePath(parentBinDir,
-                                       outP);
+    outP = this->ConvertToRelativePath(outP, START_OUTPUT);
     outP = cmOutputConverter::EscapeForCMake(outP);
     fout << "subdirs(" << outP << ")" << std::endl;
   }
@@ -1410,9 +1408,7 @@ std::string 
cmLocalGenerator::ConvertToLinkReference(std::string const& lib,
 #endif
 
   // Normal behavior.
-  return this->ConvertToOutputFormat(
-    this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), lib),
-    format);
+  return this->Convert(lib, START_OUTPUT, format);
 }
 
 /**
@@ -2246,11 +2242,11 @@ std::string cmLocalGenerator::ConstructComment(
     std::string comment;
     comment = "Generating ";
     const char* sep = "";
-    std::string currentBinaryDir = this->GetCurrentBinaryDirectory();
     for (std::vector<std::string>::const_iterator o = ccg.GetOutputs().begin();
          o != ccg.GetOutputs().end(); ++o) {
       comment += sep;
-      comment += this->ConvertToRelativePath(currentBinaryDir, *o);
+      comment +=
+        this->ConvertToRelativePath(*o, cmOutputConverter::START_OUTPUT);
       sep = ", ";
     }
     return comment;
@@ -2518,15 +2514,14 @@ std::string 
cmLocalGenerator::GetObjectFileNameWithoutTarget(
   const char* fullPath = source.GetFullPath().c_str();
 
   // Try referencing the source relative to the source tree.
-  std::string relFromSource =
-    this->ConvertToRelativePath(this->GetCurrentSourceDirectory(), fullPath);
+  std::string relFromSource = this->ConvertToRelativePath(fullPath, START);
   assert(!relFromSource.empty());
   bool relSource = !cmSystemTools::FileIsFullPath(relFromSource.c_str());
   bool subSource = relSource && relFromSource[0] != '.';
 
   // Try referencing the source relative to the binary tree.
   std::string relFromBinary =
-    this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), fullPath);
+    this->ConvertToRelativePath(fullPath, START_OUTPUT);
   assert(!relFromBinary.empty());
   bool relBinary = !cmSystemTools::FileIsFullPath(relFromBinary.c_str());
   bool subBinary = relBinary && relFromBinary[0] != '.';
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 82e4d2c..6793f84 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -34,7 +34,7 @@
 
 cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
                                              cmMakefile* mf)
-  : cmLocalCommonGenerator(gg, mf, mf->GetState()->GetBinaryDirectory())
+  : cmLocalCommonGenerator(gg, mf, cmOutputConverter::HOME_OUTPUT)
   , HomeRelativeOutputPath("")
 {
   this->TargetImplib = "$TARGET_IMPLIB";
@@ -51,7 +51,7 @@ void cmLocalNinjaGenerator::Generate()
   // Compute the path to use when referencing the current output
   // directory from the top output directory.
   this->HomeRelativeOutputPath = this->ConvertToRelativePath(
-    this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory());
+    this->GetCurrentBinaryDirectory(), cmOutputConverter::HOME_OUTPUT);
   if (this->HomeRelativeOutputPath == ".") {
     this->HomeRelativeOutputPath = "";
   }
@@ -145,8 +145,7 @@ std::string 
cmLocalNinjaGenerator::ConvertToIncludeReference(
     return this->ConvertToOutputFormat(cmSystemTools::CollapseFullPath(path),
                                        format);
   }
-  return this->ConvertToOutputFormat(
-    this->ConvertToRelativePath(this->GetBinaryDirectory(), path), format);
+  return this->Convert(path, cmOutputConverter::HOME_OUTPUT, format);
 }
 
 // Private methods.
@@ -500,10 +499,8 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
   const std::vector<std::string>& outputs = ccg.GetOutputs();
   if (!outputs.empty()) {
     if (ccg.GetWorkingDirectory().empty()) {
-      output = this->ConvertToOutputFormat(
-        this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(),
-                                    outputs[0]),
-        cmOutputConverter::SHELL);
+      output = this->Convert(outputs[0], cmOutputConverter::START_OUTPUT,
+                             cmOutputConverter::SHELL);
     } else {
       output =
         this->ConvertToOutputFormat(outputs[0], cmOutputConverter::SHELL);
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx 
b/Source/cmLocalUnixMakefileGenerator3.cxx
index 23d1571..611c502 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -94,7 +94,7 @@ static std::string cmSplitExtension(std::string const& in, 
std::string& base)
 
 cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3(
   cmGlobalGenerator* gg, cmMakefile* mf)
-  : cmLocalCommonGenerator(gg, mf, mf->GetCurrentBinaryDirectory())
+  : cmLocalCommonGenerator(gg, mf, cmOutputConverter::START_OUTPUT)
 {
   this->MakefileVariableSize = 0;
   this->ColorMakefile = false;
@@ -151,7 +151,7 @@ void 
cmLocalUnixMakefileGenerator3::ComputeHomeRelativeOutputPath()
   // Compute the path to use when referencing the current output
   // directory from the top output directory.
   this->HomeRelativeOutputPath = this->ConvertToRelativePath(
-    this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory());
+    this->GetCurrentBinaryDirectory(), cmOutputConverter::HOME_OUTPUT);
   if (this->HomeRelativeOutputPath == ".") {
     this->HomeRelativeOutputPath = "";
   }
@@ -556,8 +556,8 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
   }
 
   // Construct the left hand side of the rule.
-  std::string tgt = cmSystemTools::ConvertToOutputPath(
-    this->ConvertToRelativePath(this->GetBinaryDirectory(), target).c_str());
+  std::string tgt = this->Convert(target, cmOutputConverter::HOME_OUTPUT,
+                                  cmOutputConverter::MAKERULE);
 
   const char* space = "";
   if (tgt.size() == 1) {
@@ -581,12 +581,11 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
   } else {
     // Split dependencies into multiple rule lines.  This allows for
     // very long dependency lists even on older make implementations.
-    std::string binDir = this->GetBinaryDirectory();
     for (std::vector<std::string>::const_iterator dep = depends.begin();
          dep != depends.end(); ++dep) {
       replace = *dep;
-      replace = cmSystemTools::ConvertToOutputPath(
-        this->ConvertToRelativePath(binDir, replace).c_str());
+      replace = this->Convert(replace, cmOutputConverter::HOME_OUTPUT,
+                              cmOutputConverter::MAKERULE);
       os << cmMakeSafe(tgt) << space << ": " << cmMakeSafe(replace) << "\n";
     }
   }
@@ -953,7 +952,6 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
 
   // Add each command line to the set of commands.
   std::vector<std::string> commands1;
-  std::string currentBinDir = this->GetCurrentBinaryDirectory();
   for (unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c) {
     // Build the command line in a single string.
     std::string cmd = ccg.GetCommand(c);
@@ -978,7 +976,8 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
       // working directory will be the start-output directory.
       bool had_slash = cmd.find('/') != cmd.npos;
       if (workingDir.empty()) {
-        cmd = this->ConvertToRelativePath(currentBinDir, cmd);
+        cmd =
+          this->ConvertToRelativePath(cmd, cmOutputConverter::START_OUTPUT);
       }
       bool has_slash = cmd.find('/') != cmd.npos;
       if (had_slash && !has_slash) {
@@ -1002,10 +1001,8 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
         const std::vector<std::string>& outputs = ccg.GetOutputs();
         if (!outputs.empty()) {
           if (workingDir.empty()) {
-            output = this->ConvertToOutputFormat(
-              this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(),
-                                          outputs[0]),
-              cmOutputConverter::SHELL);
+            output = this->Convert(outputs[0], cmOutputConverter::START_OUTPUT,
+                                   cmOutputConverter::SHELL);
 
           } else {
             output = this->ConvertToOutputFormat(outputs[0],
@@ -1072,8 +1069,7 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
   std::vector<std::string>& commands, const std::vector<std::string>& files,
   cmGeneratorTarget* target, const char* filename)
 {
-  std::string currentBinDir = this->GetCurrentBinaryDirectory();
-  std::string cleanfile = currentBinDir;
+  std::string cleanfile = this->GetCurrentBinaryDirectory();
   cleanfile += "/";
   cleanfile += this->GetTargetDirectory(target);
   cleanfile += "/cmake_clean";
@@ -1091,15 +1087,15 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
     fout << "file(REMOVE_RECURSE\n";
     for (std::vector<std::string>::const_iterator f = files.begin();
          f != files.end(); ++f) {
-      std::string fc = this->ConvertToRelativePath(currentBinDir, *f);
+      std::string fc =
+        this->ConvertToRelativePath(*f, cmOutputConverter::START_OUTPUT);
       fout << "  " << cmOutputConverter::EscapeForCMake(fc) << "\n";
     }
     fout << ")\n";
   }
   std::string remove = "$(CMAKE_COMMAND) -P ";
-  remove += this->ConvertToOutputFormat(
-    this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), cleanfile),
-    cmOutputConverter::SHELL);
+  remove += this->Convert(cleanfile, cmOutputConverter::START_OUTPUT,
+                          cmOutputConverter::SHELL);
   commands.push_back(remove);
 
   // For the main clean rule add per-language cleaning.
@@ -1857,9 +1853,9 @@ void 
cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
     const std::string& config =
       this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
     this->GetIncludeDirectories(includes, target, l->first, config);
-    std::string binaryDir = this->GetState()->GetBinaryDirectory();
     if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) {
       const char* sourceDir = this->GetState()->GetSourceDirectory();
+      const char* binaryDir = this->GetState()->GetBinaryDirectory();
       std::vector<std::string>::iterator itr =
         std::remove_if(includes.begin(), includes.end(),
                        ::NotInProjectDir(sourceDir, binaryDir));
@@ -1867,7 +1863,9 @@ void 
cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
     }
     for (std::vector<std::string>::iterator i = includes.begin();
          i != includes.end(); ++i) {
-      cmakefileStream << "  \"" << this->ConvertToRelativePath(binaryDir, *i)
+      cmakefileStream << "  \""
+                      << this->ConvertToRelativePath(
+                           *i, cmOutputConverter::HOME_OUTPUT)
                       << "\"\n";
     }
     cmakefileStream << "  )\n";
@@ -1932,7 +1930,7 @@ std::string 
cmLocalUnixMakefileGenerator3::GetRecursiveMakeCall(
   if (!tgt.empty()) {
     // The make target is always relative to the top of the build tree.
     std::string tgt2 =
-      this->ConvertToRelativePath(this->GetBinaryDirectory(), tgt);
+      this->ConvertToRelativePath(tgt, cmOutputConverter::HOME_OUTPUT);
 
     // The target may have been written with windows paths.
     cmSystemTools::ConvertToOutputSlashes(tgt2);
diff --git a/Source/cmLocalVisualStudio7Generator.cxx 
b/Source/cmLocalVisualStudio7Generator.cxx
index f477a0e..70fe819 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -788,8 +788,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
       target->GetProperty("Fortran_MODULE_DIRECTORY");
     std::string modDir;
     if (target_mod_dir) {
-      modDir = this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(),
-                                           target_mod_dir);
+      modDir = this->ConvertToRelativePath(target_mod_dir,
+                                           cmOutputConverter::START_OUTPUT);
     } else {
       modDir = ".";
     }
@@ -1298,11 +1298,10 @@ void 
cmLocalVisualStudio7GeneratorInternals::OutputLibraries(
   std::ostream& fout, ItemVector const& libs)
 {
   cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
-  std::string currentBinDir = lg->GetCurrentBinaryDirectory();
   for (ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l) {
     if (l->IsPath) {
-      std::string rel =
-        lg->ConvertToRelativePath(currentBinDir, l->Value.c_str());
+      std::string rel = lg->ConvertToRelativePath(
+        l->Value.c_str(), cmOutputConverter::START_OUTPUT);
       fout << lg->ConvertToXMLOutputPath(rel.c_str()) << " ";
     } else if (!l->Target ||
                l->Target->GetType() != cmState::INTERFACE_LIBRARY) {
@@ -1317,13 +1316,13 @@ void 
cmLocalVisualStudio7GeneratorInternals::OutputObjects(
   // VS < 8 does not support per-config source locations so we
   // list object library content on the link line instead.
   cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
-  std::string currentBinDir = lg->GetCurrentBinaryDirectory();
   std::vector<std::string> objs;
   gt->UseObjectLibraries(objs, "");
   const char* sep = isep ? isep : "";
   for (std::vector<std::string>::const_iterator oi = objs.begin();
        oi != objs.end(); ++oi) {
-    std::string rel = lg->ConvertToRelativePath(currentBinDir, oi->c_str());
+    std::string rel =
+      lg->ConvertToRelativePath(oi->c_str(), cmOutputConverter::START_OUTPUT);
     fout << sep << lg->ConvertToXMLOutputPath(rel.c_str());
     sep = " ";
   }
@@ -1333,7 +1332,6 @@ void 
cmLocalVisualStudio7Generator::OutputLibraryDirectories(
   std::ostream& fout, std::vector<std::string> const& dirs)
 {
   const char* comma = "";
-  std::string currentBinDir = this->GetCurrentBinaryDirectory();
   for (std::vector<std::string>::const_iterator d = dirs.begin();
        d != dirs.end(); ++d) {
     // Remove any trailing slash and skip empty paths.
@@ -1347,8 +1345,8 @@ void 
cmLocalVisualStudio7Generator::OutputLibraryDirectories(
 
     // Switch to a relative path specification if it is shorter.
     if (cmSystemTools::FileIsFullPath(dir.c_str())) {
-      std::string rel =
-        this->ConvertToRelativePath(currentBinDir, dir.c_str());
+      std::string rel = this->ConvertToRelativePath(
+        dir.c_str(), cmOutputConverter::START_OUTPUT);
       if (rel.size() < dir.size()) {
         dir = rel;
       }
diff --git a/Source/cmLocalVisualStudioGenerator.cxx 
b/Source/cmLocalVisualStudioGenerator.cxx
index 77ec6f7..d344dc5 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -205,9 +205,7 @@ std::string cmLocalVisualStudioGenerator::ConstructScript(
     }
 
     if (workingDirectory.empty()) {
-      script += this->ConvertToOutputFormat(
-        this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), cmd),
-        cmOutputConverter::SHELL);
+      script += this->Convert(cmd.c_str(), START_OUTPUT, SHELL);
     } else {
       script += this->ConvertToOutputFormat(cmd.c_str(), SHELL);
     }
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx 
b/Source/cmMakefileExecutableTargetGenerator.cxx
index 82bd1a3..66e1ca2 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -138,20 +138,14 @@ void 
cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
   std::string targetOutPathPDB = this->LocalGenerator->ConvertToOutputFormat(
     targetFullPathPDB, cmOutputConverter::SHELL);
   // Convert to the output path to use in constructing commands.
-  std::string targetOutPath = this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->ConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath),
-    cmOutputConverter::SHELL);
-  std::string targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->ConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
-    cmOutputConverter::SHELL);
+  std::string targetOutPath = this->Convert(
+    targetFullPath, cmOutputConverter::START_OUTPUT, cmOutputConverter::SHELL);
+  std::string targetOutPathReal =
+    this->Convert(targetFullPathReal, cmOutputConverter::START_OUTPUT,
+                  cmOutputConverter::SHELL);
   std::string targetOutPathImport =
-    this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(),
-        targetFullPathImport),
-      cmOutputConverter::SHELL);
+    this->Convert(targetFullPathImport, cmOutputConverter::START_OUTPUT,
+                  cmOutputConverter::SHELL);
 
   // Get the language to use for linking this executable.
   std::string linkLanguage =
@@ -225,27 +219,25 @@ void 
cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
   // may need to be cleaned.
   std::vector<std::string> exeCleanFiles;
   exeCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath(
-    this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath));
+    targetFullPath, cmOutputConverter::START_OUTPUT));
 #ifdef _WIN32
   // There may be a manifest file for this target.  Add it to the
   // clean set just in case.
   exeCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath(
-    this->LocalGenerator->GetCurrentBinaryDirectory(),
-    (targetFullPath + ".manifest").c_str()));
+    (targetFullPath + ".manifest").c_str(), cmOutputConverter::START_OUTPUT));
 #endif
   if (targetNameReal != targetName) {
     exeCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal));
+      targetFullPathReal, cmOutputConverter::START_OUTPUT));
   }
   if (!targetNameImport.empty()) {
     exeCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(),
-      targetFullPathImport));
+      targetFullPathImport, cmOutputConverter::START_OUTPUT));
     std::string implib;
     if (this->GeneratorTarget->GetImplibGNUtoMS(targetFullPathImport,
                                                 implib)) {
       exeCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), implib));
+        implib, cmOutputConverter::START_OUTPUT));
     }
   }
 
@@ -253,7 +245,7 @@ void 
cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
   // cleaned.  We do not want to delete the .pdb file just before
   // linking the target.
   this->CleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath(
-    this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathPDB));
+    targetFullPathPDB, cmOutputConverter::START_OUTPUT));
 
   // Add the pre-build and pre-link rules building but not when relinking.
   if (!relink) {
@@ -325,19 +317,14 @@ void 
cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     vars.Language = linkLanguage.c_str();
     vars.Objects = buildObjs.c_str();
     std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
-
-    objectDir = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
-      cmOutputConverter::SHELL);
+    objectDir = this->Convert(objectDir, cmOutputConverter::START_OUTPUT,
+                              cmOutputConverter::SHELL);
     vars.ObjectDir = objectDir.c_str();
     cmOutputConverter::OutputFormat output = (useWatcomQuote)
       ? cmOutputConverter::WATCOMQUOTE
       : cmOutputConverter::SHELL;
-    std::string target = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
-      output);
+    std::string target = this->Convert(
+      targetFullPathReal, cmOutputConverter::START_OUTPUT, output);
     vars.Target = target.c_str();
     vars.TargetPDB = targetOutPathPDB.c_str();
 
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx 
b/Source/cmMakefileLibraryTargetGenerator.cxx
index 1d66d52..c31c469 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -312,25 +312,17 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
   // arguments.
   std::string targetOutPathPDB = this->LocalGenerator->ConvertToOutputFormat(
     targetFullPathPDB, cmOutputConverter::SHELL);
-
-  std::string targetOutPath = this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->ConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath),
-    cmOutputConverter::SHELL);
-  std::string targetOutPathSO = this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->ConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathSO),
-    cmOutputConverter::SHELL);
-  std::string targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->ConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
-    cmOutputConverter::SHELL);
+  std::string targetOutPath = this->Convert(
+    targetFullPath, cmOutputConverter::START_OUTPUT, cmOutputConverter::SHELL);
+  std::string targetOutPathSO =
+    this->Convert(targetFullPathSO, cmOutputConverter::START_OUTPUT,
+                  cmOutputConverter::SHELL);
+  std::string targetOutPathReal =
+    this->Convert(targetFullPathReal, cmOutputConverter::START_OUTPUT,
+                  cmOutputConverter::SHELL);
   std::string targetOutPathImport =
-    this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(),
-        targetFullPathImport),
-      cmOutputConverter::SHELL);
+    this->Convert(targetFullPathImport, cmOutputConverter::START_OUTPUT,
+                  cmOutputConverter::SHELL);
 
   this->NumberOfProgressActions++;
   if (!this->NoRuleMessages) {
@@ -376,24 +368,23 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
   // Clean files associated with this library.
   std::vector<std::string> libCleanFiles;
   libCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath(
-    this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath));
+    targetFullPath, cmOutputConverter::START_OUTPUT));
   if (targetNameReal != targetName) {
     libCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal));
+      targetFullPathReal, cmOutputConverter::START_OUTPUT));
   }
   if (targetNameSO != targetName && targetNameSO != targetNameReal) {
     libCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathSO));
+      targetFullPathSO, cmOutputConverter::START_OUTPUT));
   }
   if (!targetNameImport.empty()) {
     libCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(),
-      targetFullPathImport));
+      targetFullPathImport, cmOutputConverter::START_OUTPUT));
     std::string implib;
     if (this->GeneratorTarget->GetImplibGNUtoMS(targetFullPathImport,
                                                 implib)) {
       libCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), implib));
+        implib, cmOutputConverter::START_OUTPUT));
     }
   }
 
@@ -401,15 +392,15 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
   // cleaned.  We do not want to delete the .pdb file just before
   // linking the target.
   this->CleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath(
-    this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathPDB));
+    targetFullPathPDB, cmOutputConverter::START_OUTPUT));
 
 #ifdef _WIN32
   // There may be a manifest file for this target.  Add it to the
   // clean set just in case.
   if (this->GeneratorTarget->GetType() != cmState::STATIC_LIBRARY) {
     libCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(),
-      (targetFullPath + ".manifest").c_str()));
+      (targetFullPath + ".manifest").c_str(),
+      cmOutputConverter::START_OUTPUT));
   }
 #endif
 
@@ -544,20 +535,14 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     vars.Language = linkLanguage.c_str();
     vars.Objects = buildObjs.c_str();
     std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
-
-    objectDir = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
-      cmOutputConverter::SHELL);
-
+    objectDir = this->Convert(objectDir, cmOutputConverter::START_OUTPUT,
+                              cmOutputConverter::SHELL);
     vars.ObjectDir = objectDir.c_str();
     cmOutputConverter::OutputFormat output = (useWatcomQuote)
       ? cmOutputConverter::WATCOMQUOTE
       : cmOutputConverter::SHELL;
-    std::string target = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
-      output);
+    std::string target = this->Convert(
+      targetFullPathReal, cmOutputConverter::START_OUTPUT, output);
     vars.Target = target.c_str();
     vars.LinkLibraries = linkLibs.c_str();
     vars.ObjectsQuoted = buildObjs.c_str();
diff --git a/Source/cmMakefileTargetGenerator.cxx 
b/Source/cmMakefileTargetGenerator.cxx
index 014feb9..165f96c 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -162,8 +162,6 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
   // files for this target.
   std::vector<cmSourceFile const*> customCommands;
   this->GeneratorTarget->GetCustomCommands(customCommands, config);
-  std::string currentBinDir =
-    this->LocalGenerator->GetCurrentBinaryDirectory();
   for (std::vector<cmSourceFile const*>::const_iterator si =
          customCommands.begin();
        si != customCommands.end(); ++si) {
@@ -174,8 +172,8 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
       const std::vector<std::string>& outputs = ccg.GetOutputs();
       for (std::vector<std::string>::const_iterator o = outputs.begin();
            o != outputs.end(); ++o) {
-        this->CleanFiles.push_back(
-          this->LocalGenerator->ConvertToRelativePath(currentBinDir, *o));
+        this->CleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath(
+          *o, cmOutputConverter::START_OUTPUT));
       }
     }
   }
@@ -216,11 +214,8 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
   *this->BuildFileStream
     << "# Include any dependencies generated for this target.\n"
     << this->GlobalGenerator->IncludeDirective << " " << root
-    << cmSystemTools::ConvertToOutputPath(
-         this->LocalGenerator
-           ->ConvertToRelativePath(this->LocalGenerator->GetBinaryDirectory(),
-                                   dependFileNameFull)
-           .c_str())
+    << this->Convert(dependFileNameFull, cmOutputConverter::HOME_OUTPUT,
+                     cmOutputConverter::MAKERULE)
     << "\n\n";
 
   if (!this->NoRuleMessages) {
@@ -228,12 +223,9 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
     *this->BuildFileStream
       << "# Include the progress variables for this target.\n"
       << this->GlobalGenerator->IncludeDirective << " " << root
-      << cmSystemTools::ConvertToOutputPath(
-           this->LocalGenerator
-             ->ConvertToRelativePath(
-               this->LocalGenerator->GetBinaryDirectory(),
-               this->ProgressFileNameFull)
-             .c_str())
+      << this->Convert(this->ProgressFileNameFull,
+                       cmOutputConverter::HOME_OUTPUT,
+                       cmOutputConverter::MAKERULE)
       << "\n\n";
   }
 
@@ -263,11 +255,8 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
   *this->BuildFileStream
     << "# Include the compile flags for this target's objects.\n"
     << this->GlobalGenerator->IncludeDirective << " " << root
-    << cmSystemTools::ConvertToOutputPath(
-         this->LocalGenerator
-           ->ConvertToRelativePath(this->LocalGenerator->GetBinaryDirectory(),
-                                   this->FlagFileNameFull)
-           .c_str())
+    << this->Convert(this->FlagFileNameFull, cmOutputConverter::HOME_OUTPUT,
+                     cmOutputConverter::MAKERULE)
     << "\n\n";
 }
 
@@ -324,9 +313,9 @@ void 
cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()(
   output += cmSystemTools::GetFilenameName(input);
   this->Generator->CleanFiles.push_back(
     this->Generator->LocalGenerator->ConvertToRelativePath(
-      this->Generator->LocalGenerator->GetCurrentBinaryDirectory(), output));
+      output, cmOutputConverter::START_OUTPUT));
   output = this->Generator->LocalGenerator->ConvertToRelativePath(
-    this->Generator->LocalGenerator->GetBinaryDirectory(), output);
+    output, cmOutputConverter::HOME_OUTPUT);
 
   // Create a rule to copy the content into the bundle.
   std::vector<std::string> depends;
@@ -526,17 +515,14 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
       }
     }
 
-    targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
-      cmOutputConverter::SHELL);
+    targetOutPathReal =
+      this->Convert(targetFullPathReal, cmOutputConverter::START_OUTPUT,
+                    cmOutputConverter::SHELL);
     targetOutPathPDB = this->LocalGenerator->ConvertToOutputFormat(
       targetFullPathPDB, cmOutputConverter::SHELL);
-    targetOutPathCompilePDB = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(),
-        targetFullPathCompilePDB),
-      cmOutputConverter::SHELL);
+    targetOutPathCompilePDB =
+      this->Convert(targetFullPathCompilePDB, cmOutputConverter::START_OUTPUT,
+                    cmOutputConverter::SHELL);
 
     if (this->LocalGenerator->IsMinGWMake() &&
         cmHasLiteralSuffix(targetOutPathCompilePDB, "\\")) {
@@ -558,16 +544,12 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
     this->LocalGenerator->ConvertToOutputFormat(obj, cmOutputConverter::SHELL);
   vars.Object = shellObj.c_str();
   std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
-  objectDir = this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->ConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
-    cmOutputConverter::SHELL);
+  objectDir = this->Convert(objectDir, cmOutputConverter::START_OUTPUT,
+                            cmOutputConverter::SHELL);
   vars.ObjectDir = objectDir.c_str();
   std::string objectFileDir = cmSystemTools::GetFilenamePath(obj);
-  objectFileDir = this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->ConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), objectFileDir),
-    cmOutputConverter::SHELL);
+  objectFileDir = this->Convert(objectFileDir, cmOutputConverter::START_OUTPUT,
+                                cmOutputConverter::SHELL);
   vars.ObjectFileDir = objectFileDir.c_str();
   vars.Flags = flags.c_str();
 
@@ -907,14 +889,12 @@ bool cmMakefileTargetGenerator::WriteMakeRule(
 
   // For multiple outputs, make the extra ones depend on the first one.
   std::vector<std::string> const output_depends(1, outputs[0]);
-  std::string binDir = this->LocalGenerator->GetBinaryDirectory();
   for (std::vector<std::string>::const_iterator o = outputs.begin() + 1;
        o != outputs.end(); ++o) {
     // Touch the extra output so "make" knows that it was updated,
     // but only if the output was acually created.
-    std::string const out = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->ConvertToRelativePath(binDir, *o),
-      cmOutputConverter::SHELL);
+    std::string const out = this->Convert(*o, cmOutputConverter::HOME_OUTPUT,
+                                          cmOutputConverter::SHELL);
     std::vector<std::string> output_commands;
 
     bool o_symbolic = false;
@@ -1200,12 +1180,11 @@ void cmMakefileTargetGenerator::WriteObjectsVariable(
     << this->GeneratorTarget->GetName() << "\n"
     << variableNameExternal << " =";
   /* clang-format on */
-  std::string currentBinDir =
-    this->LocalGenerator->GetCurrentBinaryDirectory();
   for (std::vector<std::string>::const_iterator i =
          this->ExternalObjects.begin();
        i != this->ExternalObjects.end(); ++i) {
-    object = this->LocalGenerator->ConvertToRelativePath(currentBinDir, *i);
+    object = this->LocalGenerator->ConvertToRelativePath(
+      *i, cmOutputConverter::START_OUTPUT);
     *this->BuildFileStream << " " << lineContinue << "\n"
                            << this->Makefile->GetSafeDefinition(
                                 "CMAKE_OBJECT_NAME");
@@ -1238,10 +1217,8 @@ public:
   void Feed(std::string const& obj)
   {
     // Construct the name of the next object.
-    this->NextObject = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), obj),
-      cmOutputConverter::RESPONSE);
+    this->NextObject = this->LocalGenerator->Convert(
+      obj, cmOutputConverter::START_OUTPUT, cmOutputConverter::RESPONSE);
 
     // Roll over to next string if the limit will be exceeded.
     if (this->LengthLimit != std::string::npos &&
@@ -1295,7 +1272,7 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule(
   std::string buildTargetRuleName = dir;
   buildTargetRuleName += relink ? "/preinstall" : "/build";
   buildTargetRuleName = this->LocalGenerator->ConvertToRelativePath(
-    this->LocalGenerator->GetBinaryDirectory(), buildTargetRuleName);
+    buildTargetRuleName, cmOutputConverter::HOME_OUTPUT);
 
   // Build the list of target outputs to drive.
   std::vector<std::string> depends;
@@ -1483,10 +1460,8 @@ void cmMakefileTargetGenerator::CreateLinkScript(
 
   // Create the makefile command to invoke the link script.
   std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script ";
-  link_command += this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->ConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), linkScriptName),
-    cmOutputConverter::SHELL);
+  link_command += this->Convert(
+    linkScriptName, cmOutputConverter::START_OUTPUT, cmOutputConverter::SHELL);
   link_command += " --verbose=$(VERBOSE)";
   makefile_commands.push_back(link_command);
   makefile_depends.push_back(linkScriptName);
@@ -1517,9 +1492,9 @@ bool 
cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
   if (size_t const limit = calculateCommandLineLengthLimit()) {
     // Compute the total length of our list of object files with room
     // for argument separation and quoting.  This does not convert paths
-    // relative to CMAKE_CURRENT_BINARY_DIR like the final list will be, so the
-    // actual list will likely be much shorter than this.  However, in the
-    // worst case all objects will remain as absolute paths.
+    // relative to START_OUTPUT like the final list will be, so the actual
+    // list will likely be much shorter than this.  However, in the worst
+    // case all objects will remain as absolute paths.
     size_t length = 0;
     for (std::vector<std::string>::const_iterator i = this->Objects.begin();
          i != this->Objects.end(); ++i) {
@@ -1720,17 +1695,13 @@ void cmMakefileTargetGenerator::GenDefFile(
     cmd = this->LocalGenerator->ConvertToOutputFormat(
       cmd, cmOutputConverter::SHELL);
     cmd += " -E __create_def ";
-    cmd += this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), name_of_def_file),
-      cmOutputConverter::SHELL);
+    cmd += this->Convert(name_of_def_file, cmOutputConverter::START_OUTPUT,
+                         cmOutputConverter::SHELL);
     cmd += " ";
     std::string objlist_file = name_of_def_file;
     objlist_file += ".objs";
-    cmd += this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file),
-      cmOutputConverter::SHELL);
+    cmd += this->Convert(objlist_file, cmOutputConverter::START_OUTPUT,
+                         cmOutputConverter::SHELL);
     real_link_commands.insert(real_link_commands.begin(), cmd);
     // create a list of obj files for the -E __create_def to read
     cmGeneratedFileStream fout(objlist_file.c_str());
@@ -1748,10 +1719,9 @@ void cmMakefileTargetGenerator::GenDefFile(
     // now add the def file link flag
     linkFlags += " ";
     linkFlags += this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
-    linkFlags += this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->ConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), name_of_def_file),
-      cmOutputConverter::SHELL);
+    linkFlags +=
+      this->Convert(name_of_def_file, cmOutputConverter::START_OUTPUT,
+                    cmOutputConverter::SHELL);
     linkFlags += " ";
   }
 }
diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx 
b/Source/cmMakefileUtilityTargetGenerator.cxx
index 8bf0a23..b709545 100644
--- a/Source/cmMakefileUtilityTargetGenerator.cxx
+++ b/Source/cmMakefileUtilityTargetGenerator.cxx
@@ -53,12 +53,9 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
     *this->BuildFileStream
       << "# Include the progress variables for this target.\n"
       << this->GlobalGenerator->IncludeDirective << " " << root
-      << cmSystemTools::ConvertToOutputPath(
-           this->LocalGenerator
-             ->ConvertToRelativePath(
-               this->LocalGenerator->GetBinaryDirectory(),
-               this->ProgressFileNameFull)
-             .c_str())
+      << this->Convert(this->ProgressFileNameFull,
+                       cmOutputConverter::HOME_OUTPUT,
+                       cmOutputConverter::MAKERULE)
       << "\n\n";
   }
 
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx 
b/Source/cmNinjaNormalTargetGenerator.cxx
index 5c32e00..335b552 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -642,8 +642,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
       }
     }
   }
-  // If we have any PRE_LINK commands, we need to go back to CMAKE_BINARY_DIR
-  // for
+  // If we have any PRE_LINK commands, we need to go back to HOME_OUTPUT for
   // the link commands.
   if (!preLinkCmdLines.empty()) {
     const std::string homeOutDir = localGen.ConvertToOutputFormat(
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index d952007..ae7c583 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -46,12 +46,49 @@ std::string cmOutputConverter::ConvertToOutputForExisting(
   return this->ConvertToOutputFormat(remote, format);
 }
 
+std::string cmOutputConverter::ConvertToRelativePath(
+  const std::string& source, RelativeRoot relative) const
+{
+  std::string result;
+
+  switch (relative) {
+    case HOME:
+      result = this->ConvertToRelativePath(
+        this->GetState()->GetSourceDirectory(), source);
+      break;
+    case START:
+      result = this->ConvertToRelativePath(
+        this->StateSnapshot.GetDirectory().GetCurrentSource(), source);
+      break;
+    case HOME_OUTPUT:
+      result = this->ConvertToRelativePath(
+        this->GetState()->GetBinaryDirectory(), source);
+      break;
+    case START_OUTPUT:
+      result = this->ConvertToRelativePath(
+        this->StateSnapshot.GetDirectory().GetCurrentBinary(), source);
+      break;
+  }
+  return result;
+}
+
+std::string cmOutputConverter::Convert(const std::string& source,
+                                       RelativeRoot relative,
+                                       OutputFormat output) const
+{
+  // Convert the path to a relative path.
+  std::string result = this->ConvertToRelativePath(source, relative);
+  return this->ConvertToOutputFormat(result, output);
+}
+
 std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source,
                                                      OutputFormat output) const
 {
   std::string result = source;
   // Convert it to an output path.
-  if (output == SHELL || output == WATCOMQUOTE) {
+  if (output == MAKERULE) {
+    result = cmSystemTools::ConvertToOutputPath(result.c_str());
+  } else if (output == SHELL || output == WATCOMQUOTE) {
     result = this->ConvertDirectorySeparatorsForShell(source);
     result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE);
   } else if (output == RESPONSE) {
@@ -86,6 +123,15 @@ static bool cmOutputConverterNotAbove(const char* a, const 
char* b)
 }
 
 std::string cmOutputConverter::ConvertToRelativePath(
+  const std::vector<std::string>& local, const std::string& in_remote,
+  bool force) const
+{
+  std::string local_path = cmSystemTools::JoinPath(local);
+  return force ? this->ForceToRelativePath(local_path, in_remote)
+               : this->ConvertToRelativePath(local_path, in_remote);
+}
+
+std::string cmOutputConverter::ConvertToRelativePath(
   std::string const& local_path, std::string const& remote_path) const
 {
   // The paths should never be quoted.
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
index 078b451..1efe109 100644
--- a/Source/cmOutputConverter.h
+++ b/Source/cmOutputConverter.h
@@ -24,14 +24,40 @@ class cmOutputConverter
 public:
   cmOutputConverter(cmState::Snapshot snapshot);
 
+  /**
+   * Convert something to something else. This is a centralized conversion
+   * routine used by the generators to handle relative paths and the like.
+   * The flags determine what is actually done.
+   *
+   * relative: treat the argument as a directory and convert it to make it
+   * relative or full or unchanged. If relative (HOME, START etc) then that
+   * specifies what it should be relative to.
+   *
+   * output: make the result suitable for output to a...
+   *
+   * optional: should any relative path operation be controlled by the rel
+   * path setting
+   */
+  enum RelativeRoot
+  {
+    HOME,
+    START,
+    HOME_OUTPUT,
+    START_OUTPUT
+  };
   enum OutputFormat
   {
+    MAKERULE,
     SHELL,
     WATCOMQUOTE,
     RESPONSE
   };
   std::string ConvertToOutputFormat(const std::string& source,
                                     OutputFormat output) const;
+  std::string Convert(const std::string& remote, RelativeRoot local,
+                      OutputFormat output) const;
+  std::string ConvertToRelativePath(const std::string& remote,
+                                    RelativeRoot local) const;
   std::string ConvertDirectorySeparatorsForShell(
     const std::string& source) const;
 
@@ -110,6 +136,17 @@ public:
 
   /**
    * Convert the given remote path to a relative path with respect to
+   * the given local path.  The local path must be given in component
+   * form (see SystemTools::SplitPath) without a trailing slash.  The
+   * remote path must use forward slashes and not already be escaped
+   * or quoted.
+   */
+  std::string ConvertToRelativePath(const std::vector<std::string>& local,
+                                    const std::string& in_remote,
+                                    bool force = false) const;
+
+  /**
+   * Convert the given remote path to a relative path with respect to
    * the given local path.  Both paths must use forward slashes and not
    * already be escaped or quoted.
    * The conversion is skipped if the paths are not both in the source
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 1dad742..1b6c93e 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -596,8 +596,8 @@ void cmTarget::GetTllSignatureTraces(std::ostream& s, 
TLLSignature sig) const
        it != this->TLLCommands.end(); ++it) {
     if (it->first == sig) {
       cmListFileContext lfc = it->second;
-      lfc.FilePath = converter.ConvertToRelativePath(
-        this->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath);
+      lfc.FilePath =
+        converter.ConvertToRelativePath(lfc.FilePath, cmOutputConverter::HOME);
       s << " * " << lfc << std::endl;
     }
   }
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx 
b/Source/cmVisualStudio10TargetGenerator.cxx
index 85084eb..8ff7366 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2415,12 +2415,10 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
 {
   typedef cmComputeLinkInformation::ItemVector ItemVector;
   ItemVector libs = cli.GetItems();
-  std::string currentBinDir =
-    this->LocalGenerator->GetCurrentBinaryDirectory();
   for (ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l) {
     if (l->IsPath) {
       std::string path = this->LocalGenerator->ConvertToRelativePath(
-        currentBinDir, l->Value.c_str());
+        l->Value.c_str(), cmOutputConverter::START_OUTPUT);
       this->ConvertToWindowsSlash(path);
       libVec.push_back(path);
     } else if (!l->Target ||

-----------------------------------------------------------------------

Summary of changes:
 Source/cmCommonTargetGenerator.cxx             |   12 ++-
 Source/cmCommonTargetGenerator.h               |    4 +
 Source/cmDependsC.cxx                          |   17 ++--
 Source/cmDependsFortran.cxx                    |   63 +++++++-------
 Source/cmExportBuildAndroidMKGenerator.cxx     |    3 +-
 Source/cmExtraEclipseCDT4Generator.cxx         |    2 +-
 Source/cmGlobalGenerator.cxx                   |    2 +-
 Source/cmGlobalNinjaGenerator.cxx              |    8 +-
 Source/cmGlobalUnixMakefileGenerator3.cxx      |   36 ++++----
 Source/cmGlobalVisualStudio7Generator.cxx      |    4 +-
 Source/cmGlobalXCodeGenerator.cxx              |   17 +++-
 Source/cmGlobalXCodeGenerator.h                |    3 +
 Source/cmListFileCache.cxx                     |    8 +-
 Source/cmLocalCommonGenerator.cxx              |   10 +--
 Source/cmLocalCommonGenerator.h                |    9 +-
 Source/cmLocalGenerator.cxx                    |   17 ++--
 Source/cmLocalNinjaGenerator.cxx               |   13 ++-
 Source/cmLocalUnixMakefileGenerator3.cxx       |   42 +++++----
 Source/cmLocalVisualStudio7Generator.cxx       |   18 ++--
 Source/cmLocalVisualStudioGenerator.cxx        |    4 +-
 Source/cmMakefileExecutableTargetGenerator.cxx |   47 ++++------
 Source/cmMakefileLibraryTargetGenerator.cxx    |   59 +++++--------
 Source/cmMakefileTargetGenerator.cxx           |  110 +++++++++---------------
 Source/cmMakefileUtilityTargetGenerator.cxx    |    9 +-
 Source/cmNinjaNormalTargetGenerator.cxx        |    3 +-
 Source/cmOutputConverter.cxx                   |   48 ++++++++++-
 Source/cmOutputConverter.h                     |   37 ++++++++
 Source/cmTarget.cxx                            |    4 +-
 Source/cmVisualStudio10TargetGenerator.cxx     |    4 +-
 29 files changed, 324 insertions(+), 289 deletions(-)


hooks/post-receive
-- 
CMake
_______________________________________________
Cmake-commits mailing list
Cmake-commits@cmake.org
http://public.kitware.com/mailman/listinfo/cmake-commits

Reply via email to