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.
This commit is contained in:
parent
c05b8fb993
commit
9bf5af6e32
|
@ -205,6 +205,8 @@ IF (WIN32)
|
|||
cmLocalVisualStudio6Generator.h
|
||||
cmLocalVisualStudio7Generator.cxx
|
||||
cmLocalVisualStudio7Generator.h
|
||||
cmLocalVisualStudioGenerator.cxx
|
||||
cmLocalVisualStudioGenerator.h
|
||||
cmWin32ProcessExecution.cxx
|
||||
cmWin32ProcessExecution.h
|
||||
)
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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] == '.')
|
||||
// Get the object file name independent of target.
|
||||
std::string objectName = this->GetObjectFileNameWithoutTarget(source);
|
||||
if(nameWithoutTargetDir)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
*nameWithoutTargetDir = objectName;
|
||||
}
|
||||
|
||||
// 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.
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue