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.
This commit is contained in:
parent
3baaf6ccec
commit
d57047de33
|
@ -41,6 +41,7 @@ public:
|
|||
std::string ModuleDefinitionFile;
|
||||
|
||||
std::map<cmSourceFile const*, std::string> Objects;
|
||||
std::set<cmSourceFile const*> ExplicitObjectName;
|
||||
|
||||
private:
|
||||
void ClassifySources();
|
||||
|
|
|
@ -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<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,
|
||||
const std::string& regKeyBase,
|
||||
|
|
|
@ -97,6 +97,8 @@ protected:
|
|||
typedef std::map<cmTarget*, cmStdString> UtilityDependsMap;
|
||||
UtilityDependsMap UtilityDepends;
|
||||
private:
|
||||
void ComputeTargetObjects(cmGeneratorTarget* gt) const;
|
||||
|
||||
void FollowLinkDepends(cmTarget* target, std::set<cmTarget*>& linked);
|
||||
|
||||
class TargetSetMap: public std::map<cmTarget*, TargetSet> {};
|
||||
|
|
|
@ -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<const cmSourceFile *> &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<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.
|
||||
for(std::vector<const cmSourceFile *>::const_iterator sf =
|
||||
sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
|
||||
|
@ -406,11 +384,9 @@ void cmLocalVisualStudio6Generator
|
|||
std::string compileFlags;
|
||||
std::vector<std::string> 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<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
|
||||
cmLocalVisualStudio6Generator
|
||||
::GetConfigName(std::string const& configuration) const
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<std::string>* configs,
|
||||
std::string const& dir_max);
|
||||
std::vector<std::string>* configs);
|
||||
std::map<cmStdString, cmLVS7GFileConfig> FileConfigMap;
|
||||
};
|
||||
|
||||
|
@ -1361,13 +1358,14 @@ cmLocalVisualStudio7GeneratorFCInfo
|
|||
::cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg,
|
||||
cmTarget& target,
|
||||
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;
|
||||
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<std::string> *configs =
|
||||
static_cast<cmGlobalVisualStudio7Generator *>
|
||||
(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 cmSourceFile *>::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 )
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<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
|
||||
{
|
||||
|
|
|
@ -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<cmCustomCommand>
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue