Explorar el Código

ENH: add support for relative paths in makefiles

Bill Hoffman hace 22 años
padre
commit
eb9fc21543

+ 148 - 63
Source/cmLocalUnixMakefileGenerator.cxx

@@ -41,6 +41,40 @@ cmLocalUnixMakefileGenerator::~cmLocalUnixMakefileGenerator()
 
 void cmLocalUnixMakefileGenerator::Generate(bool fromTheTop)
 {
+  if(m_CurrentOutputDirectory.size() == 0)
+    {
+    m_CurrentOutputDirectory = m_Makefile->GetCurrentOutputDirectory();
+    m_HomeOutputDirectory =  m_Makefile->GetHomeOutputDirectory();
+    m_HomeDirectory = m_Makefile->GetHomeDirectory();
+#if defined(_WIN32) || defined(__APPLE__)
+    m_CurrentOutputDirectory = cmSystemTools::LowerCase(m_CurrentOutputDirectory);
+    m_HomeOutputDirectory = cmSystemTools::LowerCase(m_HomeOutputDirectory);
+    m_HomeDirectory = cmSystemTools::LowerCase(m_HomeDirectory);
+#endif
+    if(m_RelativePathToSourceDir.size() == 0)
+      {
+      m_RelativePathToSourceDir = cmSystemTools::RelativePath(
+        m_CurrentOutputDirectory.c_str(),
+        m_HomeDirectory.c_str());
+      std::string path = m_CurrentOutputDirectory;
+      cmSystemTools::ReplaceString(path, m_HomeOutputDirectory.c_str(), "");
+      unsigned i;
+      m_RelativePathToBinaryDir = "";
+      for(i =0; i < path.size(); ++i)
+        {
+        if(path[i] == '/')
+          {
+          m_RelativePathToBinaryDir += "../";
+          }
+        }
+      }
+    m_HomeOutputDirectoryNoSlash = m_HomeOutputDirectory;
+    m_HomeOutputDirectory += "/";
+    m_CurrentOutputDirectory += "/";
+    }
+  
+  
+  
   // suppoirt override in output directories
   if (m_Makefile->GetDefinition("LIBRARY_OUTPUT_PATH"))
     {
@@ -222,17 +256,18 @@ void cmLocalUnixMakefileGenerator::OutputMakefile(const char* file,
   for(std::vector<std::string>::const_iterator i = lfiles.begin();
       i !=  lfiles.end(); ++i)
     {
-    fout << " " << cmSystemTools::ConvertToOutputPath(i->c_str());
+    fout << " " << this->ConvertToMakefilePath(i->c_str());
     }
   // Add the cache to the list
   std::string cacheFile = m_Makefile->GetHomeOutputDirectory();
   cacheFile += "/CMakeCache.txt";
-  fout << " " << cmSystemTools::ConvertToOutputPath(cacheFile.c_str());
+  fout << " " << this->ConvertToMakefilePath(cacheFile.c_str());
   fout << "\n\n\n";
+  
   this->OutputMakeVariables(fout);  
   std::string checkCache = m_Makefile->GetHomeOutputDirectory();
   checkCache += "/cmake.check_cache";
-  checkCache = cmSystemTools::ConvertToOutputPath(checkCache.c_str());
+  checkCache = this->ConvertToMakefilePath(checkCache.c_str());
   // most unix makes will pass the command line flags to make down
   // to sub invoked makes via an environment variable.  However, some
   // makes do not support that, so you have to pass the flags explicitly
@@ -445,7 +480,7 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
       std::string path2 = m_LibraryOutputPath;
       path2 += this->GetFullTargetName(l->first.c_str(), l->second);
       path = "... ";
-      path += cmSystemTools::ConvertToOutputPath(path2.c_str());
+      path += this->ConvertToMakefilePath(path2.c_str());
       this->OutputEcho(fout,path.c_str());
       }
     }
@@ -490,7 +525,7 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
         path = m_LibraryOutputPath;
         path += this->GetFullTargetName(l->first.c_str(), l->second);
         fout << " \\\n" 
-             << cmSystemTools::ConvertToOutputPath(path.c_str());
+             << this->ConvertToMakefilePath(path.c_str());
         }
       }
     }
@@ -504,7 +539,7 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
       {
       path = m_ExecutableOutputPath;
       path += this->GetFullTargetName(l->first.c_str(), l->second);
-      fout << " \\\n" << cmSystemTools::ConvertToOutputPath(path.c_str());
+      fout << " \\\n" << this->ConvertToMakefilePath(path.c_str());
       }
     }
   // list utilities last
@@ -537,7 +572,7 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
           if(outExt.size())
             {
             fout << "\\\n" 
-                 << cmSystemTools::ConvertToOutputPath((*i)->GetSourceName().c_str())
+                 << this->ConvertToMakefilePath((*i)->GetSourceName().c_str())
                  << outExt.c_str() << " ";
             }
           }
@@ -553,7 +588,7 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
           std::string outExt(this->GetOutputExtension((*i)->GetSourceExtension().c_str()));
           if(outExt.size())
             {
-            fout << "\\\n\"" << cmSystemTools::ConvertToOutputPath((*i)->GetSourceName().c_str())
+            fout << "\\\n\"" << this->ConvertToMakefilePath((*i)->GetSourceName().c_str())
                  << outExt.c_str() << "\" ";
             }
           }
@@ -585,7 +620,7 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
           path = m_LibraryOutputPath;
           path += targetNameSO;
           fout << " \\\n"
-               << cmSystemTools::ConvertToOutputPath(path.c_str());
+               << this->ConvertToMakefilePath(path.c_str());
           }
         if(targetNameReal != targetName &&
            targetNameReal != targetNameSO)
@@ -593,7 +628,7 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
           path = m_LibraryOutputPath;
           path += targetNameReal;
           fout << " \\\n"
-               << cmSystemTools::ConvertToOutputPath(path.c_str());
+               << this->ConvertToMakefilePath(path.c_str());
           }
         }
       }
@@ -861,7 +896,7 @@ std::string cmLocalUnixMakefileGenerator::CreatePreBuildRules(
       {
       initNext = true;
       }
-    std::string command = cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str());
+    std::string command = this->ConvertToMakefilePath(cc.GetCommand().c_str());
     customRuleCode += command + " " + cc.GetArguments();
     }
   return customRuleCode;
@@ -886,7 +921,7 @@ std::string cmLocalUnixMakefileGenerator::CreatePreLinkRules(
       {
       initNext = true;
       }
-    std::string command = cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str());
+    std::string command = this->ConvertToMakefilePath(cc.GetCommand().c_str());
     customRuleCode += command + " " + cc.GetArguments();
     }
   return customRuleCode;
@@ -911,7 +946,7 @@ std::string cmLocalUnixMakefileGenerator::CreatePostBuildRules(
       {
       initNext = true;
       }
-    std::string command = cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str());
+    std::string command = this->ConvertToMakefilePath(cc.GetCommand().c_str());
     customRuleCode += command + " " + cc.GetArguments();
     }
   return customRuleCode;
@@ -1066,10 +1101,10 @@ void cmLocalUnixMakefileGenerator::OutputLibraryRule(std::ostream& fout,
   std::string targetFullPathSO = m_LibraryOutputPath + targetNameSO;
   std::string targetFullPathReal = m_LibraryOutputPath + targetNameReal;
   std::string targetFullPathBase = m_LibraryOutputPath + targetNameBase;
-  targetFullPath = cmSystemTools::ConvertToOutputPath(targetFullPath.c_str());
-  targetFullPathSO = cmSystemTools::ConvertToOutputPath(targetFullPathSO.c_str());
-  targetFullPathReal = cmSystemTools::ConvertToOutputPath(targetFullPathReal.c_str());
-  targetFullPathBase = cmSystemTools::ConvertToOutputPath(targetFullPathBase.c_str());
+  targetFullPath = this->ConvertToMakefilePath(targetFullPath.c_str());
+  targetFullPathSO = this->ConvertToMakefilePath(targetFullPathSO.c_str());
+  targetFullPathReal = this->ConvertToMakefilePath(targetFullPathReal.c_str());
+  targetFullPathBase = this->ConvertToMakefilePath(targetFullPathBase.c_str());
 
   // get the objects that are used to link this library
   std::string objs = "$(" + this->CreateMakeVariable(name, "_SRC_OBJS") + ") ";
@@ -1193,7 +1228,7 @@ void cmLocalUnixMakefileGenerator::OutputSharedLibraryRule(std::ostream& fout,
       if((*i)->GetSourceExtension() == "def")
         {
         linkFlags += this->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
-        linkFlags += cmSystemTools::ConvertToOutputPath((*i)->GetFullPath().c_str());
+        linkFlags += this->ConvertToMakefilePath((*i)->GetFullPath().c_str());
         linkFlags += " ";
         }
       }
@@ -1296,8 +1331,13 @@ void cmLocalUnixMakefileGenerator::OutputExecutableRule(std::ostream& fout,
       }
     }
   target += name;
-  target += cmSystemTools::GetExecutableExtension();
-  target = cmSystemTools::ConvertToOutputPath(target.c_str());
+  target += cmSystemTools::GetExecutableExtension();  
+  target = this->ConvertToMakefilePath(target.c_str());
+  bool needsLocalTarget = false;
+  if(target.find('/') != target.npos)
+    {
+    needsLocalTarget = true;
+    }
   
   std::string objs = "$(" + this->CreateMakeVariable(name, "_SRC_OBJS") + ") ";
   std::string depend = "$(";
@@ -1397,16 +1437,19 @@ void cmLocalUnixMakefileGenerator::OutputExecutableRule(std::ostream& fout,
   // If there is no executable output path, add a rule with the
   // relative path to the executable.  This is necessary for
   // try-compile to work in this case.
-  depend = target;
-  target = name;
-  target += cmSystemTools::GetExecutableExtension();
-  target = cmSystemTools::ConvertToOutputPath(target.c_str());
-  commands.resize(0);
-  this->OutputMakeRule(fout, 
-                       comment.c_str(),
-                       target.c_str(),
-                       depend.c_str(),
-                       commands);
+  if(needsLocalTarget)
+    {
+    depend = target;
+    target = name;
+    target += cmSystemTools::GetExecutableExtension();
+    target = this->ConvertToMakefilePath(target.c_str());
+    commands.resize(0);
+    this->OutputMakeRule(fout, 
+                         comment.c_str(),
+                         target.c_str(),
+                         depend.c_str(),
+                         commands);
+    }
 }
 
 
@@ -1446,7 +1489,7 @@ void cmLocalUnixMakefileGenerator::OutputUtilityRule(std::ostream& fout,
       depends +=  " \\\n";
       replaceVars = *d;
       m_Makefile->ExpandVariablesInString(replaceVars);
-      depends += cmSystemTools::ConvertToOutputPath(replaceVars.c_str());
+      depends += this->ConvertToMakefilePath(replaceVars.c_str());
       }
     }
   this->OutputMakeRule(fout, comment.c_str(), name,
@@ -1662,10 +1705,13 @@ void cmLocalUnixMakefileGenerator::OutputBuildTargetInDirWindows(std::ostream& f
                                                                  const char* libOutPath)
 {
   const char* makeTarget = library;
-  std::string currentDir = 
-    cmSystemTools::ConvertToOutputPath(m_Makefile->GetCurrentOutputDirectory());
+  std::string jumpBack = 
+    cmSystemTools::RelativePath(cmSystemTools::GetProgramPath(fullpath).c_str(),
+                                m_Makefile->GetCurrentOutputDirectory());
+  jumpBack = this->ConvertToOutputForExisting(jumpBack.c_str());
   std::string wpath = this->ConvertToOutputForExisting(path);
   std::string wfullpath = this->ConvertToOutputForExisting(fullpath);
+
   if(libOutPath && strcmp( libOutPath, "" ) != 0)
     {
     makeTarget = wfullpath.c_str();
@@ -1676,7 +1722,7 @@ void cmLocalUnixMakefileGenerator::OutputBuildTargetInDirWindows(std::ostream& f
        << "\t$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) cmake.check_depends\n"
        << "\t$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) -f cmake.check_depends\n"
        << "\t$(MAKE) $(MAKESILENT) " << makeTarget
-       << "\n\tcd " << currentDir << "\n";
+       << "\n\tcd " << jumpBack << "\n";
 }
 
 void cmLocalUnixMakefileGenerator::OutputBuildTargetInDir(std::ostream& fout,
@@ -1701,7 +1747,7 @@ void cmLocalUnixMakefileGenerator::OutputBuildTargetInDir(std::ostream& fout,
        << "; $(MAKE) $(MAKESILENT) cmake.check_depends"
        << "; $(MAKE) $(MAKESILENT) -f cmake.check_depends"
        << "; $(MAKE) $(MAKESILENT) "
-       << cmSystemTools::ConvertToOutputPath(makeTarget) << "\n\n"; 
+       << this->ConvertToMakefilePath(makeTarget) << "\n\n"; 
 }
 
 
@@ -1772,7 +1818,7 @@ void cmLocalUnixMakefileGenerator::OutputLibDepend(std::ostream& fout,
       libpath += name;
       libpath += this->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX");
       }
-    fout << cmSystemTools::ConvertToOutputPath(libpath.c_str()) << " ";
+    fout << this->ConvertToMakefilePath(libpath.c_str()) << " ";
     }
 }
 
@@ -1811,7 +1857,7 @@ void cmLocalUnixMakefileGenerator::OutputExeDepend(std::ostream& fout,
     exepath += name;
     // add the correct extension
     exepath += cmSystemTools::GetExecutableExtension();
-    fout << cmSystemTools::ConvertToOutputPath(exepath.c_str()) << " ";
+    fout << this->ConvertToMakefilePath(exepath.c_str()) << " ";
     }
   // if it isn't in the cache, it might still be a utility target
   // so check for that
@@ -1857,9 +1903,10 @@ BuildInSubDirectoryWindows(std::ostream& fout,
                            const char* target2,
                            bool silent)
 {
+  std::string dir;
   if(target1)
     {
-    std::string dir = this->ConvertToOutputForExisting(directory);
+    dir = this->ConvertToOutputForExisting(directory);
     if(dir[0] == '\"')
       {
       dir = dir.substr(1, dir.size()-2);
@@ -1881,9 +1928,19 @@ BuildInSubDirectoryWindows(std::ostream& fout,
       fout << "\t@echo " << directory << ": building " << target2 << "\n";
       }
     fout << "\t$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) " << target2 << "\n";
+    } 
+  std::string currentDir = dir;
+  cmSystemTools::ConvertToUnixSlashes(currentDir);
+  std::string cdback = "..";
+  for(unsigned int i =0; i < currentDir.size(); ++i)
+    {
+    if(currentDir[i] == '/')
+      {
+      cdback += "/..";
+      }
     }
-  std::string currentDir = m_Makefile->GetCurrentOutputDirectory();
-  fout << "\tcd " << this->ConvertToOutputForExisting(currentDir.c_str()) << "\n\n";
+  fout << "\tcd " << this->ConvertToOutputForExisting(cdback.c_str()) << "\n\n";
+  
 }
 
 
@@ -1899,7 +1956,7 @@ void cmLocalUnixMakefileGenerator::BuildInSubDirectory(std::ostream& fout,
     return;
     }
   
-  std::string directory = cmSystemTools::ConvertToOutputPath(dir);
+  std::string directory = this->ConvertToMakefilePath(dir);
   if(target1)
     {
     fout << "\t@if test ! -d " << directory 
@@ -2046,8 +2103,8 @@ bool cmLocalUnixMakefileGenerator::OutputObjectDepends(std::ostream& fout)
             {
             std::string s = (*source)->GetSourceName();
             s += this->GetOutputExtension((*source)->GetSourceExtension().c_str());
-            fout << cmSystemTools::ConvertToOutputPath(s.c_str()) << " : "
-                 << cmSystemTools::ConvertToOutputPath(dep->c_str()) << "\n";
+            fout << this->ConvertToMakefilePath(s.c_str()) << " : "
+                 << this->ConvertToMakefilePath(dep->c_str()) << "\n";
             ret = true;
             }
           fout << "\n\n";
@@ -2098,7 +2155,7 @@ void cmLocalUnixMakefileGenerator::OutputCheckDepends(std::ostream& fout)
             // has been done because m_FullPath on cmDependInformation
             // always is it called.  If it is called here, network builds are
             // very slow because of the number of stats
-            std::string dependfile = cmSystemTools::ConvertToOutputPath(dep->c_str());
+            std::string dependfile = this->ConvertToMakefilePath(dep->c_str());
             // use the lower path function to create uniqe names
             std::string lowerpath = this->LowerCasePath(dependfile.c_str());
             if(emittedLowerPath.insert(lowerpath).second)
@@ -2152,7 +2209,7 @@ void cmLocalUnixMakefileGenerator::OutputCustomRules(std::ostream& fout)
       std::string comment = c->GetComment();
       std::string command = c->GetCommand();
       cmSystemTools::ReplaceString(command, "/./", "/");
-      command = cmSystemTools::ConvertToOutputPath(command.c_str());
+      command = this->ConvertToMakefilePath(command.c_str());
       command += " ";
       // now add the arguments
       command += c->GetArguments();
@@ -2183,7 +2240,7 @@ void cmLocalUnixMakefileGenerator::OutputCustomRules(std::ostream& fout)
           }
         cmSystemTools::ReplaceString(dep, "/./", "/");
         cmSystemTools::ReplaceString(dep, "/$(IntDir)/", "/");
-        dep = cmSystemTools::ConvertToOutputPath(dep.c_str());
+        dep = this->ConvertToMakefilePath(dep.c_str());
         depends += " ";
         depends += dep;
         } 
@@ -2209,7 +2266,7 @@ void cmLocalUnixMakefileGenerator::OutputCustomRules(std::ostream& fout)
 std::string 
 cmLocalUnixMakefileGenerator::ConvertToOutputForExisting(const char* p)
 {
-  std::string ret = cmSystemTools::ConvertToOutputPath(p);
+  std::string ret = this->ConvertToMakefilePath(p);
   // if there are spaces in the path, then get the short path version
   // if there is one
   if(ret.find(' ') != std::string::npos)
@@ -2218,7 +2275,7 @@ cmLocalUnixMakefileGenerator::ConvertToOutputForExisting(const char* p)
       {
       if(!cmSystemTools::GetShortPath(ret.c_str(), ret))
         {
-        ret = cmSystemTools::ConvertToOutputPath(p);
+        ret = this->ConvertToMakefilePath(p);
         }
       }
     }
@@ -2265,16 +2322,16 @@ void cmLocalUnixMakefileGenerator::OutputMakeVariables(std::ostream& fout)
     }
 
   fout << "CMAKE_CURRENT_SOURCE = " << 
-    cmSystemTools::ConvertToOutputPath(m_Makefile->GetStartDirectory()) 
+    this->ConvertToMakefilePath(m_Makefile->GetStartDirectory()) 
        << "\n";
   fout << "CMAKE_CURRENT_BINARY = " << 
-    cmSystemTools::ConvertToOutputPath(m_Makefile->GetStartOutputDirectory())
+    this->ConvertToMakefilePath(m_Makefile->GetStartOutputDirectory())
        << "\n";
   fout << "CMAKE_SOURCE_DIR = " << 
-    cmSystemTools::ConvertToOutputPath(m_Makefile->GetHomeDirectory())
+    this->ConvertToMakefilePath(m_Makefile->GetHomeDirectory())
        << "\n";
   fout << "CMAKE_BINARY_DIR = " << 
-    cmSystemTools::ConvertToOutputPath(m_Makefile->GetHomeOutputDirectory())
+    this->ConvertToMakefilePath(m_Makefile->GetHomeOutputDirectory())
        << "\n";
   // Output Include paths
   fout << "INCLUDE_FLAGS = ";
@@ -2367,7 +2424,7 @@ void cmLocalUnixMakefileGenerator::OutputInstallRules(std::ostream& fout)
           installNameReal += targetNameReal;
           fname = m_LibraryOutputPath;
           fname += targetNameReal;
-          fout << "\t$(INSTALL_DATA) " << cmSystemTools::ConvertToOutputPath(fname.c_str())
+          fout << "\t$(INSTALL_DATA) " << this->ConvertToMakefilePath(fname.c_str())
                << " \"$(DESTDIR)" << prefix << l->second.GetInstallPath() << "\"\n";
           fout << "\t" << cmakecommand << " -E cmake_symlink_library \""
                << installNameReal << "\" \"" << installNameSO << "\" \"" << installName
@@ -2377,7 +2434,7 @@ void cmLocalUnixMakefileGenerator::OutputInstallRules(std::ostream& fout)
         case cmTarget::EXECUTABLE:
           fname = m_ExecutableOutputPath;
           fname += this->GetFullTargetName(l->first.c_str(), l->second);
-          fout << "\t$(INSTALL_PROGRAM) " << cmSystemTools::ConvertToOutputPath(fname.c_str())
+          fout << "\t$(INSTALL_PROGRAM) " << this->ConvertToMakefilePath(fname.c_str())
                << " \"$(DESTDIR)" << prefix << l->second.GetInstallPath() << "\"\n";
           break;
         case cmTarget::INSTALL_FILES:
@@ -2411,7 +2468,7 @@ void cmLocalUnixMakefileGenerator::OutputInstallRules(std::ostream& fout)
               fout << "\t$(INSTALL_DATA) ";
               }
             
-            fout << cmSystemTools::ConvertToOutputPath(i->c_str())
+            fout << this->ConvertToMakefilePath(i->c_str())
                  << " \"$(DESTDIR)" << prefix << l->second.GetInstallPath() << "\"\n";
             }
           }
@@ -2446,7 +2503,7 @@ void cmLocalUnixMakefileGenerator::OutputInstallRules(std::ostream& fout)
               {
               fout << "\t   @$(INSTALL_PROGRAM) ";
               }
-            fout << cmSystemTools::ConvertToOutputPath(i->c_str())
+            fout << this->ConvertToMakefilePath(i->c_str())
                  << " \"$(DESTDIR)" << prefix << l->second.GetInstallPath() << "\"\n";
             }
           }
@@ -2486,14 +2543,14 @@ void cmLocalUnixMakefileGenerator::OutputMakeRules(std::ostream& fout)
       {
       if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY"))
         {
-          allsources.push_back(cmSystemTools::ConvertToOutputPath((*source)->GetFullPath().c_str()));
+          allsources.push_back(this->ConvertToMakefilePath((*source)->GetFullPath().c_str()));
         }
       }
     }
 
   std::string checkCache = m_Makefile->GetHomeOutputDirectory();
   checkCache += "/cmake.check_cache";
-  checkCache = cmSystemTools::ConvertToOutputPath(checkCache.c_str());
+  checkCache = this->ConvertToMakefilePath(checkCache.c_str());
   std::vector<std::string> cmake_depends;
   cmake_depends.push_back(checkCache);
   cmake_depends.push_back("$(CMAKE_MAKEFILE_SOURCES)");
@@ -2538,7 +2595,7 @@ void cmLocalUnixMakefileGenerator::OutputMakeRules(std::ostream& fout)
   std::vector<std::string> check_cache_depends;
   std::string CMakeCache = m_Makefile->GetHomeOutputDirectory();
   CMakeCache += "/CMakeCache.txt";
-  CMakeCache = cmSystemTools::ConvertToOutputPath(CMakeCache.c_str());
+  CMakeCache = this->ConvertToMakefilePath(CMakeCache.c_str());
   check_cache_depends.push_back(CMakeCache);
   check_cache_depends.push_back("$(CMAKE_MAKEFILE_SOURCES)");
 
@@ -2643,7 +2700,7 @@ OutputBuildObjectFromSource(std::ostream& fout,
   std::string comment = "object file";
   std::string objectFile = std::string(shortName) + 
     this->GetOutputExtension(source.GetSourceExtension().c_str());
-  objectFile = cmSystemTools::ConvertToOutputPath(objectFile.c_str());
+  objectFile = this->ConvertToMakefilePath(objectFile.c_str());
   cmSystemTools::FileFormat format = 
     cmSystemTools::GetFileFormat(source.GetSourceExtension().c_str());
   std::vector<std::string> rules;
@@ -2653,7 +2710,7 @@ OutputBuildObjectFromSource(std::ostream& fout,
     flags += extraCompileFlags;
     }
   std::string sourceFile = 
-    cmSystemTools::ConvertToOutputPath(source.GetFullPath().c_str()); 
+    this->ConvertToMakefilePath(source.GetFullPath().c_str()); 
   std::string buildType =  this->GetSafeDefinition("CMAKE_BUILD_TYPE");
   buildType = cmSystemTools::UpperCase(buildType);
   switch(format)
@@ -2761,7 +2818,7 @@ OutputBuildObjectFromSource(std::ostream& fout,
     for(std::vector<std::string>::iterator i = depends.begin();
         i != depends.end(); ++i)
       {
-      sourceAndDeps.push_back(cmSystemTools::ConvertToOutputPath(i->c_str()));
+      sourceAndDeps.push_back(this->ConvertToMakefilePath(i->c_str()));
       }
     }
   
@@ -2957,7 +3014,7 @@ void cmLocalUnixMakefileGenerator::OutputMakeRule(std::ostream& fout,
   replace = target;
   m_Makefile->ExpandVariablesInString(replace);
   
-  std::string tgt = cmSystemTools::ConvertToOutputPath(replace.c_str());
+  std::string tgt = this->ConvertToMakefilePath(replace.c_str());
   if(depends.empty())
     {
     fout << tgt.c_str() << ":\n";
@@ -3156,3 +3213,31 @@ void cmLocalUnixMakefileGenerator::GetLibraryNames(const char* n,
   // The library name without extension.
   baseName = this->GetBaseTargetName(n, t);
 }
+
+std::string cmLocalUnixMakefileGenerator::ConvertToMakefilePath(const char* p)
+{
+  std::string pathIn = p;
+#if defined(_WIN32) || defined(__APPLE__)
+  pathIn = cmSystemTools::LowerCase(pathIn);
+#endif
+
+  std::string ret = pathIn;
+  cmSystemTools::ReplaceString(ret, m_CurrentOutputDirectory.c_str(), "");
+  cmSystemTools::ReplaceString(ret, m_HomeDirectory.c_str(),
+                               m_RelativePathToSourceDir.c_str());
+  cmSystemTools::ReplaceString(ret, m_HomeOutputDirectory.c_str(),
+                               m_RelativePathToBinaryDir.c_str());
+  std::string relpath = m_RelativePathToBinaryDir;
+  if(relpath.size())
+    {
+    relpath.erase(relpath.size()-1, 1);
+    }
+  else
+    {
+    relpath = ".";
+    }
+  cmSystemTools::ReplaceString(ret, m_HomeOutputDirectoryNoSlash.c_str(),
+                               relpath.c_str());
+  ret = cmSystemTools::ConvertToOutputPath(ret.c_str());
+  return ret;
+}

+ 9 - 1
Source/cmLocalUnixMakefileGenerator.h

@@ -231,7 +231,9 @@ protected:
 
   /** Output an echo command to the Makefile */
   void OutputEcho(std::ostream& fout, const char *msg);
-    
+
+  ///! final processing for a path to be put in a makefile
+  std::string ConvertToMakefilePath(const char* p);
 protected:
   int m_MakefileVariableSize;
   std::map<cmStdString, cmStdString> m_MakeVariableMap;
@@ -241,6 +243,12 @@ protected:
   std::string m_MakeSilentFlag;
   std::string m_ExecutableOutputPath;
   std::string m_LibraryOutputPath;
+  std::string m_RelativePathToSourceDir;
+  std::string m_RelativePathToBinaryDir;
+  std::string m_CurrentOutputDirectory;
+  std::string m_HomeOutputDirectory;
+  std::string m_HomeDirectory;
+  std::string m_HomeOutputDirectoryNoSlash;
   bool m_WindowsShell;
   bool m_PassMakeflags;
 private:

+ 64 - 0
Source/cmSystemTools.cxx

@@ -438,6 +438,7 @@ bool cmSystemTools::RunSingleCommand(
     }
   else
     {
+    std::cerr << cmsysProcess_GetErrorString(cp) << "\n";
     result = false;
     }
   
@@ -1063,3 +1064,66 @@ bool cmSystemTools::CreateSymlink(const char* origName, const char* newName)
   return (symlink(origName, newName) >= 0);
 }
 #endif
+
+
+std::vector<std::string> cmSystemTools::SplitString(const char* p, char sep)
+{
+  std::string path = p;
+  std::vector<std::string> paths;
+  std::string::size_type pos1 = 0;
+  std::string::size_type pos2 = path.find(sep, pos1+1);
+  while(pos2 != std::string::npos)
+    {
+    paths.push_back(path.substr(pos1+1, pos2-pos1-1));
+    pos1 = pos2;
+    pos2 = path.find(sep, pos1+1);
+    } 
+  paths.push_back(path.substr(pos1+1, pos2-pos1-1));
+  
+  return paths;
+}
+
+
+// compute the relative path from here to there
+std::string cmSystemTools::RelativePath(const char* local, const char* remote)
+{
+#ifdef _WIN32
+  std::string lowerCaseLocal = cmSystemTools::LowerCase(std::string(local));
+  std::string lowerCaseRemote = cmSystemTools::LowerCase(std::string(remote));
+  remote = lowerCaseRemote.c_str();
+  local = lowerCaseLocal.c_str();
+#endif
+  // check for driveletter: as the start of the path
+  // if not on the same drive then full path to remote must be used.
+  if(local[0] && local[0] != '/')
+    {
+    if(remote[0] && local[0] != remote[0])
+      {
+      return remote;
+      }
+    }
+  std::string relativePath;     // result string
+  // split up both paths into arrays of strings using / as a separator
+  std::vector<std::string> fileSplit = cmSystemTools::SplitString(local);
+  std::vector<std::string> relativeSplit = cmSystemTools::SplitString(remote);
+  // count up how many mathing directory names there are from the start
+  int sameCount = 0;
+  while(sameCount < fileSplit.size()-1 && sameCount < relativeSplit.size()-1 && 
+        fileSplit[sameCount] == relativeSplit[sameCount])
+    {
+    sameCount++;
+    }
+  // put in sameCount number of ../ into the path
+  int i;
+  for(i = sameCount; i < fileSplit.size(); ++i)
+    {
+    relativePath += "../";
+    }
+  // now put the rest of path that did not match back
+  for(i = sameCount; i < relativeSplit.size()-1; ++i)
+    {
+    relativePath += relativeSplit[i] + "/";
+    }
+  relativePath += relativeSplit[i];
+  return relativePath;
+}

+ 5 - 0
Source/cmSystemTools.h

@@ -245,6 +245,11 @@ public:
   static bool StringEndsWith(const char* str1, const char* str2);
 
   static bool CreateSymlink(const char* origName, const char* newName);
+  
+  ///! compute the relative path from local to remote
+  static std::string RelativePath(const char* local, const char* remote);
+  ///! split a path by separator into an array of strings, default is /
+  static std::vector<std::string> SplitString(const char* s, char separator = '/');
 private:
   static bool s_ForceUnixPaths;
   static bool s_RunCommandHideConsole;

+ 8 - 0
Source/cmake.cxx

@@ -275,6 +275,8 @@ void cmake::SetArgs(const std::vector<std::string>& args)
       {
       directoriesSet = true;
       std::string path = arg.substr(2);
+      path = cmSystemTools::CollapseFullPath(path.c_str());
+      cmSystemTools::ConvertToUnixSlashes(path);
       this->SetHomeDirectory(path.c_str());
       }
     else if(arg.find("-S",0) == 0)
@@ -282,18 +284,24 @@ void cmake::SetArgs(const std::vector<std::string>& args)
       directoriesSet = true;
       m_Local = true;
       std::string path = arg.substr(2);
+      path = cmSystemTools::CollapseFullPath(path.c_str());
+      cmSystemTools::ConvertToUnixSlashes(path);
       this->SetStartDirectory(path.c_str());
       }
     else if(arg.find("-O",0) == 0)
       {
       directoriesSet = true;
       std::string path = arg.substr(2);
+      path = cmSystemTools::CollapseFullPath(path.c_str());
+      cmSystemTools::ConvertToUnixSlashes(path);
       this->SetStartOutputDirectory(path.c_str());
       }
     else if(arg.find("-B",0) == 0)
       {
       directoriesSet = true;
       std::string path = arg.substr(2);
+      path = cmSystemTools::CollapseFullPath(path.c_str());
+      cmSystemTools::ConvertToUnixSlashes(path);
       this->SetHomeOutputDirectory(path.c_str());
       }
     else if(arg.find("-V",0) == 0)