1
0
Эх сурвалжийг харах

Merge topic 'relative-paths'

f6d4fa63f8 cmStateDirectory: Comment relative path top directory selection approach
f0ffb1e2d4 cmGlobalGenerator: Simplify relative path conversion in AddRuleHash
d346805e41 cmLocalCommonGenerator: Select work directory semantically
15fa320071 cmLocalGenerator: Factor out relative path conversion helpers
1879f1bcbc cmLocalCommonGenerator: Factor out relative path conversion helper
1d1d88d3c8 cmMakefileTargetGenerator: Clarify name of relative path conversion helper
ec1ea13066 cmDependsFortran: Simplify relative path conversion helper
ba7b939831 cmStateDirectory: Rename ConvertToRelPathIf{Not => }Contained
...

Acked-by: Kitware Robot <[email protected]>
Merge-request: !6122
Brad King 4 жил өмнө
parent
commit
21da0f83a2
33 өөрчлөгдсөн 277 нэмэгдсэн , 376 устгасан
  1. 1 2
      Source/cmCommonTargetGenerator.cxx
  2. 2 5
      Source/cmDependsC.cxx
  3. 6 8
      Source/cmDependsCompiler.cxx
  4. 10 25
      Source/cmDependsFortran.cxx
  5. 0 4
      Source/cmDependsFortran.h
  6. 2 2
      Source/cmExtraEclipseCDT4Generator.cxx
  7. 2 6
      Source/cmGhsMultiTargetGenerator.cxx
  8. 2 4
      Source/cmGlobalGenerator.cxx
  9. 4 4
      Source/cmGlobalGhsMultiGenerator.cxx
  10. 1 1
      Source/cmGlobalGhsMultiGenerator.h
  11. 2 4
      Source/cmGlobalNinjaGenerator.cxx
  12. 8 20
      Source/cmGlobalUnixMakefileGenerator3.cxx
  13. 1 2
      Source/cmGlobalVisualStudio7Generator.cxx
  14. 3 10
      Source/cmGlobalXCodeGenerator.cxx
  15. 1 2
      Source/cmGlobalXCodeGenerator.h
  16. 2 2
      Source/cmListFileCache.cxx
  17. 24 5
      Source/cmLocalCommonGenerator.cxx
  18. 12 4
      Source/cmLocalCommonGenerator.h
  19. 24 10
      Source/cmLocalGenerator.cxx
  20. 8 4
      Source/cmLocalGenerator.h
  21. 6 8
      Source/cmLocalNinjaGenerator.cxx
  22. 25 40
      Source/cmLocalUnixMakefileGenerator3.cxx
  23. 4 9
      Source/cmLocalVisualStudio7Generator.cxx
  24. 2 4
      Source/cmLocalVisualStudioGenerator.cxx
  25. 26 40
      Source/cmMakefileExecutableTargetGenerator.cxx
  26. 30 46
      Source/cmMakefileLibraryTargetGenerator.cxx
  27. 48 77
      Source/cmMakefileTargetGenerator.cxx
  28. 2 4
      Source/cmMakefileUtilityTargetGenerator.cxx
  29. 7 1
      Source/cmStateDirectory.cxx
  30. 1 1
      Source/cmStateDirectory.h
  31. 1 1
      Source/cmTarget.cxx
  32. 4 9
      Source/cmTransformDepfile.cxx
  33. 6 12
      Source/cmVisualStudio10TargetGenerator.cxx

+ 1 - 2
Source/cmCommonTargetGenerator.cxx

@@ -241,8 +241,7 @@ std::string cmCommonTargetGenerator::GetManifests(const std::string& config)
   manifests.reserve(manifest_srcs.size());
   for (cmSourceFile const* manifest_src : manifest_srcs) {
     manifests.push_back(this->LocalCommonGenerator->ConvertToOutputFormat(
-      this->LocalCommonGenerator->MaybeConvertToRelativePath(
-        this->LocalCommonGenerator->GetWorkingDirectory(),
+      this->LocalCommonGenerator->MaybeRelativeToWorkDir(
         manifest_src->GetFullPath()),
       cmOutputConverter::SHELL));
   }

+ 2 - 5
Source/cmDependsC.cxx

@@ -90,13 +90,10 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
   std::set<std::string> dependencies;
   bool haveDeps = false;
 
-  std::string binDir = this->LocalGenerator->GetBinaryDirectory();
-
   // Compute a path to the object file to write to the internal depend file.
   // Any existing content of the internal depend file has already been
   // loaded in ValidDeps with this path as a key.
-  std::string obj_i =
-    this->LocalGenerator->MaybeConvertToRelativePath(binDir, obj);
+  std::string obj_i = this->LocalGenerator->MaybeRelativeToTopBinDir(obj);
 
   if (this->ValidDeps != nullptr) {
     auto const tmpIt = this->ValidDeps->find(obj_i);
@@ -228,7 +225,7 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
     }
     for (std::string const& dep : dependencies) {
       std::string dependee = this->LocalGenerator->ConvertToMakefilePath(
-        this->LocalGenerator->MaybeConvertToRelativePath(binDir, dep));
+        this->LocalGenerator->MaybeRelativeToTopBinDir(dep));
       if (supportLongLineDepend) {
         makeDepends << ' ' << lineContinue << ' ' << dependee;
       } else {

+ 6 - 8
Source/cmDependsCompiler.cxx

@@ -190,21 +190,19 @@ void cmDependsCompiler::WriteDependencies(
   bool supportLongLineDepend = static_cast<cmGlobalUnixMakefileGenerator3*>(
                                  this->LocalGenerator->GetGlobalGenerator())
                                  ->SupportsLongLineDependencies();
-  const auto& binDir = this->LocalGenerator->GetBinaryDirectory();
   cmDepends::DependencyMap makeDependencies(dependencies);
   std::unordered_set<cm::string_view> phonyTargets;
 
   // external dependencies file
   for (auto& node : makeDependencies) {
     auto target = this->LocalGenerator->ConvertToMakefilePath(
-      this->LocalGenerator->MaybeConvertToRelativePath(binDir, node.first));
+      this->LocalGenerator->MaybeRelativeToTopBinDir(node.first));
     auto& deps = node.second;
-    std::transform(
-      deps.cbegin(), deps.cend(), deps.begin(),
-      [this, &binDir](const std::string& dep) {
-        return this->LocalGenerator->ConvertToMakefilePath(
-          this->LocalGenerator->MaybeConvertToRelativePath(binDir, dep));
-      });
+    std::transform(deps.cbegin(), deps.cend(), deps.begin(),
+                   [this](const std::string& dep) {
+                     return this->LocalGenerator->ConvertToMakefilePath(
+                       this->LocalGenerator->MaybeRelativeToTopBinDir(dep));
+                   });
 
     bool first_dep = true;
     if (supportLongLineDepend) {

+ 10 - 25
Source/cmDependsFortran.cxx

@@ -17,8 +17,6 @@
 #include "cmMakefile.h"
 #include "cmOutputConverter.h"
 #include "cmProperty.h"
-#include "cmStateDirectory.h"
-#include "cmStateSnapshot.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
@@ -192,8 +190,6 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
     cmGeneratedFileStream fcStream(fcName);
     fcStream << "# Remove fortran modules provided by this target.\n";
     fcStream << "FILE(REMOVE";
-    std::string currentBinDir =
-      this->LocalGenerator->GetCurrentBinaryDirectory();
     for (std::string const& i : provides) {
       std::string mod_upper = cmStrCat(mod_dir, '/');
       std::string mod_lower = cmStrCat(mod_dir, '/');
@@ -201,13 +197,13 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
       std::string stamp = cmStrCat(stamp_dir, '/', i, ".stamp");
       fcStream << "\n"
                   "  \""
-               << this->MaybeConvertToRelativePath(currentBinDir, mod_lower)
+               << this->LocalGenerator->MaybeRelativeToCurBinDir(mod_lower)
                << "\"\n"
                   "  \""
-               << this->MaybeConvertToRelativePath(currentBinDir, mod_upper)
+               << this->LocalGenerator->MaybeRelativeToCurBinDir(mod_upper)
                << "\"\n"
                   "  \""
-               << this->MaybeConvertToRelativePath(currentBinDir, stamp)
+               << this->LocalGenerator->MaybeRelativeToCurBinDir(stamp)
                << "\"\n";
     }
     fcStream << "  )\n";
@@ -317,8 +313,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
   std::string const& src = info.Source;
 
   // Write the include dependencies to the output stream.
-  std::string binDir = this->LocalGenerator->GetBinaryDirectory();
-  std::string obj_i = this->MaybeConvertToRelativePath(binDir, obj);
+  std::string obj_i = this->LocalGenerator->MaybeRelativeToTopBinDir(obj);
   std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i);
   internalDepends << obj_i << "\n " << src << '\n';
   if (!info.Includes.empty()) {
@@ -333,7 +328,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
     }
     for (std::string const& i : info.Includes) {
       std::string dependee = cmSystemTools::ConvertToOutputPath(
-        this->MaybeConvertToRelativePath(binDir, i));
+        this->LocalGenerator->MaybeRelativeToTopBinDir(i));
       if (supportLongLineDepend) {
         makeDepends << ' ' << lineContinue << ' ' << dependee;
       } else {
@@ -360,7 +355,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
     if (!required->second.empty()) {
       // This module is known.  Depend on its timestamp file.
       std::string stampFile = cmSystemTools::ConvertToOutputPath(
-        this->MaybeConvertToRelativePath(binDir, required->second));
+        this->LocalGenerator->MaybeRelativeToTopBinDir(required->second));
       makeDepends << obj_m << ": " << stampFile << '\n';
     } else {
       // This module is not known to CMake.  Try to locate it where
@@ -368,7 +363,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
       std::string module;
       if (this->FindModule(i, module)) {
         module = cmSystemTools::ConvertToOutputPath(
-          this->MaybeConvertToRelativePath(binDir, module));
+          this->LocalGenerator->MaybeRelativeToTopBinDir(module));
         makeDepends << obj_m << ": " << module << '\n';
       }
     }
@@ -387,10 +382,10 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
       // try various cases for the real mod file name.
       std::string modFile = cmStrCat(mod_dir, '/', i);
       modFile = this->LocalGenerator->ConvertToOutputFormat(
-        this->MaybeConvertToRelativePath(binDir, modFile),
+        this->LocalGenerator->MaybeRelativeToTopBinDir(modFile),
         cmOutputConverter::SHELL);
       std::string stampFile = cmStrCat(stamp_dir, '/', i, ".stamp");
-      stampFile = this->MaybeConvertToRelativePath(binDir, stampFile);
+      stampFile = this->LocalGenerator->MaybeRelativeToTopBinDir(stampFile);
       std::string const stampFileForShell =
         this->LocalGenerator->ConvertToOutputFormat(stampFile,
                                                     cmOutputConverter::SHELL);
@@ -425,7 +420,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
     // the target finishes building.
     std::string driver = cmStrCat(this->TargetDirectory, "/build");
     driver = cmSystemTools::ConvertToOutputPath(
-      this->MaybeConvertToRelativePath(binDir, driver));
+      this->LocalGenerator->MaybeRelativeToTopBinDir(driver));
     makeDepends << driver << ": " << obj_m << ".provides.build\n";
   }
 
@@ -681,13 +676,3 @@ bool cmDependsFortran::ModulesDiffer(const std::string& modFile,
   // content.
   return cmFortranStreamsDiffer(finModFile, finStampFile);
 }
-
-std::string cmDependsFortran::MaybeConvertToRelativePath(
-  std::string const& base, std::string const& path)
-{
-  if (!this->LocalGenerator->GetStateSnapshot().GetDirectory().ContainsBoth(
-        base, path)) {
-    return path;
-  }
-  return cmSystemTools::ForceToRelativePath(base, path);
-}

+ 0 - 4
Source/cmDependsFortran.h

@@ -85,8 +85,4 @@ protected:
 
   // Internal implementation details.
   std::unique_ptr<cmDependsFortranInternals> Internal;
-
-private:
-  std::string MaybeConvertToRelativePath(std::string const& base,
-                                         std::string const& path);
 };

+ 2 - 2
Source/cmExtraEclipseCDT4Generator.cxx

@@ -916,8 +916,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
   // and UTILITY targets
   for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) {
     const auto& targets = lgen->GetGeneratorTargets();
-    std::string subdir = lgen->MaybeConvertToRelativePath(
-      this->HomeOutputDirectory, lgen->GetCurrentBinaryDirectory());
+    std::string subdir =
+      lgen->MaybeRelativeToTopBinDir(lgen->GetCurrentBinaryDirectory());
     if (subdir == ".") {
       subdir.clear();
     }

+ 2 - 6
Source/cmGhsMultiTargetGenerator.cxx

@@ -159,13 +159,11 @@ void cmGhsMultiTargetGenerator::WriteTargetSpecifics(std::ostream& fout,
                                                      const std::string& config)
 {
   std::string outpath;
-  std::string rootpath = this->LocalGenerator->GetCurrentBinaryDirectory();
 
   if (this->TagType != GhsMultiGpj::SUBPROJECT) {
     // set target binary file destination
     outpath = this->GeneratorTarget->GetDirectory(config);
-    outpath =
-      this->LocalGenerator->MaybeConvertToRelativePath(rootpath, outpath);
+    outpath = this->LocalGenerator->MaybeRelativeToCurBinDir(outpath);
     /* clang-format off */
     fout << "    :binDirRelative=\"" << outpath << "\"\n"
             "    -o \"" << this->TargetNameReal << "\"\n";
@@ -369,7 +367,6 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
 
   // if the command specified a working directory use it.
   std::string dir = this->LocalGenerator->GetCurrentBinaryDirectory();
-  std::string currentBinDir = dir;
   std::string workingDir = ccg.GetWorkingDirectory();
   if (!workingDir.empty()) {
     dir = workingDir;
@@ -427,8 +424,7 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
       // working directory will be the start-output directory.
       bool had_slash = cmd.find('/') != std::string::npos;
       if (workingDir.empty()) {
-        cmd =
-          this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, cmd);
+        cmd = this->LocalGenerator->MaybeRelativeToCurBinDir(cmd);
       }
       bool has_slash = cmd.find('/') != std::string::npos;
       if (had_slash && !has_slash) {

+ 2 - 4
Source/cmGlobalGenerator.cxx

@@ -3027,10 +3027,8 @@ void cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
   }
 
   // Shorten the output name (in expected use case).
-  cmStateDirectory cmDir =
-    this->GetMakefiles()[0]->GetStateSnapshot().GetDirectory();
-  std::string fname = cmDir.ConvertToRelPathIfNotContained(
-    this->GetMakefiles()[0]->GetState()->GetBinaryDirectory(), outputs[0]);
+  std::string fname =
+    this->LocalGenerators[0]->MaybeRelativeToTopBinDir(outputs[0]);
 
   // Associate the hash with this output.
   this->RuleHashes[fname] = hash;

+ 4 - 4
Source/cmGlobalGhsMultiGenerator.cxx

@@ -375,7 +375,7 @@ void cmGlobalGhsMultiGenerator::WriteSubProjects(std::ostream& fout,
 }
 
 void cmGlobalGhsMultiGenerator::WriteProjectLine(
-  std::ostream& fout, cmGeneratorTarget const* target, cmLocalGenerator* root,
+  std::ostream& fout, cmGeneratorTarget const* target,
   std::string& rootBinaryDir)
 {
   cmProp projName = target->GetProperty("GENERATOR_FILE_NAME");
@@ -383,7 +383,7 @@ void cmGlobalGhsMultiGenerator::WriteProjectLine(
   if (projName && projType) {
     cmLocalGenerator* lg = target->GetLocalGenerator();
     std::string dir = lg->GetCurrentBinaryDirectory();
-    dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir);
+    dir = cmSystemTools::ForceToRelativePath(rootBinaryDir, dir);
     if (dir == ".") {
       dir.clear();
     } else {
@@ -433,7 +433,7 @@ void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root)
                  target->GetName(), "] had a cycle.\n"));
     } else {
       for (auto& tgt : build) {
-        this->WriteProjectLine(fbld, tgt, root, rootBinaryDir);
+        this->WriteProjectLine(fbld, tgt, rootBinaryDir);
       }
     }
     fbld.Close();
@@ -490,7 +490,7 @@ void cmGlobalGhsMultiGenerator::WriteAllTarget(
           target->GetType() == cmStateEnums::SHARED_LIBRARY) {
         continue;
       }
-      this->WriteProjectLine(fbld, target, root, rootBinaryDir);
+      this->WriteProjectLine(fbld, target, rootBinaryDir);
     }
   }
   fbld.Close();

+ 1 - 1
Source/cmGlobalGhsMultiGenerator.h

@@ -103,7 +103,7 @@ private:
   void WriteSubProjects(std::ostream& fout, std::string& all_target);
   void WriteTargets(cmLocalGenerator* root);
   void WriteProjectLine(std::ostream& fout, cmGeneratorTarget const* target,
-                        cmLocalGenerator* root, std::string& rootBinaryDir);
+                        std::string& rootBinaryDir);
   void WriteCustomRuleBOD(std::ostream& fout);
   void WriteCustomTargetBOD(std::ostream& fout);
   void WriteAllTarget(cmLocalGenerator* root,

+ 2 - 4
Source/cmGlobalNinjaGenerator.cxx

@@ -1123,10 +1123,8 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath(
     return f->second;
   }
 
-  const auto& ng =
-    cm::static_reference_cast<cmLocalNinjaGenerator>(this->LocalGenerators[0]);
-  std::string const& bin_dir = ng.GetState()->GetBinaryDirectory();
-  std::string convPath = ng.MaybeConvertToRelativePath(bin_dir, path);
+  std::string convPath =
+    this->LocalGenerators[0]->MaybeRelativeToTopBinDir(path);
   convPath = this->NinjaOutputPath(convPath);
 #ifdef _WIN32
   std::replace(convPath.begin(), convPath.end(), '/', '\\');

+ 8 - 20
Source/cmGlobalUnixMakefileGenerator3.cxx

@@ -318,16 +318,13 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
     const auto& lg = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(
       this->LocalGenerators[0]);
 
-    const 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"
       << "  \"CMakeCache.txt\"\n";
     for (std::string const& f : lfiles) {
-      cmakefileStream << "  \""
-                      << lg.MaybeConvertToRelativePath(currentBinDir, f)
-                      << "\"\n";
+      cmakefileStream << "  \"" << lg.MaybeRelativeToCurBinDir(f) << "\"\n";
     }
     cmakefileStream << "  )\n\n";
 
@@ -339,17 +336,11 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
     // Set the corresponding makefile in the cmake file.
     cmakefileStream << "# The corresponding makefile is:\n"
                     << "set(CMAKE_MAKEFILE_OUTPUTS\n"
-                    << "  \""
-                    << lg.MaybeConvertToRelativePath(currentBinDir,
-                                                     makefileName)
+                    << "  \"" << lg.MaybeRelativeToCurBinDir(makefileName)
                     << "\"\n"
-                    << "  \""
-                    << lg.MaybeConvertToRelativePath(currentBinDir, check)
-                    << "\"\n";
+                    << "  \"" << lg.MaybeRelativeToCurBinDir(check) << "\"\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"
                     << "set(CMAKE_MAKEFILE_PRODUCTS\n";
@@ -359,14 +350,12 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
     for (const auto& localGen : this->LocalGenerators) {
       for (std::string const& outfile :
            localGen->GetMakefile()->GetOutputFiles()) {
-        cmakefileStream << "  \""
-                        << lg.MaybeConvertToRelativePath(binDir, outfile)
+        cmakefileStream << "  \"" << lg.MaybeRelativeToTopBinDir(outfile)
                         << "\"\n";
       }
       tmpStr = cmStrCat(localGen->GetCurrentBinaryDirectory(),
                         "/CMakeFiles/CMakeDirectoryInformation.cmake");
-      cmakefileStream << "  \""
-                      << localGen->MaybeConvertToRelativePath(binDir, tmpStr)
+      cmakefileStream << "  \"" << localGen->MaybeRelativeToTopBinDir(tmpStr)
                       << "\"\n";
     }
     cmakefileStream << "  )\n\n";
@@ -458,9 +447,8 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
   auto* lg = static_cast<cmLocalUnixMakefileGenerator3*>(dt.LG);
   // Begin the directory-level rules section.
   {
-    std::string dir =
-      cmSystemTools::ConvertToOutputPath(lg->MaybeConvertToRelativePath(
-        lg->GetBinaryDirectory(), lg->GetCurrentBinaryDirectory()));
+    std::string dir = cmSystemTools::ConvertToOutputPath(
+      lg->MaybeRelativeToTopBinDir(lg->GetCurrentBinaryDirectory()));
     lg->WriteDivider(ruleFileStream);
     if (lg->IsRootMakefile()) {
       ruleFileStream << "# Directory level rules for the build root directory";
@@ -610,7 +598,7 @@ cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
         tname += "/fast";
       }
       tname =
-        mf->GetStateSnapshot().GetDirectory().ConvertToRelPathIfNotContained(
+        mf->GetStateSnapshot().GetDirectory().ConvertToRelPathIfContained(
           mf->GetState()->GetBinaryDirectory(), tname);
       cmSystemTools::ConvertToOutputSlashes(tname);
       makeCommand.Add(std::move(tname));

+ 1 - 2
Source/cmGlobalVisualStudio7Generator.cxx

@@ -367,7 +367,6 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
 {
   VisualStudioFolders.clear();
 
-  std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
   for (cmGeneratorTarget const* target : projectTargets) {
     if (!target->IsInBuildSystem()) {
       continue;
@@ -390,7 +389,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
       if (vcprojName) {
         cmLocalGenerator* lg = target->GetLocalGenerator();
         std::string dir = lg->GetCurrentBinaryDirectory();
-        dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir);
+        dir = root->MaybeRelativeToCurBinDir(dir);
         if (dir == ".") {
           dir.clear(); // msbuild cannot handle ".\" prefix
         }

+ 3 - 10
Source/cmGlobalXCodeGenerator.cxx

@@ -586,13 +586,7 @@ 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->CurrentRootGenerator = root;
   this->CurrentXCodeHackMakefile =
     cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeScripts");
   cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile);
@@ -4704,13 +4698,12 @@ std::string cmGlobalXCodeGenerator::RelativeToSource(const std::string& p)
   // We force conversion because Xcode breakpoints do not work unless
   // they are in a file named relative to the source tree.
   return cmSystemTools::ForceToRelativePath(
-    cmSystemTools::JoinPath(this->ProjectSourceDirectoryComponents), p);
+    this->CurrentRootGenerator->GetCurrentSourceDirectory(), p);
 }
 
 std::string cmGlobalXCodeGenerator::RelativeToBinary(const std::string& p)
 {
-  return this->CurrentLocalGenerator->MaybeConvertToRelativePath(
-    cmSystemTools::JoinPath(this->ProjectOutputDirectoryComponents), p);
+  return this->CurrentRootGenerator->MaybeRelativeToCurBinDir(p);
 }
 
 std::string cmGlobalXCodeGenerator::XCodeEscapePath(const std::string& p)

+ 1 - 2
Source/cmGlobalXCodeGenerator.h

@@ -348,13 +348,12 @@ private:
   cmXCodeObject* FrameworkGroup;
   cmMakefile* CurrentMakefile;
   cmLocalGenerator* CurrentLocalGenerator;
+  cmLocalGenerator* CurrentRootGenerator = nullptr;
   std::vector<std::string> CurrentConfigurationTypes;
   std::string CurrentReRunCMakeMakefile;
   std::string CurrentXCodeHackMakefile;
   std::string CurrentProject;
   std::set<std::string> TargetDoneSet;
-  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;

+ 2 - 2
Source/cmListFileCache.cxx

@@ -550,7 +550,7 @@ void cmListFileBacktrace::PrintTitle(std::ostream& out) const
   cmListFileContext lfc = this->TopEntry->Context;
   cmStateSnapshot bottom = this->GetBottom();
   if (!bottom.GetState()->GetIsInTryCompile()) {
-    lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfNotContained(
+    lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfContained(
       bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
   }
   out << (lfc.Line ? " at " : " in ") << lfc;
@@ -581,7 +581,7 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const
     }
     cmListFileContext lfc = cur->Context;
     if (!bottom.GetState()->GetIsInTryCompile()) {
-      lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfNotContained(
+      lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfContained(
         bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
     }
     out << "  " << lfc << "\n";

+ 24 - 5
Source/cmLocalCommonGenerator.cxx

@@ -9,14 +9,17 @@
 #include "cmMakefile.h"
 #include "cmOutputConverter.h"
 #include "cmProperty.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
 #include "cmStringAlgorithms.h"
 
 class cmGlobalGenerator;
 
 cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg,
-                                               cmMakefile* mf, std::string wd)
+                                               cmMakefile* mf, WorkDir wd)
   : cmLocalGenerator(gg, mf)
-  , WorkingDirectory(std::move(wd))
+  , WorkingDirectory(wd)
 {
   this->ConfigNames =
     this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
@@ -24,6 +27,23 @@ cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg,
 
 cmLocalCommonGenerator::~cmLocalCommonGenerator() = default;
 
+std::string const& cmLocalCommonGenerator::GetWorkingDirectory() const
+{
+  if (this->WorkingDirectory == WorkDir::TopBin) {
+    return this->GetState()->GetBinaryDirectory();
+  }
+  return this->StateSnapshot.GetDirectory().GetCurrentBinary();
+}
+
+std::string cmLocalCommonGenerator::MaybeRelativeToWorkDir(
+  std::string const& path) const
+{
+  if (this->WorkingDirectory == WorkDir::TopBin) {
+    return this->MaybeRelativeToTopBinDir(path);
+  }
+  return this->MaybeRelativeToCurBinDir(path);
+}
+
 std::string cmLocalCommonGenerator::GetTargetFortranFlags(
   cmGeneratorTarget const* target, std::string const& config)
 {
@@ -35,11 +55,10 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags(
 
   // Add a module output directory flag if necessary.
   std::string mod_dir =
-    target->GetFortranModuleDirectory(this->WorkingDirectory);
+    target->GetFortranModuleDirectory(this->GetWorkingDirectory());
   if (!mod_dir.empty()) {
     mod_dir = this->ConvertToOutputFormat(
-      this->MaybeConvertToRelativePath(this->WorkingDirectory, mod_dir),
-      cmOutputConverter::SHELL);
+      this->MaybeRelativeToWorkDir(mod_dir), cmOutputConverter::SHELL);
   } else {
     mod_dir =
       this->Makefile->GetSafeDefinition("CMAKE_Fortran_MODDIR_DEFAULT");

+ 12 - 4
Source/cmLocalCommonGenerator.h

@@ -20,9 +20,15 @@ class cmSourceFile;
  */
 class cmLocalCommonGenerator : public cmLocalGenerator
 {
+protected:
+  enum class WorkDir
+  {
+    TopBin,
+    CurBin,
+  };
+
 public:
-  cmLocalCommonGenerator(cmGlobalGenerator* gg, cmMakefile* mf,
-                         std::string wd);
+  cmLocalCommonGenerator(cmGlobalGenerator* gg, cmMakefile* mf, WorkDir wd);
   ~cmLocalCommonGenerator() override;
 
   std::vector<std::string> const& GetConfigNames() const
@@ -30,7 +36,9 @@ public:
     return this->ConfigNames;
   }
 
-  std::string GetWorkingDirectory() const { return this->WorkingDirectory; }
+  std::string const& GetWorkingDirectory() const;
+
+  std::string MaybeRelativeToWorkDir(std::string const& path) const;
 
   std::string GetTargetFortranFlags(cmGeneratorTarget const* target,
                                     std::string const& config) override;
@@ -40,7 +48,7 @@ public:
     cmGeneratorTarget const* gt = nullptr) override;
 
 protected:
-  std::string WorkingDirectory;
+  WorkDir WorkingDirectory;
 
   std::vector<std::string> ConfigNames;
 

+ 24 - 10
Source/cmLocalGenerator.cxx

@@ -351,11 +351,10 @@ void cmLocalGenerator::GenerateTestFiles()
   }
   using vec_t = std::vector<cmStateSnapshot>;
   vec_t const& children = this->Makefile->GetStateSnapshot().GetChildren();
-  std::string parentBinDir = this->GetCurrentBinaryDirectory();
   for (cmStateSnapshot const& i : children) {
     // TODO: Use add_subdirectory instead?
     std::string outP = i.GetDirectory().GetCurrentBinary();
-    outP = this->MaybeConvertToRelativePath(parentBinDir, outP);
+    outP = this->MaybeRelativeToCurBinDir(outP);
     outP = cmOutputConverter::EscapeForCMake(outP);
     fout << "subdirs(" << outP << ")\n";
   }
@@ -3286,10 +3285,9 @@ std::string cmLocalGenerator::ConstructComment(
     std::string comment;
     comment = "Generating ";
     const char* sep = "";
-    std::string currentBinaryDir = this->GetCurrentBinaryDirectory();
     for (std::string const& o : ccg.GetOutputs()) {
       comment += sep;
-      comment += this->MaybeConvertToRelativePath(currentBinaryDir, o);
+      comment += this->MaybeRelativeToCurBinDir(o);
       sep = ", ";
     }
     return comment;
@@ -3550,15 +3548,13 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
   std::string const& fullPath = source.GetFullPath();
 
   // Try referencing the source relative to the source tree.
-  std::string relFromSource = this->MaybeConvertToRelativePath(
-    this->GetCurrentSourceDirectory(), fullPath);
+  std::string relFromSource = this->MaybeRelativeToCurSrcDir(fullPath);
   assert(!relFromSource.empty());
   bool relSource = !cmSystemTools::FileIsFullPath(relFromSource);
   bool subSource = relSource && relFromSource[0] != '.';
 
   // Try referencing the source relative to the binary tree.
-  std::string relFromBinary = this->MaybeConvertToRelativePath(
-    this->GetCurrentBinaryDirectory(), fullPath);
+  std::string relFromBinary = this->MaybeRelativeToCurBinDir(fullPath);
   assert(!relFromBinary.empty());
   bool relBinary = !cmSystemTools::FileIsFullPath(relFromBinary);
   bool subBinary = relBinary && relFromBinary[0] != '.';
@@ -3673,13 +3669,31 @@ std::string const& cmLocalGenerator::GetCurrentSourceDirectory() const
   return this->StateSnapshot.GetDirectory().GetCurrentSource();
 }
 
-std::string cmLocalGenerator::MaybeConvertToRelativePath(
+std::string cmLocalGenerator::MaybeRelativeTo(
   std::string const& local_path, std::string const& remote_path) const
 {
-  return this->StateSnapshot.GetDirectory().ConvertToRelPathIfNotContained(
+  return this->StateSnapshot.GetDirectory().ConvertToRelPathIfContained(
     local_path, remote_path);
 }
 
+std::string cmLocalGenerator::MaybeRelativeToTopBinDir(
+  std::string const& path) const
+{
+  return this->MaybeRelativeTo(this->GetBinaryDirectory(), path);
+}
+
+std::string cmLocalGenerator::MaybeRelativeToCurBinDir(
+  std::string const& path) const
+{
+  return this->MaybeRelativeTo(this->GetCurrentBinaryDirectory(), path);
+}
+
+std::string cmLocalGenerator::MaybeRelativeToCurSrcDir(
+  std::string const& path) const
+{
+  return this->MaybeRelativeTo(this->GetCurrentSourceDirectory(), path);
+}
+
 std::string cmLocalGenerator::GetTargetDirectory(
   const cmGeneratorTarget* /*unused*/) const
 {

+ 8 - 4
Source/cmLocalGenerator.h

@@ -464,13 +464,14 @@ public:
 
   /**
    * 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.
+   * one of our common work directories.  The path must use forward
+   * slashes and not already be escaped or quoted.
    * The conversion is skipped if the paths are not both in the source
    * or both in the binary tree.
    */
-  std::string MaybeConvertToRelativePath(std::string const& local_path,
-                                         std::string const& remote_path) const;
+  std::string MaybeRelativeToTopBinDir(std::string const& path) const;
+  std::string MaybeRelativeToCurBinDir(std::string const& path) const;
+  std::string MaybeRelativeToCurSrcDir(std::string const& path) const;
 
   /**
    * Generate a macOS application bundle Info.plist file.
@@ -558,6 +559,9 @@ public:
   cmProp GetRuleLauncher(cmGeneratorTarget* target, const std::string& prop);
 
 protected:
+  std::string MaybeRelativeTo(std::string const& local_path,
+                              std::string const& remote_path) const;
+
   // The default implementation ignores the IncludePathStyle and always
   // uses absolute paths.  A generator may override this to use relative
   // paths in some cases.

+ 6 - 8
Source/cmLocalNinjaGenerator.cxx

@@ -39,7 +39,7 @@
 
 cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
                                              cmMakefile* mf)
-  : cmLocalCommonGenerator(gg, mf, mf->GetState()->GetBinaryDirectory())
+  : cmLocalCommonGenerator(gg, mf, WorkDir::TopBin)
 {
 }
 
@@ -60,8 +60,8 @@ void cmLocalNinjaGenerator::Generate()
 {
   // Compute the path to use when referencing the current output
   // directory from the top output directory.
-  this->HomeRelativeOutputPath = this->MaybeConvertToRelativePath(
-    this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory());
+  this->HomeRelativeOutputPath =
+    this->MaybeRelativeToTopBinDir(this->GetCurrentBinaryDirectory());
   if (this->HomeRelativeOutputPath == ".") {
     this->HomeRelativeOutputPath.clear();
   }
@@ -213,9 +213,8 @@ std::string cmLocalNinjaGenerator::ConvertToIncludeReference(
       cmSystemTools::CollapseFullPath(path, this->GetCurrentBinaryDirectory()),
       format);
   }
-  return this->ConvertToOutputFormat(
-    this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), path),
-    format);
+  return this->ConvertToOutputFormat(this->MaybeRelativeToTopBinDir(path),
+                                     format);
 }
 
 // Private methods.
@@ -881,8 +880,7 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
   if (!outputs.empty()) {
     output = outputs[0];
     if (ccg.GetWorkingDirectory().empty()) {
-      output = this->MaybeConvertToRelativePath(
-        this->GetCurrentBinaryDirectory(), output);
+      output = this->MaybeRelativeToCurBinDir(output);
     }
     output = this->ConvertToOutputFormat(output, cmOutputConverter::SHELL);
   }

+ 25 - 40
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -110,7 +110,7 @@ private:
 
 cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3(
   cmGlobalGenerator* gg, cmMakefile* mf)
-  : cmLocalCommonGenerator(gg, mf, mf->GetCurrentBinaryDirectory())
+  : cmLocalCommonGenerator(gg, mf, WorkDir::CurBin)
 {
   this->MakefileVariableSize = 0;
   this->ColorMakefile = false;
@@ -177,8 +177,8 @@ void cmLocalUnixMakefileGenerator3::ComputeHomeRelativeOutputPath()
 {
   // Compute the path to use when referencing the current output
   // directory from the top output directory.
-  this->HomeRelativeOutputPath = this->MaybeConvertToRelativePath(
-    this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory());
+  this->HomeRelativeOutputPath =
+    this->MaybeRelativeToTopBinDir(this->GetCurrentBinaryDirectory());
   if (this->HomeRelativeOutputPath == ".") {
     this->HomeRelativeOutputPath.clear();
   }
@@ -561,8 +561,8 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
   }
 
   // Construct the left hand side of the rule.
-  std::string tgt = this->ConvertToMakefilePath(
-    this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), target));
+  std::string tgt =
+    this->ConvertToMakefilePath(this->MaybeRelativeToTopBinDir(target));
 
   const char* space = "";
   if (tgt.size() == 1) {
@@ -586,11 +586,9 @@ 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::string const& depend : depends) {
       os << tgt << space << ": "
-         << this->ConvertToMakefilePath(
-              this->MaybeConvertToRelativePath(binDir, depend))
+         << this->ConvertToMakefilePath(this->MaybeRelativeToTopBinDir(depend))
          << '\n';
     }
   }
@@ -968,7 +966,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);
@@ -993,7 +990,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
       // working directory will be the start-output directory.
       bool had_slash = cmd.find('/') != std::string::npos;
       if (workingDir.empty()) {
-        cmd = this->MaybeConvertToRelativePath(currentBinDir, cmd);
+        cmd = this->MaybeRelativeToCurBinDir(cmd);
       }
       bool has_slash = cmd.find('/') != std::string::npos;
       if (had_slash && !has_slash) {
@@ -1017,8 +1014,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
         if (!outputs.empty()) {
           output = outputs[0];
           if (workingDir.empty()) {
-            output = this->MaybeConvertToRelativePath(
-              this->GetCurrentBinaryDirectory(), output);
+            output = this->MaybeRelativeToCurBinDir(output);
           }
           output =
             this->ConvertToOutputFormat(output, cmOutputConverter::SHELL);
@@ -1097,18 +1093,16 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
   if (!files.empty()) {
     fout << "file(REMOVE_RECURSE\n";
     for (std::string const& file : files) {
-      std::string fc = this->MaybeConvertToRelativePath(currentBinDir, file);
+      std::string fc = this->MaybeRelativeToCurBinDir(file);
       fout << "  " << cmOutputConverter::EscapeForCMake(fc) << "\n";
     }
     fout << ")\n";
   }
   {
-    std::string remove =
-      cmStrCat("$(CMAKE_COMMAND) -P ",
-               this->ConvertToOutputFormat(
-                 this->MaybeConvertToRelativePath(
-                   this->GetCurrentBinaryDirectory(), cleanfile),
-                 cmOutputConverter::SHELL));
+    std::string remove = cmStrCat(
+      "$(CMAKE_COMMAND) -P ",
+      this->ConvertToOutputFormat(this->MaybeRelativeToCurBinDir(cleanfile),
+                                  cmOutputConverter::SHELL));
     commands.push_back(std::move(remove));
   }
 
@@ -1146,7 +1140,6 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand(
   }
 
   const auto& rootLG = this->GetGlobalGenerator()->GetLocalGenerators().at(0);
-  std::string const& binaryDir = rootLG->GetCurrentBinaryDirectory();
   std::string const& currentBinaryDir = this->GetCurrentBinaryDirectory();
   std::string cleanfile =
     cmStrCat(currentBinaryDir, "/CMakeFiles/cmake_directory_clean.cmake");
@@ -1159,19 +1152,18 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand(
     }
     fout << "file(REMOVE_RECURSE\n";
     for (std::string const& cfl : cleanFiles) {
-      std::string fc = rootLG->MaybeConvertToRelativePath(
-        binaryDir, cmSystemTools::CollapseFullPath(cfl, currentBinaryDir));
+      std::string fc = rootLG->MaybeRelativeToCurBinDir(
+        cmSystemTools::CollapseFullPath(cfl, currentBinaryDir));
       fout << "  " << cmOutputConverter::EscapeForCMake(fc) << "\n";
     }
     fout << ")\n";
   }
   // Create command
   {
-    std::string remove =
-      cmStrCat("$(CMAKE_COMMAND) -P ",
-               this->ConvertToOutputFormat(
-                 rootLG->MaybeConvertToRelativePath(binaryDir, cleanfile),
-                 cmOutputConverter::SHELL));
+    std::string remove = cmStrCat(
+      "$(CMAKE_COMMAND) -P ",
+      this->ConvertToOutputFormat(rootLG->MaybeRelativeToCurBinDir(cleanfile),
+                                  cmOutputConverter::SHELL));
     commands.push_back(std::move(remove));
   }
 }
@@ -1964,8 +1956,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
         cm::erase_if(includes, ::NotInProjectDir(sourceDir, binaryDir));
       }
       for (std::string const& include : includes) {
-        cmakefileStream << "  \""
-                        << this->MaybeConvertToRelativePath(binaryDir, include)
+        cmakefileStream << "  \"" << this->MaybeRelativeToTopBinDir(include)
                         << "\"\n";
       }
       cmakefileStream << "  )\n";
@@ -2004,12 +1995,9 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
       for (auto const& compilerPair : compilerPairs) {
         for (auto const& src : compilerPair.second) {
           cmakefileStream << R"(  "" ")"
-                          << this->MaybeConvertToRelativePath(
-                               this->GetBinaryDirectory(), compilerPair.first)
+                          << this->MaybeRelativeToTopBinDir(compilerPair.first)
                           << R"(" "custom" ")"
-                          << this->MaybeConvertToRelativePath(
-                               this->GetBinaryDirectory(), src)
-                          << "\"\n";
+                          << this->MaybeRelativeToTopBinDir(src) << "\"\n";
         }
       }
     } else {
@@ -2018,11 +2006,9 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
       for (auto const& compilerPair : compilerPairs) {
         for (auto const& src : compilerPair.second) {
           cmakefileStream << "  \"" << src << "\" \""
-                          << this->MaybeConvertToRelativePath(
-                               this->GetBinaryDirectory(), compilerPair.first)
+                          << this->MaybeRelativeToTopBinDir(compilerPair.first)
                           << "\" \"" << depFormat << "\" \""
-                          << this->MaybeConvertToRelativePath(
-                               this->GetBinaryDirectory(), compilerPair.first)
+                          << this->MaybeRelativeToTopBinDir(compilerPair.first)
                           << ".d\"\n";
         }
       }
@@ -2066,8 +2052,7 @@ std::string cmLocalUnixMakefileGenerator3::GetRecursiveMakeCall(
   // Add the target.
   if (!tgt.empty()) {
     // The make target is always relative to the top of the build tree.
-    std::string tgt2 =
-      this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), tgt);
+    std::string tgt2 = this->MaybeRelativeToTopBinDir(tgt);
 
     // The target may have been written with windows paths.
     cmSystemTools::ConvertToOutputSlashes(tgt2);

+ 4 - 9
Source/cmLocalVisualStudio7Generator.cxx

@@ -784,8 +784,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
     cmProp target_mod_dir = target->GetProperty("Fortran_MODULE_DIRECTORY");
     std::string modDir;
     if (target_mod_dir) {
-      modDir = this->MaybeConvertToRelativePath(
-        this->GetCurrentBinaryDirectory(), *target_mod_dir);
+      modDir = this->MaybeRelativeToCurBinDir(*target_mod_dir);
     } else {
       modDir = ".";
     }
@@ -1254,11 +1253,9 @@ void cmLocalVisualStudio7GeneratorInternals::OutputLibraries(
   std::ostream& fout, ItemVector const& libs)
 {
   cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
-  std::string currentBinDir = lg->GetCurrentBinaryDirectory();
   for (auto const& lib : libs) {
     if (lib.IsPath) {
-      std::string rel =
-        lg->MaybeConvertToRelativePath(currentBinDir, lib.Value.Value);
+      std::string rel = lg->MaybeRelativeToCurBinDir(lib.Value.Value);
       fout << lg->ConvertToXMLOutputPath(rel) << " ";
     } else if (!lib.Target ||
                lib.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
@@ -1274,7 +1271,6 @@ 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<cmSourceFile const*> objs;
   gt->GetExternalObjects(objs, configName);
@@ -1283,7 +1279,7 @@ void cmLocalVisualStudio7GeneratorInternals::OutputObjects(
   for (cmSourceFile const* obj : objs) {
     if (!obj->GetObjectLibrary().empty()) {
       std::string const& objFile = obj->GetFullPath();
-      std::string rel = lg->MaybeConvertToRelativePath(currentBinDir, objFile);
+      std::string rel = lg->MaybeRelativeToCurBinDir(objFile);
       fout << sep << lg->ConvertToXMLOutputPath(rel);
       sep = " ";
     }
@@ -1294,7 +1290,6 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories(
   std::ostream& fout, std::vector<std::string> const& dirs)
 {
   const char* comma = "";
-  std::string currentBinDir = this->GetCurrentBinaryDirectory();
   for (std::string dir : dirs) {
     // Remove any trailing slash and skip empty paths.
     if (dir.back() == '/') {
@@ -1306,7 +1301,7 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories(
 
     // Switch to a relative path specification if it is shorter.
     if (cmSystemTools::FileIsFullPath(dir)) {
-      std::string rel = this->MaybeConvertToRelativePath(currentBinDir, dir);
+      std::string rel = this->MaybeRelativeToCurBinDir(dir);
       if (rel.size() < dir.size()) {
         dir = rel;
       }

+ 2 - 4
Source/cmLocalVisualStudioGenerator.cxx

@@ -207,10 +207,8 @@ std::string cmLocalVisualStudioGenerator::ConstructScript(
     }
 
     if (workingDirectory.empty()) {
-      script +=
-        this->ConvertToOutputFormat(this->MaybeConvertToRelativePath(
-                                      this->GetCurrentBinaryDirectory(), cmd),
-                                    cmOutputConverter::SHELL);
+      script += this->ConvertToOutputFormat(
+        this->MaybeRelativeToCurBinDir(cmd), cmOutputConverter::SHELL);
     } else {
       script += this->ConvertToOutputFormat(cmd.c_str(), SHELL);
     }

+ 26 - 40
Source/cmMakefileExecutableTargetGenerator.cxx

@@ -104,13 +104,11 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
     cmLocalUnixMakefileGenerator3::EchoProgress progress;
     this->MakeEchoProgress(progress);
     // Add the link message.
-    std::string buildEcho =
-      cmStrCat("Linking CUDA device code ",
-               this->LocalGenerator->ConvertToOutputFormat(
-                 this->LocalGenerator->MaybeConvertToRelativePath(
-                   this->LocalGenerator->GetCurrentBinaryDirectory(),
-                   this->DeviceLinkObject),
-                 cmOutputConverter::SHELL));
+    std::string buildEcho = cmStrCat(
+      "Linking CUDA device code ",
+      this->LocalGenerator->ConvertToOutputFormat(
+        this->LocalGenerator->MaybeRelativeToCurBinDir(this->DeviceLinkObject),
+        cmOutputConverter::SHELL));
     this->LocalGenerator->AppendEcho(
       commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
   }
@@ -152,8 +150,8 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
   // Construct a list of files associated with this executable that
   // may need to be cleaned.
   std::vector<std::string> exeCleanFiles;
-  exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
-    this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutput));
+  exeCleanFiles.push_back(
+    this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput));
 
   // Determine whether a link script will be used.
   bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
@@ -203,17 +201,14 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
     std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
 
     objectDir = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+      this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir),
       cmOutputConverter::SHELL);
 
     cmOutputConverter::OutputFormat output = (useWatcomQuote)
       ? cmOutputConverter::WATCOMQUOTE
       : cmOutputConverter::SHELL;
     std::string target = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutput),
-      output);
+      this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput), output);
 
     std::string targetFullPathCompilePDB =
       this->ComputeTargetCompilePDB(this->GetConfigName());
@@ -330,18 +325,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     targetFullPathPDB, cmOutputConverter::SHELL);
   // Convert to the output path to use in constructing commands.
   std::string targetOutPath = this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath),
+    this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPath),
     cmOutputConverter::SHELL);
   std::string targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+    this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal),
     cmOutputConverter::SHELL);
   std::string targetOutPathImport =
     this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(),
-        targetFullPathImport),
+      this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathImport),
       cmOutputConverter::SHELL);
 
   // Get the language to use for linking this executable.
@@ -436,36 +427,34 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
   // Construct a list of files associated with this executable that
   // may need to be cleaned.
   std::vector<std::string> exeCleanFiles;
-  exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
-    this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath));
+  exeCleanFiles.push_back(
+    this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPath));
 #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->MaybeConvertToRelativePath(
-    this->LocalGenerator->GetCurrentBinaryDirectory(),
+  exeCleanFiles.push_back(this->LocalGenerator->MaybeRelativeToCurBinDir(
     targetFullPath + ".manifest"));
 #endif
   if (this->TargetNames.Real != this->TargetNames.Output) {
-    exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal));
+    exeCleanFiles.push_back(
+      this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal));
   }
   if (!this->TargetNames.ImportLibrary.empty()) {
-    exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(),
-      targetFullPathImport));
+    exeCleanFiles.push_back(
+      this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathImport));
     std::string implib;
     if (this->GeneratorTarget->GetImplibGNUtoMS(
           this->GetConfigName(), targetFullPathImport, implib)) {
-      exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), implib));
+      exeCleanFiles.push_back(
+        this->LocalGenerator->MaybeRelativeToCurBinDir(implib));
     }
   }
 
   // List the PDB for cleaning only when the whole target is
   // cleaned.  We do not want to delete the .pdb file just before
   // linking the target.
-  this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
-    this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathPDB));
+  this->CleanFiles.insert(
+    this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathPDB));
 
   // Add the pre-build and pre-link rules building but not when relinking.
   if (!relink) {
@@ -529,8 +518,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     if (!this->DeviceLinkObject.empty()) {
       buildObjs += " " +
         this->LocalGenerator->ConvertToOutputFormat(
-          this->LocalGenerator->MaybeConvertToRelativePath(
-            this->LocalGenerator->GetCurrentBinaryDirectory(),
+          this->LocalGenerator->MaybeRelativeToCurBinDir(
             this->DeviceLinkObject),
           cmOutputConverter::SHELL);
     }
@@ -549,16 +537,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
 
     objectDir = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+      this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir),
       cmOutputConverter::SHELL);
     vars.ObjectDir = objectDir.c_str();
     cmOutputConverter::OutputFormat output = (useWatcomQuote)
       ? cmOutputConverter::WATCOMQUOTE
       : cmOutputConverter::SHELL;
     std::string target = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+      this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal),
       output);
     vars.Target = target.c_str();
     vars.TargetPDB = targetOutPathPDB.c_str();

+ 30 - 46
Source/cmMakefileLibraryTargetGenerator.cxx

@@ -250,13 +250,11 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
     cmLocalUnixMakefileGenerator3::EchoProgress progress;
     this->MakeEchoProgress(progress);
     // Add the link message.
-    std::string buildEcho =
-      cmStrCat("Linking CUDA device code ",
-               this->LocalGenerator->ConvertToOutputFormat(
-                 this->LocalGenerator->MaybeConvertToRelativePath(
-                   this->LocalGenerator->GetCurrentBinaryDirectory(),
-                   this->DeviceLinkObject),
-                 cmOutputConverter::SHELL));
+    std::string buildEcho = cmStrCat(
+      "Linking CUDA device code ",
+      this->LocalGenerator->ConvertToOutputFormat(
+        this->LocalGenerator->MaybeRelativeToCurBinDir(this->DeviceLinkObject),
+        cmOutputConverter::SHELL));
     this->LocalGenerator->AppendEcho(
       commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
   }
@@ -293,8 +291,8 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
 
   // Clean files associated with this library.
   std::set<std::string> libCleanFiles;
-  libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
-    this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutput));
+  libCleanFiles.insert(
+    this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput));
 
   // Determine whether a link script will be used.
   bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
@@ -342,14 +340,11 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
 
     std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
     objectDir = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+      this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir),
       cmOutputConverter::SHELL);
 
     std::string target = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutput),
-      output);
+      this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput), output);
 
     std::string targetFullPathCompilePDB =
       this->ComputeTargetCompilePDB(this->GetConfigName());
@@ -519,22 +514,17 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     targetFullPathPDB, cmOutputConverter::SHELL);
 
   std::string targetOutPath = this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath),
+    this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPath),
     cmOutputConverter::SHELL);
   std::string targetOutPathSO = this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathSO),
+    this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathSO),
     cmOutputConverter::SHELL);
   std::string targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+    this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal),
     cmOutputConverter::SHELL);
   std::string targetOutPathImport =
     this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(),
-        targetFullPathImport),
+      this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathImport),
       cmOutputConverter::SHELL);
 
   this->NumberOfProgressActions++;
@@ -567,8 +557,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
 
   // Clean files associated with this library.
   std::set<std::string> libCleanFiles;
-  libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
-    this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal));
+  libCleanFiles.insert(
+    this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal));
 
   std::vector<std::string> commands1;
   // Add a command to remove any existing files for this library.
@@ -584,38 +574,36 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
   }
 
   if (this->TargetNames.Output != this->TargetNames.Real) {
-    libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath));
+    libCleanFiles.insert(
+      this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPath));
   }
   if (this->TargetNames.SharedObject != this->TargetNames.Real &&
       this->TargetNames.SharedObject != this->TargetNames.Output) {
-    libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathSO));
+    libCleanFiles.insert(
+      this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathSO));
   }
   if (!this->TargetNames.ImportLibrary.empty()) {
-    libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(),
-      targetFullPathImport));
+    libCleanFiles.insert(
+      this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathImport));
     std::string implib;
     if (this->GeneratorTarget->GetImplibGNUtoMS(
           this->GetConfigName(), targetFullPathImport, implib)) {
-      libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), implib));
+      libCleanFiles.insert(
+        this->LocalGenerator->MaybeRelativeToCurBinDir(implib));
     }
   }
 
   // List the PDB for cleaning only when the whole target is
   // cleaned.  We do not want to delete the .pdb file just before
   // linking the target.
-  this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
-    this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathPDB));
+  this->CleanFiles.insert(
+    this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathPDB));
 
 #ifdef _WIN32
   // There may be a manifest file for this target.  Add it to the
   // clean set just in case.
   if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) {
-    libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(),
+    libCleanFiles.insert(this->LocalGenerator->MaybeRelativeToCurBinDir(
       targetFullPath + ".manifest"));
   }
 #endif
@@ -723,8 +711,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     if (!this->DeviceLinkObject.empty()) {
       buildObjs += " " +
         this->LocalGenerator->ConvertToOutputFormat(
-          this->LocalGenerator->MaybeConvertToRelativePath(
-            this->LocalGenerator->GetCurrentBinaryDirectory(),
+          this->LocalGenerator->MaybeRelativeToCurBinDir(
             this->DeviceLinkObject),
           cmOutputConverter::SHELL);
     }
@@ -765,8 +752,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
 
     objectDir = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+      this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir),
       cmOutputConverter::SHELL);
 
     vars.ObjectDir = objectDir.c_str();
@@ -774,8 +760,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
       ? cmOutputConverter::WATCOMQUOTE
       : cmOutputConverter::SHELL;
     std::string target = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+      this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal),
       output);
     vars.Target = target.c_str();
     vars.LinkLibraries = linkLibs.c_str();
@@ -839,8 +824,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
       // only occur on archives which have CUDA_RESOLVE_DEVICE_SYMBOLS enabled
       if (!this->DeviceLinkObject.empty()) {
         object_strings.push_back(this->LocalGenerator->ConvertToOutputFormat(
-          this->LocalGenerator->MaybeConvertToRelativePath(
-            this->LocalGenerator->GetCurrentBinaryDirectory(),
+          this->LocalGenerator->MaybeRelativeToCurBinDir(
             this->DeviceLinkObject),
           cmOutputConverter::SHELL));
       }

+ 48 - 77
Source/cmMakefileTargetGenerator.cxx

@@ -218,15 +218,12 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
     }
   }
 
-  std::string currentBinDir =
-    this->LocalGenerator->GetCurrentBinaryDirectory();
-
   // Look for ISPC extra object files generated by this target
   auto ispcAdditionalObjs =
     this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName());
   for (std::string const& ispcObj : ispcAdditionalObjs) {
-    this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
-      currentBinDir, ispcObj));
+    this->CleanFiles.insert(
+      this->LocalGenerator->MaybeRelativeToCurBinDir(ispcObj));
   }
 
   // add custom commands to the clean rules?
@@ -251,14 +248,12 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
       const std::vector<std::string>& outputs = ccg.GetOutputs();
       for (std::string const& output : outputs) {
         this->CleanFiles.insert(
-          this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
-                                                           output));
+          this->LocalGenerator->MaybeRelativeToCurBinDir(output));
       }
       const std::vector<std::string>& byproducts = ccg.GetByproducts();
       for (std::string const& byproduct : byproducts) {
         this->CleanFiles.insert(
-          this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
-                                                           byproduct));
+          this->LocalGenerator->MaybeRelativeToCurBinDir(byproduct));
       }
     }
   }
@@ -279,8 +274,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
       const std::vector<std::string>& byproducts = beg.GetByproducts();
       for (std::string const& byproduct : byproducts) {
         this->CleanFiles.insert(
-          this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
-                                                           byproduct));
+          this->LocalGenerator->MaybeRelativeToCurBinDir(byproduct));
       }
     }
   }
@@ -327,8 +321,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
     << "# Include any dependencies generated for this target.\n"
     << this->GlobalGenerator->IncludeDirective << " " << root
     << cmSystemTools::ConvertToOutputPath(
-         this->LocalGenerator->MaybeConvertToRelativePath(
-           this->LocalGenerator->GetBinaryDirectory(), dependFileNameFull))
+         this->LocalGenerator->MaybeRelativeToTopBinDir(dependFileNameFull))
     << "\n";
 
   std::string depsUseCompiler = "CMAKE_DEPENDS_USE_COMPILER";
@@ -336,14 +329,14 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
       this->Makefile->IsOn(depsUseCompiler)) {
     std::string compilerDependFile =
       cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make");
-    *this->BuildFileStream
-      << "# Include any dependencies generated by the "
-         "compiler for this target.\n"
-      << this->GlobalGenerator->IncludeDirective << " " << root
-      << cmSystemTools::ConvertToOutputPath(
-           this->LocalGenerator->MaybeConvertToRelativePath(
-             this->LocalGenerator->GetBinaryDirectory(), compilerDependFile))
-      << "\n\n";
+    *this->BuildFileStream << "# Include any dependencies generated by the "
+                              "compiler for this target.\n"
+                           << this->GlobalGenerator->IncludeDirective << " "
+                           << root
+                           << cmSystemTools::ConvertToOutputPath(
+                                this->LocalGenerator->MaybeRelativeToTopBinDir(
+                                  compilerDependFile))
+                           << "\n\n";
 
     // Write an empty dependency file.
     cmGeneratedFileStream depFileStream(
@@ -399,8 +392,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
       << "# Include the progress variables for this target.\n"
       << this->GlobalGenerator->IncludeDirective << " " << root
       << cmSystemTools::ConvertToOutputPath(
-           this->LocalGenerator->MaybeConvertToRelativePath(
-             this->LocalGenerator->GetBinaryDirectory(),
+           this->LocalGenerator->MaybeRelativeToTopBinDir(
              this->ProgressFileNameFull))
       << "\n\n";
   }
@@ -423,8 +415,8 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
     << "# Include the compile flags for this target's objects.\n"
     << this->GlobalGenerator->IncludeDirective << " " << root
     << cmSystemTools::ConvertToOutputPath(
-         this->LocalGenerator->MaybeConvertToRelativePath(
-           this->LocalGenerator->GetBinaryDirectory(), this->FlagFileNameFull))
+         this->LocalGenerator->MaybeRelativeToTopBinDir(
+           this->FlagFileNameFull))
     << "\n\n";
 }
 
@@ -491,10 +483,8 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()(
   std::string output =
     cmStrCat(macdir, '/', cmSystemTools::GetFilenameName(input));
   this->Generator->CleanFiles.insert(
-    this->Generator->LocalGenerator->MaybeConvertToRelativePath(
-      this->Generator->LocalGenerator->GetCurrentBinaryDirectory(), output));
-  output = this->Generator->LocalGenerator->MaybeConvertToRelativePath(
-    this->Generator->LocalGenerator->GetBinaryDirectory(), output);
+    this->Generator->LocalGenerator->MaybeRelativeToCurBinDir(output));
+  output = this->Generator->LocalGenerator->MaybeRelativeToTopBinDir(output);
 
   // Create a rule to copy the content into the bundle.
   std::vector<std::string> depends;
@@ -797,15 +787,12 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
     }
 
     targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+      this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal),
       cmOutputConverter::SHELL);
     targetOutPathPDB = this->LocalGenerator->ConvertToOutputFormat(
       targetFullPathPDB, cmOutputConverter::SHELL);
     targetOutPathCompilePDB = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(),
-        targetFullPathCompilePDB),
+      this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathCompilePDB),
       cmOutputConverter::SHELL);
 
     if (this->LocalGenerator->IsMinGWMake() &&
@@ -834,14 +821,12 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
   vars.Object = shellObj.c_str();
   std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
   objectDir = this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+    this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir),
     cmOutputConverter::SHELL);
   vars.ObjectDir = objectDir.c_str();
   std::string objectFileDir = cmSystemTools::GetFilenamePath(obj);
   objectFileDir = this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), objectFileDir),
+    this->LocalGenerator->MaybeRelativeToCurBinDir(objectFileDir),
     cmOutputConverter::SHELL);
   vars.ObjectFileDir = objectFileDir.c_str();
   vars.Flags = flags.c_str();
@@ -865,8 +850,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
   if (compilerGenerateDeps) {
     dependencyTarget = this->LocalGenerator->EscapeForShell(
       this->LocalGenerator->ConvertToMakefilePath(
-        this->LocalGenerator->MaybeConvertToRelativePath(
-          this->LocalGenerator->GetBinaryDirectory(), relativeObj)));
+        this->LocalGenerator->MaybeRelativeToTopBinDir(relativeObj)));
     vars.DependencyTarget = dependencyTarget.c_str();
 
     auto depFile = cmStrCat(obj, ".d");
@@ -875,8 +859,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
     vars.DependencyFile = shellDependencyFile.c_str();
     this->CleanFiles.insert(depFile);
 
-    dependencyTimestamp = this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetBinaryDirectory(),
+    dependencyTimestamp = this->LocalGenerator->MaybeRelativeToTopBinDir(
       cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts"));
   }
 
@@ -1302,12 +1285,11 @@ 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::string const& output : cmMakeRange(outputs).advance(1)) {
     // Touch the extra output so "make" knows that it was updated,
     // but only if the output was actually created.
     std::string const out = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(binDir, output),
+      this->LocalGenerator->MaybeRelativeToTopBinDir(output),
       cmOutputConverter::SHELL);
     std::vector<std::string> output_commands;
 
@@ -1515,14 +1497,12 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
 
   const std::string objectDir = this->GeneratorTarget->ObjectDirectory;
   const std::string relObjectDir =
-    this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir);
+    this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir);
 
   // Construct a list of files associated with this executable that
   // may need to be cleaned.
   std::vector<std::string> cleanFiles;
-  cleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
-    this->LocalGenerator->GetCurrentBinaryDirectory(), output));
+  cleanFiles.push_back(this->LocalGenerator->MaybeRelativeToCurBinDir(output));
 
   std::string profiles;
   std::vector<std::string> fatbinaryDepends;
@@ -1547,8 +1527,7 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
     // generate it only on the first invocation to reduce overhead.
     if (fatbinaryDepends.size() == 1) {
       std::string registerFileRel =
-        this->LocalGenerator->MaybeConvertToRelativePath(
-          this->LocalGenerator->GetCurrentBinaryDirectory(), registerFile);
+        this->LocalGenerator->MaybeRelativeToCurBinDir(registerFile);
       registerFileCmd =
         cmStrCat(" --register-link-binaries=", registerFileRel);
       cleanFiles.push_back(registerFileRel);
@@ -1572,8 +1551,7 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
   const std::string fatbinaryOutput =
     cmStrCat(objectDir, "cmake_cuda_fatbin.h");
   const std::string fatbinaryOutputRel =
-    this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), fatbinaryOutput);
+    this->LocalGenerator->MaybeRelativeToCurBinDir(fatbinaryOutput);
 
   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
                                       fatbinaryOutputRel, fatbinaryDepends,
@@ -1640,8 +1618,7 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
   if (!ccg.GetCC().GetDepfile().empty()) {
     // Add dependency over timestamp file for dependencies management
     auto dependTimestamp = cmSystemTools::ConvertToOutputPath(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetBinaryDirectory(),
+      this->LocalGenerator->MaybeRelativeToTopBinDir(
         cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts")));
 
     depends.push_back(dependTimestamp);
@@ -1743,11 +1720,8 @@ void cmMakefileTargetGenerator::WriteObjectsVariable(
     << this->GeneratorTarget->GetName() << "\n"
     << variableNameExternal << " =";
   /* clang-format on */
-  std::string currentBinDir =
-    this->LocalGenerator->GetCurrentBinaryDirectory();
   for (std::string const& obj : this->ExternalObjects) {
-    object =
-      this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, obj);
+    object = this->LocalGenerator->MaybeRelativeToCurBinDir(obj);
     *this->BuildFileStream << " " << lineContinue;
     *this->BuildFileStream
       << cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
@@ -1775,7 +1749,7 @@ public:
   {
     // Construct the name of the next object.
     this->NextObject = this->OutputConverter->ConvertToOutputFormat(
-      this->MaybeConvertToRelativePath(obj), cmOutputConverter::RESPONSE);
+      this->MaybeRelativeToCurBinDir(obj), cmOutputConverter::RESPONSE);
 
     // Roll over to next string if the limit will be exceeded.
     if (this->LengthLimit != std::string::npos &&
@@ -1796,13 +1770,13 @@ public:
   void Done() { this->Strings.push_back(this->CurrentString); }
 
 private:
-  std::string MaybeConvertToRelativePath(std::string const& obj)
+  std::string MaybeRelativeToCurBinDir(std::string const& path)
   {
-    if (!this->StateDir.ContainsBoth(this->StateDir.GetCurrentBinary(), obj)) {
-      return obj;
+    std::string const& base = this->StateDir.GetCurrentBinary();
+    if (!this->StateDir.ContainsBoth(base, path)) {
+      return path;
     }
-    return cmSystemTools::ForceToRelativePath(
-      this->StateDir.GetCurrentBinary(), obj);
+    return cmSystemTools::ForceToRelativePath(base, path);
   }
 
   std::vector<std::string>& Strings;
@@ -1847,8 +1821,8 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule(
     this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
   std::string buildTargetRuleName =
     cmStrCat(dir, relink ? "/preinstall" : "/build");
-  buildTargetRuleName = this->LocalGenerator->MaybeConvertToRelativePath(
-    this->LocalGenerator->GetBinaryDirectory(), buildTargetRuleName);
+  buildTargetRuleName =
+    this->LocalGenerator->MaybeRelativeToTopBinDir(buildTargetRuleName);
 
   // Build the list of target outputs to drive.
   std::vector<std::string> depends;
@@ -1985,13 +1959,12 @@ void cmMakefileTargetGenerator::CreateLinkScript(
   }
 
   // Create the makefile command to invoke the link script.
-  std::string link_command = cmStrCat(
-    "$(CMAKE_COMMAND) -E cmake_link_script ",
-    this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), linkScriptName),
-      cmOutputConverter::SHELL),
-    " --verbose=$(VERBOSE)");
+  std::string link_command =
+    cmStrCat("$(CMAKE_COMMAND) -E cmake_link_script ",
+             this->LocalGenerator->ConvertToOutputFormat(
+               this->LocalGenerator->MaybeRelativeToCurBinDir(linkScriptName),
+               cmOutputConverter::SHELL),
+             " --verbose=$(VERBOSE)");
   makefile_commands.push_back(std::move(link_command));
   makefile_depends.push_back(std::move(linkScriptName));
 }
@@ -2233,14 +2206,12 @@ void cmMakefileTargetGenerator::GenDefFile(
     this->LocalGenerator->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL),
     " -E __create_def ",
     this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), mdi->DefFile),
+      this->LocalGenerator->MaybeRelativeToCurBinDir(mdi->DefFile),
       cmOutputConverter::SHELL),
     ' ');
   std::string objlist_file = mdi->DefFile + ".objs";
   cmd += this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file),
+    this->LocalGenerator->MaybeRelativeToCurBinDir(objlist_file),
     cmOutputConverter::SHELL);
   cmProp nm_executable = this->Makefile->GetDefinition("CMAKE_NM");
   if (cmNonempty(nm_executable)) {

+ 2 - 4
Source/cmMakefileUtilityTargetGenerator.cxx

@@ -48,8 +48,7 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
     << "# Include any custom commands dependencies for this target.\n"
     << this->GlobalGenerator->IncludeDirective << " " << root
     << cmSystemTools::ConvertToOutputPath(
-         this->LocalGenerator->MaybeConvertToRelativePath(
-           this->LocalGenerator->GetBinaryDirectory(), dependFile))
+         this->LocalGenerator->MaybeRelativeToTopBinDir(dependFile))
     << "\n\n";
   if (!cmSystemTools::FileExists(dependFile)) {
     // Write an empty dependency file.
@@ -78,8 +77,7 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
       << "# Include the progress variables for this target.\n"
       << this->GlobalGenerator->IncludeDirective << " " << root
       << cmSystemTools::ConvertToOutputPath(
-           this->LocalGenerator->MaybeConvertToRelativePath(
-             this->LocalGenerator->GetBinaryDirectory(),
+           this->LocalGenerator->MaybeRelativeToTopBinDir(
              this->ProgressFileNameFull))
       << "\n\n";
   }

+ 7 - 1
Source/cmStateDirectory.cxx

@@ -44,6 +44,9 @@ void cmStateDirectory::ComputeRelativePathTopSource()
 
   std::string result = snapshots.front().GetDirectory().GetCurrentSource();
 
+  // Walk up the buildsystem directory tree to find the highest source
+  // directory that contains the current source directory and the
+  // intermediate ancestors.
   for (cmStateSnapshot const& snp : cmMakeRange(snapshots).advance(1)) {
     std::string currentSource = snp.GetDirectory().GetCurrentSource();
     if (cmSystemTools::IsSubDirectory(result, currentSource)) {
@@ -69,6 +72,9 @@ void cmStateDirectory::ComputeRelativePathTopBinary()
 
   std::string result = snapshots.front().GetDirectory().GetCurrentBinary();
 
+  // Walk up the buildsystem directory tree to find the highest binary
+  // directory that contains the current binary directory and the
+  // intermediate ancestors.
   for (cmStateSnapshot const& snp : cmMakeRange(snapshots).advance(1)) {
     std::string currentBinary = snp.GetDirectory().GetCurrentBinary();
     if (cmSystemTools::IsSubDirectory(result, currentBinary)) {
@@ -159,7 +165,7 @@ bool cmStateDirectory::ContainsBoth(std::string const& local_path,
   return bothInBinary || bothInSource;
 }
 
-std::string cmStateDirectory::ConvertToRelPathIfNotContained(
+std::string cmStateDirectory::ConvertToRelPathIfContained(
   std::string const& local_path, std::string const& remote_path) const
 {
   if (!this->ContainsBoth(local_path, remote_path)) {

+ 1 - 1
Source/cmStateDirectory.h

@@ -36,7 +36,7 @@ public:
   bool ContainsBoth(std::string const& local_path,
                     std::string const& remote_path) const;
 
-  std::string ConvertToRelPathIfNotContained(
+  std::string ConvertToRelPathIfContained(
     std::string const& local_path, std::string const& remote_path) const;
 
   cmStringRange GetIncludeDirectoriesEntries() const;

+ 1 - 1
Source/cmTarget.cxx

@@ -934,7 +934,7 @@ void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const
   for (auto const& cmd : this->impl->TLLCommands) {
     if (cmd.first == sig) {
       cmListFileContext lfc = cmd.second;
-      lfc.FilePath = cmDir.ConvertToRelPathIfNotContained(
+      lfc.FilePath = cmDir.ConvertToRelPathIfContained(
         this->impl->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath);
       s << " * " << lfc << '\n';
     }

+ 4 - 9
Source/cmTransformDepfile.cxx

@@ -40,10 +40,9 @@ void WriteDepfile(cmDepfileFormat format, cmsys::ofstream& fout,
                   const cmLocalGenerator& lg,
                   const cmGccDepfileContent& content)
 {
-  const auto& binDir = lg.GetBinaryDirectory();
   std::function<std::string(const std::string&)> formatPath =
-    [&lg, &binDir](const std::string& path) -> std::string {
-    return lg.MaybeConvertToRelativePath(binDir, path);
+    [&lg](const std::string& path) -> std::string {
+    return lg.MaybeRelativeToTopBinDir(path);
   };
   if (lg.GetGlobalGenerator()->GetName() == "Xcode") {
     // full paths must be preserved for Xcode compliance
@@ -93,8 +92,6 @@ std::string ConvertToTLogOutputPath(const std::string& path)
 void WriteVsTlog(cmsys::ofstream& fout, const cmLocalGenerator& lg,
                  const cmGccDepfileContent& content)
 {
-  const auto& binDir = lg.GetBinaryDirectory();
-
   for (auto const& dep : content) {
     fout << '^';
     bool first = true;
@@ -103,13 +100,11 @@ void WriteVsTlog(cmsys::ofstream& fout, const cmLocalGenerator& lg,
         fout << '|';
       }
       first = false;
-      fout << ConvertToTLogOutputPath(
-        lg.MaybeConvertToRelativePath(binDir, rule));
+      fout << ConvertToTLogOutputPath(lg.MaybeRelativeToTopBinDir(rule));
     }
     fout << "\r\n";
     for (auto const& path : dep.paths) {
-      fout << ConvertToTLogOutputPath(
-                lg.MaybeConvertToRelativePath(binDir, path))
+      fout << ConvertToTLogOutputPath(lg.MaybeRelativeToTopBinDir(path))
            << "\r\n";
     }
   }

+ 6 - 12
Source/cmVisualStudio10TargetGenerator.cxx

@@ -3356,8 +3356,6 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
     // cmLinkLineDeviceComputer
     cmComputeLinkInformation& cli = *pcli;
     std::vector<std::string> libVec;
-    const std::string currentBinDir =
-      this->LocalGenerator->GetCurrentBinaryDirectory();
     const auto& libs = cli.GetItems();
     for (cmComputeLinkInformation::Item const& l : libs) {
 
@@ -3394,8 +3392,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
       }
 
       if (l.IsPath) {
-        std::string path = this->LocalGenerator->MaybeConvertToRelativePath(
-          currentBinDir, l.Value.Value);
+        std::string path =
+          this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value);
         ConvertToWindowsSlash(path);
         if (!cmVS10IsTargetsFile(l.Value.Value)) {
           libVec.push_back(path);
@@ -3946,12 +3944,10 @@ bool cmVisualStudio10TargetGenerator::ComputeLibOptions(
   cmComputeLinkInformation& cli = *pcli;
   using ItemVector = cmComputeLinkInformation::ItemVector;
   const ItemVector& libs = cli.GetItems();
-  std::string currentBinDir =
-    this->LocalGenerator->GetCurrentBinaryDirectory();
   for (cmComputeLinkInformation::Item const& l : libs) {
     if (l.IsPath && cmVS10IsTargetsFile(l.Value.Value)) {
-      std::string path = this->LocalGenerator->MaybeConvertToRelativePath(
-        currentBinDir, l.Value.Value);
+      std::string path =
+        this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value);
       ConvertToWindowsSlash(path);
       this->AddTargetsFileAndConfigPair(path, config);
     }
@@ -3991,8 +3987,6 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
 {
   using ItemVector = cmComputeLinkInformation::ItemVector;
   ItemVector const& libs = cli.GetItems();
-  std::string currentBinDir =
-    this->LocalGenerator->GetCurrentBinaryDirectory();
   for (cmComputeLinkInformation::Item const& l : libs) {
     if (l.Target) {
       auto managedType = l.Target->GetManagedType(config);
@@ -4035,8 +4029,8 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
     }
 
     if (l.IsPath) {
-      std::string path = this->LocalGenerator->MaybeConvertToRelativePath(
-        currentBinDir, l.Value.Value);
+      std::string path =
+        this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value);
       ConvertToWindowsSlash(path);
       if (cmVS10IsTargetsFile(l.Value.Value)) {
         vsTargetVec.push_back(path);