Переглянути джерело

ENH: Add an invocation that maintains symbolic paths to the source and binary trees, mainly for systems with automounted network drives.
ENH: CollapseFullPath() no longer adds a trailing "/" to directory paths.

Amitha Perera 24 роки тому
батько
коміт
2fa6a0eb44
4 змінених файлів з 121 додано та 47 видалено
  1. 31 3
      Source/cmSystemTools.cxx
  2. 13 0
      Source/cmSystemTools.h
  3. 76 44
      Source/cmake.cxx
  4. 1 0
      Source/cmake.h

+ 31 - 3
Source/cmSystemTools.cxx

@@ -94,6 +94,7 @@ inline int Chdir(const char* dir)
 bool cmSystemTools::s_DisableRunCommandOutput = false;
 bool cmSystemTools::s_ErrorOccured = false;
 bool cmSystemTools::s_DisableMessages = false;
+cmSystemTools::PathMap cmSystemTools::s_PathMap;
 
 void (*cmSystemTools::s_ErrorCallback)(const char*, const char*, bool&);
 
@@ -1176,6 +1177,7 @@ std::string cmSystemTools::GetCurrentWorkingDirectory()
 {
   char buf[2048];
   std::string path = Getcwd(buf, 2048);
+  ApplyPathTranslation( path );
   return path;
 }
 
@@ -1237,6 +1239,7 @@ void cmSystemTools::SplitProgramPath(const char* in_name,
 std::string cmSystemTools::CollapseFullPath(const char* in_name)
 {
   std::string dir, file;
+  std::string return_value;
   cmSystemTools::SplitProgramPath(in_name, dir, file);
 #ifdef _WIN32
   // Ultra-hack warning:
@@ -1248,8 +1251,7 @@ std::string cmSystemTools::CollapseFullPath(const char* in_name)
   Chdir(cwd.c_str());
 
   cmSystemTools::ConvertToUnixSlashes(newDir);
-  std::string newPath = newDir+"/"+file;
-  return newPath;
+  return_value = newDir;
 #else
 # ifdef MAXPATHLEN
   char resolved_name[MAXPATHLEN];
@@ -1269,8 +1271,13 @@ std::string cmSystemTools::CollapseFullPath(const char* in_name)
     {
     dir = cmSystemTools::GetCurrentWorkingDirectory();
     }
-  return dir + "/" + file;
+  return_value = dir;
 #endif
+  if(file != "")
+    return_value += "/" + file;
+
+  ApplyPathTranslation( return_value );
+  return return_value;
 }
 
 /**
@@ -1424,3 +1431,24 @@ void cmSystemTools::GlobDirs(const char *fullPath,
       }
     }
 }
+
+
+void cmSystemTools::AddPathTranslation( const std::string& from, const std::string& to )
+{
+  s_PathMap[from] = to;
+}
+
+void cmSystemTools::ApplyPathTranslation( std::string& path )
+{
+  PathMap::iterator i;
+
+  // For each key in the map, see if path starts with it. If so, perform the substitution.
+  for( i = s_PathMap.begin(); i != s_PathMap.end(); ++i )
+    {
+    if( path.substr( 0, i->first.length() ) == i->first )
+      {
+      path.replace( 0, i->first.length(), i->second );
+      return;
+      }
+    }
+}

+ 13 - 0
Source/cmSystemTools.h

@@ -254,6 +254,16 @@ public:
                                std::string& file);
   static std::string CollapseFullPath(const char*);
 
+  /**
+   * all file path prefixes matching \arg from will be replaced by
+   * \arg to.  Affects the return value of CollapseFullPath and
+   * GetCurrentWorkingDirectory.
+   */
+  static void AddPathTranslation( const std::string& from, const std::string& to );
+
+  ///! Apply the current path translations to \arg path.
+  static void ApplyPathTranslation( std::string& path );
+
   ///! return path of a full filename (no trailing slashes).
   static std::string GetFilenamePath(const std::string&);
   
@@ -295,6 +305,9 @@ private:
   static bool s_DisableMessages;
   static bool s_DisableRunCommandOutput;
   static ErrorCallback s_ErrorCallback;
+
+  typedef std::map<cmStdString, cmStdString> PathMap;
+  static PathMap s_PathMap;
 };
 
 

+ 76 - 44
Source/cmake.cxx

@@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 cmake::cmake()
 {
   m_Verbose = false;
+  m_UsePathTranslation = false;
 #if defined(_WIN32) && !defined(__CYGWIN__)  
   cmMakefileGenerator::RegisterGenerator(new cmMSProjectGenerator);
   cmMakefileGenerator::RegisterGenerator(new cmNMakeMakefileGenerator);
@@ -67,8 +68,9 @@ void cmake::Usage(const char* program)
   std::cerr << "cmake version " << cmMakefile::GetMajorVersion()
             << "." << cmMakefile::GetMinorVersion() << " - " 
             << cmMakefile::GetReleaseVersion() << "\n";
-  std::cerr << "Usage: " << program << " [srcdir] [options]\n" 
+  std::cerr << "Usage: " << program << " [srcdir] [outdir] [options]\n" 
             << "Where cmake is run from the directory where you want the object files written.  If srcdir is not specified, the current directory is used for both source and object files.\n";
+  std::cerr << "If outdir is specified, pathname translation is enabled, and srcdir and outdir are used as given to access the roots of source and output directories.\n";
   std::cerr << "Options are:\n";
   std::cerr << "\n-i (puts cmake in wizard mode, not available for ccmake)\n";
   std::cerr << "\n-DVAR:TYPE=VALUE (create a cache file entry)\n";
@@ -128,29 +130,9 @@ void cmake::SetArgs(cmMakefile& builder, const std::vector<std::string>& args)
 {
   m_Local = false;
   bool directoriesSet = false;
-  // watch for cmake and cmake srcdir invocations
-  if (args.size() <= 2)
-    {
-    directoriesSet = true;
-    builder.SetHomeOutputDirectory
-      (cmSystemTools::GetCurrentWorkingDirectory().c_str());
-    builder.SetStartOutputDirectory
-      (cmSystemTools::GetCurrentWorkingDirectory().c_str());
-    if (args.size() == 2)
-      {
-      builder.SetHomeDirectory
-	(cmSystemTools::CollapseFullPath(args[1].c_str()).c_str());
-      builder.SetStartDirectory
-	(cmSystemTools::CollapseFullPath(args[1].c_str()).c_str());
-      }
-    else
-      {
-      builder.SetHomeDirectory
-	(cmSystemTools::GetCurrentWorkingDirectory().c_str());
-      builder.SetStartDirectory
-	(cmSystemTools::GetCurrentWorkingDirectory().c_str());
-      }
-    }
+
+  std::string srcdir;
+  std::string outdir;
 
   for(unsigned int i=1; i < args.size(); ++i)
     {
@@ -159,6 +141,12 @@ void cmake::SetArgs(cmMakefile& builder, const std::vector<std::string>& args)
       {
       directoriesSet = true;
       std::string path = arg.substr(2);
+      if( cmSystemTools::CollapseFullPath(path.c_str()) != path &&
+          path.size() > 0 && path[0] != '.' )
+        {
+        cmSystemTools::AddPathTranslation( cmSystemTools::CollapseFullPath(path.c_str()), path );
+        m_UsePathTranslation = true;
+        }
       builder.SetHomeDirectory(path.c_str());
       }
     else if(arg.find("-S",0) == 0)
@@ -178,6 +166,12 @@ void cmake::SetArgs(cmMakefile& builder, const std::vector<std::string>& args)
       {
       directoriesSet = true;
       std::string path = arg.substr(2);
+      if( cmSystemTools::CollapseFullPath(path.c_str()) != path &&
+          path.size() > 0 && path[0] != '.' )
+        {
+        cmSystemTools::AddPathTranslation( cmSystemTools::CollapseFullPath(path.c_str()), path );
+        m_UsePathTranslation = true;
+        }
       builder.SetHomeOutputDirectory(path.c_str());
       }
     else if(arg.find("-V",0) == 0)
@@ -207,31 +201,66 @@ void cmake::SetArgs(cmMakefile& builder, const std::vector<std::string>& args)
         builder.SetMakefileGenerator(gen);
         }
       }
-    // no option assume it is the path to the source
+    // no option assume it is the path to the source or to the output
     else
       {
-      directoriesSet = true;
-      builder.SetHomeOutputDirectory
-        (cmSystemTools::GetCurrentWorkingDirectory().c_str());
-      builder.SetStartOutputDirectory
-        (cmSystemTools::GetCurrentWorkingDirectory().c_str());
-      builder.SetHomeDirectory
-        (cmSystemTools::CollapseFullPath(arg.c_str()).c_str());
-      builder.SetStartDirectory
-        (cmSystemTools::CollapseFullPath(arg.c_str()).c_str());
+      if( srcdir.size() == 0 )
+        {
+        srcdir = arg;
+        }
+      else if( outdir.size() == 0 )
+        {
+        // Make sure the symbolic output directory specified matches
+        // the current directory, and that the symbolic path is
+        // absolute. Even if not, set the outdir variable so that
+        // further attempts to set the output directory (with
+        // another command line argument) fails.
+        if( cmSystemTools::CollapseFullPath( arg.c_str() ) == cmSystemTools::GetCurrentWorkingDirectory() )
+          {
+          outdir = arg;
+          if( srcdir.size() > 0 && srcdir[0] != '.' && outdir.size() > 0 && outdir[0] != '.' )
+            {
+            cmSystemTools::AddPathTranslation( cmSystemTools::GetCurrentWorkingDirectory(), outdir );
+            cmSystemTools::AddPathTranslation( cmSystemTools::CollapseFullPath(srcdir.c_str()), srcdir );
+            m_UsePathTranslation = true;
+            }
+          else
+            {
+            std::cerr << "Symbolic paths must be absolute for path translation. One of \"" << srcdir
+                      << "\" or \"" << outdir << "\" is not.\n"
+                      << "Not performing path name translation." << std::endl;
+            outdir = cmSystemTools::GetCurrentWorkingDirectory();
+            }
+          }
+        else
+          {
+          std::cerr << "The current working directory (" << cmSystemTools::GetCurrentWorkingDirectory() << ")\n"
+                    << "does not match the binary directory (" << (cmSystemTools::CollapseFullPath(arg.c_str())) << ")\n"
+                    << "[ given as " << arg << " ].\n"
+                    << "Not performing path name translation." << std::endl;
+          outdir = cmSystemTools::GetCurrentWorkingDirectory();
+          }
+        }
+      else
+        {
+        std::cerr << "Ignoring parameter " << arg << std::endl;
+        }
       }
     }
+
   if(!directoriesSet)
     {
-    builder.SetHomeOutputDirectory
-      (cmSystemTools::GetCurrentWorkingDirectory().c_str());
-    builder.SetStartOutputDirectory
-      (cmSystemTools::GetCurrentWorkingDirectory().c_str());
-    builder.SetHomeDirectory
-      (cmSystemTools::GetCurrentWorkingDirectory().c_str());
-    builder.SetStartDirectory
-      (cmSystemTools::GetCurrentWorkingDirectory().c_str());
+    if( srcdir.size() == 0 )  srcdir = cmSystemTools::GetCurrentWorkingDirectory();
+
+    outdir = cmSystemTools::GetCurrentWorkingDirectory();
+    srcdir = cmSystemTools::CollapseFullPath( srcdir.c_str() );
+
+    builder.SetHomeOutputDirectory( outdir.c_str() );
+    builder.SetStartOutputDirectory( outdir.c_str() );
+    builder.SetHomeDirectory( srcdir.c_str() );
+    builder.SetStartDirectory( srcdir.c_str() );
     }
+
   if (!m_Local)
     {
     builder.SetStartDirectory(builder.GetHomeDirectory());
@@ -242,10 +271,13 @@ void cmake::SetArgs(cmMakefile& builder, const std::vector<std::string>& args)
 // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the cache
 void cmake::AddCMakePaths(const std::vector<std::string>& args)
 {
-  // Find our own executable.
+  // Find our own executable. If path translations are enabled and the
+  // user supplies the full path to cmake, use it as the canonical
+  // name (i.e. don't translate to a local disk path).
   std::string cMakeSelf = args[0];
   cmSystemTools::ConvertToUnixSlashes(cMakeSelf);
-  cMakeSelf = cmSystemTools::FindProgram(cMakeSelf.c_str());
+  if(!(m_UsePathTranslation && cmSystemTools::FileExists(cMakeSelf.c_str()) && cMakeSelf[0]!='.'))
+    cMakeSelf = cmSystemTools::FindProgram(cMakeSelf.c_str());
   if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
     {
 #ifdef CMAKE_BUILD_DIR

+ 1 - 0
Source/cmake.h

@@ -83,5 +83,6 @@ class cmake
 private:
   bool m_Verbose;
   bool m_Local;
+  bool m_UsePathTranslation;
 };