浏览代码

Pre-compute object file names before VS project generation

Implement cmGlobalGenerator::ComputeTargetObjects in the VS generator
to pre-compute all the object file names.  Use the results during
generation instead of re-computing it later.
Brad King 13 年之前
父节点
当前提交
d57047de33

+ 1 - 0
Source/cmGeneratorTarget.h

@@ -41,6 +41,7 @@ public:
   std::string ModuleDefinitionFile;
   std::string ModuleDefinitionFile;
 
 
   std::map<cmSourceFile const*, std::string> Objects;
   std::map<cmSourceFile const*, std::string> Objects;
+  std::set<cmSourceFile const*> ExplicitObjectName;
 
 
 private:
 private:
   void ClassifySources();
   void ClassifySources();

+ 45 - 1
Source/cmGlobalVisualStudioGenerator.cxx

@@ -12,8 +12,10 @@
 #include "cmGlobalVisualStudioGenerator.h"
 #include "cmGlobalVisualStudioGenerator.h"
 
 
 #include "cmCallVisualStudioMacro.h"
 #include "cmCallVisualStudioMacro.h"
-#include "cmLocalGenerator.h"
+#include "cmGeneratorTarget.h"
+#include "cmLocalVisualStudioGenerator.h"
 #include "cmMakefile.h"
 #include "cmMakefile.h"
+#include "cmSourceFile.h"
 #include "cmTarget.h"
 #include "cmTarget.h"
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
@@ -97,6 +99,48 @@ void cmGlobalVisualStudioGenerator::Generate()
   this->cmGlobalGenerator::Generate();
   this->cmGlobalGenerator::Generate();
 }
 }
 
 
+//----------------------------------------------------------------------------
+void
+cmGlobalVisualStudioGenerator
+::ComputeTargetObjects(cmGeneratorTarget* gt) const
+{
+  cmLocalVisualStudioGenerator* lg =
+    static_cast<cmLocalVisualStudioGenerator*>(gt->LocalGenerator);
+  std::string dir_max = lg->ComputeLongestObjectDirectory(*gt->Target);
+
+  // Count the number of object files with each name.  Note that
+  // windows file names are not case sensitive.
+  std::map<cmStdString, int> counts;
+  for(std::vector<cmSourceFile*>::const_iterator
+        si = gt->ObjectSources.begin();
+      si != gt->ObjectSources.end(); ++si)
+    {
+    cmSourceFile* sf = *si;
+    std::string objectNameLower = cmSystemTools::LowerCase(
+      cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()));
+    objectNameLower += ".obj";
+    counts[objectNameLower] += 1;
+    }
+
+  // For all source files producing duplicate names we need unique
+  // object name computation.
+  for(std::vector<cmSourceFile*>::const_iterator
+        si = gt->ObjectSources.begin();
+      si != gt->ObjectSources.end(); ++si)
+    {
+    cmSourceFile* sf = *si;
+    std::string objectName =
+      cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
+    objectName += ".obj";
+    if(counts[cmSystemTools::LowerCase(objectName)] > 1)
+      {
+      gt->ExplicitObjectName.insert(sf);
+      objectName = lg->GetObjectFileNameWithoutTarget(*sf, dir_max);
+      }
+    gt->Objects[sf] = objectName;
+    }
+}
+
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
 bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
   const std::string& regKeyBase,
   const std::string& regKeyBase,

+ 2 - 0
Source/cmGlobalVisualStudioGenerator.h

@@ -97,6 +97,8 @@ protected:
   typedef std::map<cmTarget*, cmStdString> UtilityDependsMap;
   typedef std::map<cmTarget*, cmStdString> UtilityDependsMap;
   UtilityDependsMap UtilityDepends;
   UtilityDependsMap UtilityDepends;
 private:
 private:
+  void ComputeTargetObjects(cmGeneratorTarget* gt) const;
+
   void FollowLinkDepends(cmTarget* target, std::set<cmTarget*>& linked);
   void FollowLinkDepends(cmTarget* target, std::set<cmTarget*>& linked);
 
 
   class TargetSetMap: public std::map<cmTarget*, TargetSet> {};
   class TargetSetMap: public std::map<cmTarget*, TargetSet> {};

+ 35 - 29
Source/cmLocalVisualStudio6Generator.cxx

@@ -15,6 +15,7 @@
 #include "cmSystemTools.h"
 #include "cmSystemTools.h"
 #include "cmSourceFile.h"
 #include "cmSourceFile.h"
 #include "cmCacheManager.h"
 #include "cmCacheManager.h"
+#include "cmGeneratorTarget.h"
 #include "cmake.h"
 #include "cmake.h"
 
 
 #include "cmComputeLinkInformation.h"
 #include "cmComputeLinkInformation.h"
@@ -336,9 +337,6 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
       }
       }
     }
     }
 
 
-  // Compute which sources need unique object computation.
-  this->ComputeObjectNameRequirements(classes);
-  
   // Write the DSP file's header.
   // Write the DSP file's header.
   this->WriteDSPHeader(fout, libName, target, sourceGroups);
   this->WriteDSPHeader(fout, libName, target, sourceGroups);
   
   
@@ -358,6 +356,8 @@ void cmLocalVisualStudio6Generator
 ::WriteGroup(const cmSourceGroup *sg, cmTarget& target,
 ::WriteGroup(const cmSourceGroup *sg, cmTarget& target,
              std::ostream &fout, const char *libName)
              std::ostream &fout, const char *libName)
 {
 {
+  cmGeneratorTarget* gt =
+    this->GlobalGenerator->GetGeneratorTarget(&target);
   const std::vector<const cmSourceFile *> &sourceFiles = 
   const std::vector<const cmSourceFile *> &sourceFiles = 
     sg->GetSourceFiles();
     sg->GetSourceFiles();
   // If the group is empty, don't write it at all.
   // If the group is empty, don't write it at all.
@@ -374,28 +374,6 @@ void cmLocalVisualStudio6Generator
     this->WriteDSPBeginGroup(fout, name.c_str(), "");
     this->WriteDSPBeginGroup(fout, name.c_str(), "");
     }
     }
 
 
-  // Compute the maximum length configuration name.
-  std::string config_max;
-  for(std::vector<std::string>::iterator i = this->Configurations.begin();
-      i != this->Configurations.end(); ++i)
-    {
-    // Strip the subdirectory name out of the configuration name.
-    std::string config = this->GetConfigName(*i);
-    if(config.size() > config_max.size())
-      {
-      config_max = config;
-      }
-    }
-
-  // Compute the maximum length full path to the intermediate
-  // files directory for any configuration.  This is used to construct
-  // object file names that do not produce paths that are too long.
-  std::string dir_max;
-  dir_max += this->Makefile->GetCurrentOutputDirectory();
-  dir_max += "/";
-  dir_max += config_max;
-  dir_max += "/";
-
   // Loop through each source in the source group.
   // Loop through each source in the source group.
   for(std::vector<const cmSourceFile *>::const_iterator sf =
   for(std::vector<const cmSourceFile *>::const_iterator sf =
         sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
         sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
@@ -406,11 +384,9 @@ void cmLocalVisualStudio6Generator
     std::string compileFlags;
     std::string compileFlags;
     std::vector<std::string> depends;
     std::vector<std::string> depends;
     std::string objectNameDir;
     std::string objectNameDir;
-    if(this->NeedObjectName.find(*sf) != this->NeedObjectName.end())
+    if(gt->ExplicitObjectName.find(*sf) != gt->ExplicitObjectName.end())
       {
       {
-      objectNameDir =
-        cmSystemTools::GetFilenamePath(
-          this->GetObjectFileNameWithoutTarget(*(*sf), dir_max));
+      objectNameDir = cmSystemTools::GetFilenamePath(gt->Objects[*sf]);
       }
       }
 
 
     // Add per-source file flags.
     // Add per-source file flags.
@@ -1795,6 +1771,36 @@ cmLocalVisualStudio6Generator
   return "";
   return "";
 }
 }
 
 
+//----------------------------------------------------------------------------
+std::string
+cmLocalVisualStudio6Generator
+::ComputeLongestObjectDirectory(cmTarget&) const
+{
+  // Compute the maximum length configuration name.
+  std::string config_max;
+  for(std::vector<std::string>::const_iterator
+        i = this->Configurations.begin();
+      i != this->Configurations.end(); ++i)
+    {
+    // Strip the subdirectory name out of the configuration name.
+    std::string config = this->GetConfigName(*i);
+    if(config.size() > config_max.size())
+      {
+      config_max = config;
+      }
+    }
+
+  // Compute the maximum length full path to the intermediate
+  // files directory for any configuration.  This is used to construct
+  // object file names that do not produce paths that are too long.
+  std::string dir_max;
+  dir_max += this->Makefile->GetCurrentOutputDirectory();
+  dir_max += "/";
+  dir_max += config_max;
+  dir_max += "/";
+  return dir_max;
+}
+
 std::string
 std::string
 cmLocalVisualStudio6Generator
 cmLocalVisualStudio6Generator
 ::GetConfigName(std::string const& configuration) const
 ::GetConfigName(std::string const& configuration) const

+ 1 - 0
Source/cmLocalVisualStudio6Generator.h

@@ -50,6 +50,7 @@ public:
   void SetBuildType(BuildType, const char* libName, cmTarget&);
   void SetBuildType(BuildType, const char* libName, cmTarget&);
 
 
   virtual std::string GetTargetDirectory(cmTarget const& target) const;
   virtual std::string GetTargetDirectory(cmTarget const& target) const;
+  virtual std::string ComputeLongestObjectDirectory(cmTarget&) const;
 private:
 private:
   std::string DSPHeaderTemplate;
   std::string DSPHeaderTemplate;
   std::string DSPFooterTemplate;
   std::string DSPFooterTemplate;

+ 14 - 22
Source/cmLocalVisualStudio7Generator.cxx

@@ -17,6 +17,7 @@
 #include "cmSystemTools.h"
 #include "cmSystemTools.h"
 #include "cmSourceFile.h"
 #include "cmSourceFile.h"
 #include "cmCacheManager.h"
 #include "cmCacheManager.h"
+#include "cmGeneratorTarget.h"
 #include "cmake.h"
 #include "cmake.h"
 
 
 #include "cmComputeLinkInformation.h"
 #include "cmComputeLinkInformation.h"
@@ -1310,9 +1311,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
     sourceGroup.AssignSource(*i);
     sourceGroup.AssignSource(*i);
     }
     }
 
 
-  // Compute which sources need unique object computation.
-  this->ComputeObjectNameRequirements(classes);
-
   // open the project
   // open the project
   this->WriteProjectStart(fout, libName, target, sourceGroups);
   this->WriteProjectStart(fout, libName, target, sourceGroups);
   // write the configuration information
   // write the configuration information
@@ -1352,8 +1350,7 @@ public:
   cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg,
   cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg,
                                       cmTarget& target,
                                       cmTarget& target,
                                       cmSourceFile const& sf,
                                       cmSourceFile const& sf,
-                                      std::vector<std::string>* configs,
-                                      std::string const& dir_max);
+                                      std::vector<std::string>* configs);
   std::map<cmStdString, cmLVS7GFileConfig> FileConfigMap;
   std::map<cmStdString, cmLVS7GFileConfig> FileConfigMap;
 };
 };
 
 
@@ -1361,13 +1358,14 @@ cmLocalVisualStudio7GeneratorFCInfo
 ::cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg,
 ::cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg,
                                       cmTarget& target,
                                       cmTarget& target,
                                       cmSourceFile const& sf,
                                       cmSourceFile const& sf,
-                                      std::vector<std::string>* configs,
-                                      std::string const& dir_max)
+                                      std::vector<std::string>* configs)
 {
 {
+  cmGeneratorTarget* gt =
+    lg->GetGlobalGenerator()->GetGeneratorTarget(&target);
   std::string objectName;
   std::string objectName;
-  if(lg->NeedObjectName.find(&sf) != lg->NeedObjectName.end())
+  if(gt->ExplicitObjectName.find(&sf) != gt->ExplicitObjectName.end())
     {
     {
-    objectName = lg->GetObjectFileNameWithoutTarget(sf, dir_max);
+    objectName = gt->Objects[&sf];
     }
     }
 
 
   // Compute per-source, per-config information.
   // Compute per-source, per-config information.
@@ -1478,11 +1476,11 @@ cmLocalVisualStudio7GeneratorFCInfo
     }
     }
 }
 }
 
 
-
-void cmLocalVisualStudio7Generator
-::ComputeMaxDirectoryLength(std::string& maxdir,
-  cmTarget& target)
-{  
+//----------------------------------------------------------------------------
+std::string
+cmLocalVisualStudio7Generator
+::ComputeLongestObjectDirectory(cmTarget& target) const
+{
   std::vector<std::string> *configs =
   std::vector<std::string> *configs =
     static_cast<cmGlobalVisualStudio7Generator *>
     static_cast<cmGlobalVisualStudio7Generator *>
     (this->GlobalGenerator)->GetConfigurations();
     (this->GlobalGenerator)->GetConfigurations();
@@ -1507,7 +1505,7 @@ void cmLocalVisualStudio7Generator
   dir_max += "/";
   dir_max += "/";
   dir_max += config_max;
   dir_max += config_max;
   dir_max += "/";
   dir_max += "/";
-  maxdir = dir_max;
+  return dir_max;
 }
 }
 
 
 void cmLocalVisualStudio7Generator
 void cmLocalVisualStudio7Generator
@@ -1530,19 +1528,13 @@ void cmLocalVisualStudio7Generator
     this->WriteVCProjBeginGroup(fout, name.c_str(), "");
     this->WriteVCProjBeginGroup(fout, name.c_str(), "");
     }
     }
 
 
-  // Compute the maximum length full path to the intermediate
-  // files directory for any configuration.  This is used to construct
-  // object file names that do not produce paths that are too long.
-  std::string dir_max;
-  this->ComputeMaxDirectoryLength(dir_max, target);
-
   // Loop through each source in the source group.
   // Loop through each source in the source group.
   std::string objectName;
   std::string objectName;
   for(std::vector<const cmSourceFile *>::const_iterator sf =
   for(std::vector<const cmSourceFile *>::const_iterator sf =
         sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
         sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
     {
     {
     std::string source = (*sf)->GetFullPath();
     std::string source = (*sf)->GetFullPath();
-    FCInfo fcinfo(this, target, *(*sf), configs, dir_max);
+    FCInfo fcinfo(this, target, *(*sf), configs);
 
 
     if (source != libName || target.GetType() == cmTarget::UTILITY ||
     if (source != libName || target.GetType() == cmTarget::UTILITY ||
       target.GetType() == cmTarget::GLOBAL_TARGET )
       target.GetType() == cmTarget::GLOBAL_TARGET )

+ 1 - 5
Source/cmLocalVisualStudio7Generator.h

@@ -60,11 +60,7 @@ public:
   virtual std::string GetTargetDirectory(cmTarget const&) const;
   virtual std::string GetTargetDirectory(cmTarget const&) const;
   cmSourceFile* CreateVCProjBuildRule();
   cmSourceFile* CreateVCProjBuildRule();
   void WriteStampFiles();
   void WriteStampFiles();
-  // Compute the maximum length full path to the intermediate
-  // files directory for any configuration.  This is used to construct
-  // object file names that do not produce paths that are too long.
-  void ComputeMaxDirectoryLength(std::string& maxdir,
-                                 cmTarget& target);
+  virtual std::string ComputeLongestObjectDirectory(cmTarget&) const;
 
 
   virtual void ReadAndStoreExternalGUID(const char* name,
   virtual void ReadAndStoreExternalGUID(const char* name,
                                         const char* path);
                                         const char* path);

+ 0 - 63
Source/cmLocalVisualStudioGenerator.cxx

@@ -64,69 +64,6 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmTarget& target,
   return pcc;
   return pcc;
 }
 }
 
 
-//----------------------------------------------------------------------------
-bool cmLocalVisualStudioGenerator::SourceFileCompiles(const cmSourceFile* sf)
-{
-  // Identify the language of the source file.
-  if(const char* lang = this->GetSourceFileLanguage(*sf))
-    {
-    // Check whether this source will actually be compiled.
-    return (!sf->GetCustomCommand() &&
-            !sf->GetPropertyAsBool("HEADER_FILE_ONLY") &&
-            !sf->GetPropertyAsBool("EXTERNAL_OBJECT"));
-    }
-  else
-    {
-    // Unknown source file language.  Assume it will not be compiled.
-    return false;
-    }
-}
-
-//----------------------------------------------------------------------------
-void
-cmLocalVisualStudioGenerator::ComputeObjectNameRequirements(
-  std::vector<cmSourceFile*> const& sources
-  )
-{
-  // Clear the current set of requirements.
-  this->NeedObjectName.clear();
-
-  // Count the number of object files with each name.  Note that
-  // windows file names are not case sensitive.
-  std::map<cmStdString, int> counts;
-  for(std::vector<cmSourceFile*>::const_iterator s = sources.begin();
-      s != sources.end(); ++s)
-    {
-    const cmSourceFile* sf = *s;
-    if(this->SourceFileCompiles(sf))
-      {
-      std::string objectName = cmSystemTools::LowerCase(
-        cmSystemTools::GetFilenameWithoutLastExtension(
-          sf->GetFullPath()));
-      objectName += ".obj";
-      counts[objectName] += 1;
-      }
-    }
-
-  // For all source files producing duplicate names we need unique
-  // object name computation.
-  for(std::vector<cmSourceFile*>::const_iterator s = sources.begin();
-      s != sources.end(); ++s)
-    {
-    const cmSourceFile* sf = *s;
-    if(this->SourceFileCompiles(sf))
-      {
-      std::string objectName = cmSystemTools::LowerCase(
-         cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()));
-      objectName += ".obj";
-      if(counts[objectName] > 1)
-        {
-        this->NeedObjectName.insert(sf);
-        }
-      }
-    }
-}
-
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 const char* cmLocalVisualStudioGenerator::ReportErrorLabel() const
 const char* cmLocalVisualStudioGenerator::ReportErrorLabel() const
 {
 {

+ 2 - 6
Source/cmLocalVisualStudioGenerator.h

@@ -56,6 +56,8 @@ public:
   /** Version of Visual Studio.  */
   /** Version of Visual Studio.  */
   VSVersion GetVersion() const { return this->Version; }
   VSVersion GetVersion() const { return this->Version; }
 
 
+  virtual std::string ComputeLongestObjectDirectory(cmTarget&) const = 0;
+
 protected:
 protected:
   virtual const char* ReportErrorLabel() const;
   virtual const char* ReportErrorLabel() const;
   virtual bool CustomCommandUseLocal() const { return false; }
   virtual bool CustomCommandUseLocal() const { return false; }
@@ -64,12 +66,6 @@ protected:
   cmsys::auto_ptr<cmCustomCommand>
   cmsys::auto_ptr<cmCustomCommand>
   MaybeCreateImplibDir(cmTarget& target, const char* config, bool isFortran);
   MaybeCreateImplibDir(cmTarget& target, const char* config, bool isFortran);
 
 
-  // Safe object file name generation.
-  void ComputeObjectNameRequirements(std::vector<cmSourceFile*> const&);
-  bool SourceFileCompiles(const cmSourceFile* sf);
-  std::set<const cmSourceFile*> NeedObjectName;
-  friend class cmVisualStudio10TargetGenerator;
-
   VSVersion Version;
   VSVersion Version;
 };
 };
 
 

+ 3 - 10
Source/cmVisualStudio10TargetGenerator.cxx

@@ -72,8 +72,6 @@ cmVisualStudio10TargetGenerator(cmTarget* target,
   this->GlobalGenerator->CreateGUID(this->Name.c_str());
   this->GlobalGenerator->CreateGUID(this->Name.c_str());
   this->GUID = this->GlobalGenerator->GetGUID(this->Name.c_str());
   this->GUID = this->GlobalGenerator->GetGUID(this->Name.c_str());
   this->Platform = gg->GetPlatformName();
   this->Platform = gg->GetPlatformName();
-  this->LocalGenerator
-    ->ComputeObjectNameRequirements(target->GetSourceFiles());
   this->BuildFileStream = 0;
   this->BuildFileStream = 0;
 }
 }
 
 
@@ -883,16 +881,11 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
   cmSourceFile& sf = *source;
   cmSourceFile& sf = *source;
   cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
   cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
 
 
-  // Compute the maximum length full path to the intermediate
-  // files directory for any configuration.  This is used to construct
-  // object file names that do not produce paths that are too long.
-  std::string dir_max;
-  lg->ComputeMaxDirectoryLength(dir_max, *this->Target);
-
   std::string objectName;
   std::string objectName;
-  if(lg->NeedObjectName.find(&sf) != lg->NeedObjectName.end())
+  if(this->GeneratorTarget->ExplicitObjectName.find(&sf)
+     != this->GeneratorTarget->ExplicitObjectName.end())
     {
     {
-    objectName = lg->GetObjectFileNameWithoutTarget(sf, dir_max);
+    objectName = this->GeneratorTarget->Objects[&sf];
     }
     }
   std::string flags;
   std::string flags;
   std::string defines;
   std::string defines;