Sfoglia il codice sorgente

ENH: Moved unique object file name computation from cmLocalUnixMakefileGenerator3 up to cmLocalGenerator for use by all generators. Created cmLocalVisualStudioGenerator as superclass for all VS generators. Implemented on-demand unique object file name computation for VS 7 generator to avoid slow compiles when all sources are in subdirectories.

Brad King 19 anni fa
parent
commit
9bf5af6e32

+ 2 - 0
Source/CMakeLists.txt

@@ -205,6 +205,8 @@ IF (WIN32)
       cmLocalVisualStudio6Generator.h
       cmLocalVisualStudio7Generator.cxx
       cmLocalVisualStudio7Generator.h
+      cmLocalVisualStudioGenerator.cxx
+      cmLocalVisualStudioGenerator.h
       cmWin32ProcessExecution.cxx
       cmWin32ProcessExecution.h
       )

+ 117 - 0
Source/cmLocalGenerator.cxx

@@ -2081,3 +2081,120 @@ cmLocalGenerator
       }
     }
 }
+
+//----------------------------------------------------------------------------
+std::string& cmLocalGenerator::CreateSafeUniqueObjectFileName(const char* sin)
+{
+  // Look for an existing mapped name for this object file.
+  std::map<cmStdString,cmStdString>::iterator it =
+    this->UniqueObjectNamesMap.find(sin);
+
+  // If no entry exists create one.
+  if(it == this->UniqueObjectNamesMap.end())
+    {
+    // Start with the original name.
+    std::string ssin = sin;
+
+    // Avoid full paths by removing leading slashes.
+    std::string::size_type pos = 0;
+    for(;pos < ssin.size() && ssin[pos] == '/'; ++pos);
+    ssin = ssin.substr(pos);
+
+    // Avoid full paths by removing colons.
+    cmSystemTools::ReplaceString(ssin, ":", "_");
+
+    // Avoid relative paths that go up the tree.
+    cmSystemTools::ReplaceString(ssin, "../", "__/");
+
+    // Avoid spaces.
+    cmSystemTools::ReplaceString(ssin, " ", "_");
+
+    // Mangle the name if necessary.
+    if(this->Makefile->IsOn("CMAKE_MANGLE_OBJECT_FILE_NAMES"))
+      {
+      bool done;
+      int cc = 0;
+      char rpstr[100];
+      sprintf(rpstr, "_p_");
+      cmSystemTools::ReplaceString(ssin, "+", rpstr);
+      std::string sssin = sin;
+      do
+        {
+        done = true;
+        for ( it = this->UniqueObjectNamesMap.begin();
+              it != this->UniqueObjectNamesMap.end();
+              ++ it )
+          {
+          if ( it->second == ssin )
+            {
+            done = false;
+            }
+          }
+        if ( done )
+          {
+          break;
+          }
+        sssin = ssin;
+        cmSystemTools::ReplaceString(ssin, "_p_", rpstr);
+        sprintf(rpstr, "_p%d_", cc++);
+        }
+      while ( !done );
+      }
+
+    // Insert the newly mapped object file name.
+    std::map<cmStdString, cmStdString>::value_type e(sin, ssin);
+    it = this->UniqueObjectNamesMap.insert(e).first;
+    }
+
+  // Return the map entry.
+  return it->second;
+}
+
+//----------------------------------------------------------------------------
+std::string
+cmLocalGenerator::GetObjectFileNameWithoutTarget(const cmSourceFile& source)
+{
+  // If the source file is located below the current binary directory
+  // then use that relative path for the object file name.
+  std::string objectName = this->Convert(source.GetFullPath().c_str(),
+                                         START_OUTPUT);
+  if(cmSystemTools::FileIsFullPath(objectName.c_str()) ||
+     objectName.empty() || objectName[0] == '.')
+    {
+    // If the source file is located below the current source
+    // directory then use that relative path for the object file name.
+    // Otherwise just use the relative path from the current binary
+    // directory.
+    std::string relFromSource = this->Convert(source.GetFullPath().c_str(),
+                                              START);
+    if(!cmSystemTools::FileIsFullPath(relFromSource.c_str()) &&
+       !relFromSource.empty() && relFromSource[0] != '.')
+      {
+      objectName = relFromSource;
+      }
+    }
+
+  // Replace the original source file extension with the object file
+  // extension.
+  std::string::size_type dot_pos = objectName.rfind(".");
+  if(dot_pos != std::string::npos)
+    {
+    objectName = objectName.substr(0, dot_pos);
+    }
+  if ( source.GetPropertyAsBool("KEEP_EXTENSION") )
+    {
+    if ( !source.GetSourceExtension().empty() )
+      {
+      objectName += "." + source.GetSourceExtension();
+      }
+    }
+  else
+    {
+    objectName +=
+      this->GlobalGenerator->GetLanguageOutputExtensionFromExtension(
+        source.GetSourceExtension().c_str());
+    }
+
+  // Convert to a safe name.
+  return this->CreateSafeUniqueObjectFileName(objectName.c_str());
+}

+ 5 - 0
Source/cmLocalGenerator.h

@@ -254,6 +254,10 @@ protected:
     std::ostream& os, const char* config,
     std::vector<std::string> const& configurationTypes);
 
+  // Compute object file names.
+  std::string GetObjectFileNameWithoutTarget(const cmSourceFile& source);
+  std::string& CreateSafeUniqueObjectFileName(const char* sin);
+
   cmMakefile *Makefile;
   cmGlobalGenerator *GlobalGenerator;
   // members used for relative path function ConvertToMakefilePath
@@ -267,6 +271,7 @@ protected:
   cmLocalGenerator* Parent;
   std::vector<cmLocalGenerator*> Children;
   std::map<cmStdString, cmStdString> LanguageToIncludeFlags;
+  std::map<cmStdString, cmStdString> UniqueObjectNamesMap;
   bool WindowsShell;
   bool ForceUnixPath;
   bool UseRelativePaths;

+ 4 - 114
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -1061,75 +1061,6 @@ std::string cmLocalUnixMakefileGenerator3
   return ret;
 }
 
-//----------------------------------------------------------------------------
-std::string&
-cmLocalUnixMakefileGenerator3::CreateSafeUniqueObjectFileName(const char* sin)
-{
-  // Look for an existing mapped name for this object file.
-  std::map<cmStdString,cmStdString>::iterator it =
-    this->UniqueObjectNamesMap.find(sin);
-
-  // If no entry exists create one.
-  if(it == this->UniqueObjectNamesMap.end())
-    {
-    // Start with the original name.
-    std::string ssin = sin;
-
-    // Avoid full paths by removing leading slashes.
-    std::string::size_type pos = 0;
-    for(;pos < ssin.size() && ssin[pos] == '/'; ++pos);
-    ssin = ssin.substr(pos);
-
-    // Avoid full paths by removing colons.
-    cmSystemTools::ReplaceString(ssin, ":", "_");
-
-    // Avoid relative paths that go up the tree.
-    cmSystemTools::ReplaceString(ssin, "../", "__/");
-
-    // Avoid spaces.
-    cmSystemTools::ReplaceString(ssin, " ", "_");
-
-    // Mangle the name if necessary.
-    if(this->Makefile->IsOn("CMAKE_MANGLE_OBJECT_FILE_NAMES"))
-      {
-      bool done;
-      int cc = 0;
-      char rpstr[100];
-      sprintf(rpstr, "_p_");
-      cmSystemTools::ReplaceString(ssin, "+", rpstr);
-      std::string sssin = sin;
-      do
-        {
-        done = true;
-        for ( it = this->UniqueObjectNamesMap.begin();
-              it != this->UniqueObjectNamesMap.end();
-              ++ it )
-          {
-          if ( it->second == ssin )
-            {
-            done = false;
-            }
-          }
-        if ( done )
-          {
-          break;
-          }
-        sssin = ssin;
-        cmSystemTools::ReplaceString(ssin, "_p_", rpstr);
-        sprintf(rpstr, "_p%d_", cc++);
-        }
-      while ( !done );
-      }
-
-    // Insert the newly mapped object file name.
-    std::map<cmStdString, cmStdString>::value_type e(sin, ssin);
-    it = this->UniqueObjectNamesMap.insert(e).first;
-    }
-
-  // Return the map entry.
-  return it->second;
-}
-
 //----------------------------------------------------------------------------
 std::string
 cmLocalUnixMakefileGenerator3
@@ -1707,50 +1638,13 @@ cmLocalUnixMakefileGenerator3
                     const cmSourceFile& source,
                     std::string* nameWithoutTargetDir)
 {
-  // If the source file is located below the current binary directory
-  // then use that relative path for the object file name.
-  std::string objectName = this->Convert(source.GetFullPath().c_str(),
-                                         START_OUTPUT);
-  if(cmSystemTools::FileIsFullPath(objectName.c_str()) ||
-     objectName.empty() || objectName[0] == '.')
-    {
-    // If the source file is located below the current source
-    // directory then use that relative path for the object file name.
-    // Otherwise just use the relative path from the current binary
-    // directory.
-    std::string relFromSource = this->Convert(source.GetFullPath().c_str(),
-                                              START);
-    if(!cmSystemTools::FileIsFullPath(relFromSource.c_str()) &&
-       !relFromSource.empty() && relFromSource[0] != '.')
-      {
-      objectName = relFromSource;
-      }
-    }
-
-  // Replace the original source file extension with the object file
-  // extension.
-  std::string::size_type dot_pos = objectName.rfind(".");
-  if(dot_pos != std::string::npos)
-    {
-    objectName = objectName.substr(0, dot_pos);
-    }
-  if ( source.GetPropertyAsBool("KEEP_EXTENSION") )
-    {
-    if ( !source.GetSourceExtension().empty() )
-      {
-      objectName += "." + source.GetSourceExtension();
-      }
-    }
-  else
+  // Get the object file name independent of target.
+  std::string objectName = this->GetObjectFileNameWithoutTarget(source);
+  if(nameWithoutTargetDir)
     {
-    objectName +=
-      this->GlobalGenerator->GetLanguageOutputExtensionFromExtension(
-        source.GetSourceExtension().c_str());
+    *nameWithoutTargetDir = objectName;
     }
 
-  // Convert to a safe name.
-  objectName = this->CreateSafeUniqueObjectFileName(objectName.c_str());
-
   // Prepend the target directory.
   std::string obj;
   const char* fileTargetDirectory = 
@@ -1788,10 +1682,6 @@ cmLocalUnixMakefileGenerator3
     }
   obj += "/";
   obj += objectName;
-  if(nameWithoutTargetDir)
-    {
-    *nameWithoutTargetDir = objectName;
-    }
   return obj;
 }
 

+ 0 - 2
Source/cmLocalUnixMakefileGenerator3.h

@@ -168,7 +168,6 @@ public:
 
   static std::string ConvertToQuotedOutputPath(const char* p);
 
-  std::string& CreateSafeUniqueObjectFileName(const char* sin);
   std::string CreateMakeVariable(const char* sin, const char* s2in);
 
   // cleanup the name of a potential target
@@ -326,7 +325,6 @@ private:
   std::vector<cmMakefileTargetGenerator *> TargetGenerators;
   std::map<cmStdString, cmStdString> MakeVariableMap;
   std::map<cmStdString, cmStdString> ShortMakeVariableMap;
-  std::map<cmStdString, cmStdString> UniqueObjectNamesMap;
 };
 
 #endif

+ 5 - 5
Source/cmLocalVisualStudio7Generator.cxx

@@ -1012,6 +1012,9 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
     sourceGroup.AssignSource(*i);
     }
 
+  // Compute which sources need unique object computation.
+  this->ComputeObjectNameRequirements(sourceGroups);
+
   // open the project
   this->WriteProjectStart(fout, libName, target, sourceGroups);
   // write the configuration information
@@ -1064,12 +1067,9 @@ void cmLocalVisualStudio7Generator
     const cmCustomCommand *command = (*sf)->GetCustomCommand();
     std::string compileFlags;
     std::string additionalDeps;
-    objectName = (*sf)->GetSourceName();
-    if(!(*sf)->GetPropertyAsBool("HEADER_FILE_ONLY" )
-       && objectName.find("/") != objectName.npos)
+    if(this->NeedObjectName.find(*sf) != this->NeedObjectName.end())
       {
-      cmSystemTools::ReplaceString(objectName, "/", "_");
-      objectName += ".obj";
+      objectName = this->GetObjectFileNameWithoutTarget(*(*sf));
       }
     else
       {

+ 5 - 5
Source/cmLocalVisualStudio7Generator.h

@@ -17,7 +17,7 @@
 #ifndef cmLocalVisualStudio7Generator_h
 #define cmLocalVisualStudio7Generator_h
 
-#include "cmLocalGenerator.h"
+#include "cmLocalVisualStudioGenerator.h"
 
 class cmMakeDepend;
 class cmTarget;
@@ -27,12 +27,12 @@ class cmSourceGroup;
 struct cmVS7FlagTable;
 
 /** \class cmLocalVisualStudio7Generator
- * \brief Write a LocalUnix makefiles.
+ * \brief Write Visual Studio .NET project files.
  *
- * cmLocalVisualStudio7Generator produces a LocalUnix makefile from its
- * member Makefile.
+ * cmLocalVisualStudio7Generator produces a Visual Studio .NET project
+ * file for each target in its directory.
  */
-class cmLocalVisualStudio7Generator : public cmLocalGenerator
+class cmLocalVisualStudio7Generator : public cmLocalVisualStudioGenerator
 {
 public:
   ///! Set cache only and recurse to false by default.

+ 89 - 0
Source/cmLocalVisualStudioGenerator.cxx

@@ -0,0 +1,89 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmLocalVisualStudioGenerator.h"
+
+#include "cmMakefile.h"
+#include "cmSourceFile.h"
+#include "cmSystemTools.h"
+
+//----------------------------------------------------------------------------
+cmLocalVisualStudioGenerator::cmLocalVisualStudioGenerator()
+{
+}
+
+//----------------------------------------------------------------------------
+cmLocalVisualStudioGenerator::~cmLocalVisualStudioGenerator()
+{
+}
+
+//----------------------------------------------------------------------------
+void
+cmLocalVisualStudioGenerator
+::ComputeObjectNameRequirements(std::vector<cmSourceGroup> const& sourceGroups)
+{
+  // Clear the current set of requirements.
+  this->NeedObjectName.clear();
+
+  // Count the number of object files with each name.
+  std::map<cmStdString, int> objectNameCounts;
+  for(unsigned int i = 0; i < sourceGroups.size(); ++i)
+    {
+    cmSourceGroup sg = sourceGroups[i];
+    std::vector<const cmSourceFile*> const& srcs = sg.GetSourceFiles();
+    for(std::vector<const cmSourceFile*>::const_iterator s = srcs.begin();
+        s != srcs.end(); ++s)
+      {
+      const cmSourceFile& sf = *(*s);
+      if(!sf.GetCustomCommand() &&
+         !sf.GetPropertyAsBool("HEADER_FILE_ONLY") &&
+         !sf.GetPropertyAsBool("EXTERNAL_OBJECT"))
+        {
+        std::string objectName =
+          cmSystemTools::GetFilenameWithoutLastExtension(
+            sf.GetFullPath().c_str());
+        objectName += ".obj";
+        objectNameCounts[objectName] += 1;
+        }
+      }
+    }
+
+  // For all source files producing duplicate names we need unique
+  // object name computation.
+  for(unsigned int i = 0; i < sourceGroups.size(); ++i)
+    {
+    cmSourceGroup sg = sourceGroups[i];
+    std::vector<const cmSourceFile*> const& srcs = sg.GetSourceFiles();
+    for(std::vector<const cmSourceFile*>::const_iterator s = srcs.begin();
+        s != srcs.end(); ++s)
+      {
+      const cmSourceFile* sf = *s;
+      if(!sf->GetCustomCommand() &&
+         !sf->GetPropertyAsBool("HEADER_FILE_ONLY") &&
+         !sf->GetPropertyAsBool("EXTERNAL_OBJECT"))
+        {
+        std::string objectName =
+          cmSystemTools::GetFilenameWithoutLastExtension(
+            sf->GetFullPath().c_str());
+        objectName += ".obj";
+        if(objectNameCounts[objectName] > 1)
+          {
+          this->NeedObjectName.insert(sf);
+          }
+        }
+      }
+    }
+}

+ 43 - 0
Source/cmLocalVisualStudioGenerator.h

@@ -0,0 +1,43 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmLocalVisualStudioGenerator_h
+#define cmLocalVisualStudioGenerator_h
+
+#include "cmLocalGenerator.h"
+
+class cmSourceFile;
+class cmSourceGroup;
+
+/** \class cmLocalVisualStudioGenerator
+ * \brief Base class for Visual Studio generators.
+ *
+ * cmLocalVisualStudioGenerator provides functionality common to all
+ * Visual Studio generators.
+ */
+class cmLocalVisualStudioGenerator : public cmLocalGenerator
+{
+public:
+  cmLocalVisualStudioGenerator();
+  virtual ~cmLocalVisualStudioGenerator();
+
+protected:
+  // Safe object file name generation.
+  void ComputeObjectNameRequirements(std::vector<cmSourceGroup> const&);
+  std::set<const cmSourceFile*> NeedObjectName;
+};
+
+#endif