From d57047de33e096eac6fc84976c733b7941c9add3 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 7 Mar 2012 14:04:33 -0500 Subject: [PATCH] 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. --- Source/cmGeneratorTarget.h | 1 + Source/cmGlobalVisualStudioGenerator.cxx | 46 +++++++++++++++- Source/cmGlobalVisualStudioGenerator.h | 2 + Source/cmLocalVisualStudio6Generator.cxx | 64 ++++++++++++---------- Source/cmLocalVisualStudio6Generator.h | 1 + Source/cmLocalVisualStudio7Generator.cxx | 36 +++++------- Source/cmLocalVisualStudio7Generator.h | 6 +- Source/cmLocalVisualStudioGenerator.cxx | 63 --------------------- Source/cmLocalVisualStudioGenerator.h | 8 +-- Source/cmVisualStudio10TargetGenerator.cxx | 13 +---- 10 files changed, 104 insertions(+), 136 deletions(-) diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 976cac4f4..2bfc0374e 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -41,6 +41,7 @@ public: std::string ModuleDefinitionFile; std::map Objects; + std::set ExplicitObjectName; private: void ClassifySources(); diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 449d09016..e5a978459 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -12,8 +12,10 @@ #include "cmGlobalVisualStudioGenerator.h" #include "cmCallVisualStudioMacro.h" -#include "cmLocalGenerator.h" +#include "cmGeneratorTarget.h" +#include "cmLocalVisualStudioGenerator.h" #include "cmMakefile.h" +#include "cmSourceFile.h" #include "cmTarget.h" //---------------------------------------------------------------------------- @@ -97,6 +99,48 @@ void cmGlobalVisualStudioGenerator::Generate() this->cmGlobalGenerator::Generate(); } +//---------------------------------------------------------------------------- +void +cmGlobalVisualStudioGenerator +::ComputeTargetObjects(cmGeneratorTarget* gt) const +{ + cmLocalVisualStudioGenerator* lg = + static_cast(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 counts; + for(std::vector::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::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, const std::string& regKeyBase, diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index bc96f4e0a..b62ba229d 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -97,6 +97,8 @@ protected: typedef std::map UtilityDependsMap; UtilityDependsMap UtilityDepends; private: + void ComputeTargetObjects(cmGeneratorTarget* gt) const; + void FollowLinkDepends(cmTarget* target, std::set& linked); class TargetSetMap: public std::map {}; diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index 678c5bf72..8f5f11142 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -15,6 +15,7 @@ #include "cmSystemTools.h" #include "cmSourceFile.h" #include "cmCacheManager.h" +#include "cmGeneratorTarget.h" #include "cmake.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. this->WriteDSPHeader(fout, libName, target, sourceGroups); @@ -358,6 +356,8 @@ void cmLocalVisualStudio6Generator ::WriteGroup(const cmSourceGroup *sg, cmTarget& target, std::ostream &fout, const char *libName) { + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); const std::vector &sourceFiles = sg->GetSourceFiles(); // If the group is empty, don't write it at all. @@ -374,28 +374,6 @@ void cmLocalVisualStudio6Generator this->WriteDSPBeginGroup(fout, name.c_str(), ""); } - // Compute the maximum length configuration name. - std::string config_max; - for(std::vector::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. for(std::vector::const_iterator sf = sourceFiles.begin(); sf != sourceFiles.end(); ++sf) @@ -406,11 +384,9 @@ void cmLocalVisualStudio6Generator std::string compileFlags; std::vector depends; 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. @@ -1795,6 +1771,36 @@ cmLocalVisualStudio6Generator return ""; } +//---------------------------------------------------------------------------- +std::string +cmLocalVisualStudio6Generator +::ComputeLongestObjectDirectory(cmTarget&) const +{ + // Compute the maximum length configuration name. + std::string config_max; + for(std::vector::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 cmLocalVisualStudio6Generator ::GetConfigName(std::string const& configuration) const diff --git a/Source/cmLocalVisualStudio6Generator.h b/Source/cmLocalVisualStudio6Generator.h index 4e588c3ee..d36d63358 100644 --- a/Source/cmLocalVisualStudio6Generator.h +++ b/Source/cmLocalVisualStudio6Generator.h @@ -50,6 +50,7 @@ public: void SetBuildType(BuildType, const char* libName, cmTarget&); virtual std::string GetTargetDirectory(cmTarget const& target) const; + virtual std::string ComputeLongestObjectDirectory(cmTarget&) const; private: std::string DSPHeaderTemplate; std::string DSPFooterTemplate; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index c5714cce8..ee54433da 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -17,6 +17,7 @@ #include "cmSystemTools.h" #include "cmSourceFile.h" #include "cmCacheManager.h" +#include "cmGeneratorTarget.h" #include "cmake.h" #include "cmComputeLinkInformation.h" @@ -1310,9 +1311,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, sourceGroup.AssignSource(*i); } - // Compute which sources need unique object computation. - this->ComputeObjectNameRequirements(classes); - // open the project this->WriteProjectStart(fout, libName, target, sourceGroups); // write the configuration information @@ -1352,8 +1350,7 @@ public: cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg, cmTarget& target, cmSourceFile const& sf, - std::vector* configs, - std::string const& dir_max); + std::vector* configs); std::map FileConfigMap; }; @@ -1361,13 +1358,14 @@ cmLocalVisualStudio7GeneratorFCInfo ::cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg, cmTarget& target, cmSourceFile const& sf, - std::vector* configs, - std::string const& dir_max) + std::vector* configs) { + cmGeneratorTarget* gt = + lg->GetGlobalGenerator()->GetGeneratorTarget(&target); 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. @@ -1478,11 +1476,11 @@ cmLocalVisualStudio7GeneratorFCInfo } } - -void cmLocalVisualStudio7Generator -::ComputeMaxDirectoryLength(std::string& maxdir, - cmTarget& target) -{ +//---------------------------------------------------------------------------- +std::string +cmLocalVisualStudio7Generator +::ComputeLongestObjectDirectory(cmTarget& target) const +{ std::vector *configs = static_cast (this->GlobalGenerator)->GetConfigurations(); @@ -1507,7 +1505,7 @@ void cmLocalVisualStudio7Generator dir_max += "/"; dir_max += config_max; dir_max += "/"; - maxdir = dir_max; + return dir_max; } void cmLocalVisualStudio7Generator @@ -1530,19 +1528,13 @@ void cmLocalVisualStudio7Generator 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. std::string objectName; for(std::vector::const_iterator sf = sourceFiles.begin(); sf != sourceFiles.end(); ++sf) { 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 || target.GetType() == cmTarget::GLOBAL_TARGET ) diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index 6ddf82af8..9d3a9f29c 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -60,11 +60,7 @@ public: virtual std::string GetTargetDirectory(cmTarget const&) const; cmSourceFile* CreateVCProjBuildRule(); 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, const char* path); diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index f389b35ab..4bcf4defd 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -64,69 +64,6 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmTarget& target, 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 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 counts; - for(std::vector::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::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 { diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index e58c757ce..410cc9a52 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/Source/cmLocalVisualStudioGenerator.h @@ -56,6 +56,8 @@ public: /** Version of Visual Studio. */ VSVersion GetVersion() const { return this->Version; } + virtual std::string ComputeLongestObjectDirectory(cmTarget&) const = 0; + protected: virtual const char* ReportErrorLabel() const; virtual bool CustomCommandUseLocal() const { return false; } @@ -64,12 +66,6 @@ protected: cmsys::auto_ptr MaybeCreateImplibDir(cmTarget& target, const char* config, bool isFortran); - // Safe object file name generation. - void ComputeObjectNameRequirements(std::vector const&); - bool SourceFileCompiles(const cmSourceFile* sf); - std::set NeedObjectName; - friend class cmVisualStudio10TargetGenerator; - VSVersion Version; }; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 91688187a..b5794d6b0 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -72,8 +72,6 @@ cmVisualStudio10TargetGenerator(cmTarget* target, this->GlobalGenerator->CreateGUID(this->Name.c_str()); this->GUID = this->GlobalGenerator->GetGUID(this->Name.c_str()); this->Platform = gg->GetPlatformName(); - this->LocalGenerator - ->ComputeObjectNameRequirements(target->GetSourceFiles()); this->BuildFileStream = 0; } @@ -883,16 +881,11 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( cmSourceFile& sf = *source; 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; - 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 defines;