[cmake-commits] king committed cmLocalGenerator.cxx 1.204 1.205
cmLocalGenerator.h 1.77 1.78 cmLocalUnixMakefileGenerator3.cxx
1.201 1.202 cmLocalVisualStudio6Generator.cxx 1.117 1.118
cmLocalVisualStudio7Generator.cxx 1.182 1.183
cmake-commits at cmake.org
cmake-commits at cmake.org
Fri Mar 16 09:34:27 EST 2007
Update of /cvsroot/CMake/CMake/Source
In directory public:/mounts/ram/cvs-serv30235/Source
Modified Files:
cmLocalGenerator.cxx cmLocalGenerator.h
cmLocalUnixMakefileGenerator3.cxx
cmLocalVisualStudio6Generator.cxx
cmLocalVisualStudio7Generator.cxx
Log Message:
ENH: Added computation of object file names that are almost always short enough to not exceed the filesystem path length limitation. This is useful when a source file from outside the tree is referenced with a long full path. The object file name previously would contain the entire path which when combined with the build output directory could exceed the filesystem limit. Now CMake recognizes this case and replaces enough of the beginning of the full path to the source file with an md5sum of the replaced portion to make the name fit on disk. This addresses bug#4520.
Index: cmLocalVisualStudio7Generator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmLocalVisualStudio7Generator.cxx,v
retrieving revision 1.182
retrieving revision 1.183
diff -u -d -r1.182 -r1.183
--- cmLocalVisualStudio7Generator.cxx 14 Mar 2007 20:29:10 -0000 1.182
+++ cmLocalVisualStudio7Generator.cxx 16 Mar 2007 14:34:25 -0000 1.183
@@ -1055,6 +1055,28 @@
this->WriteVCProjBeginGroup(fout, name.c_str(), "");
}
+ // Compute the maximum length of a configuration name.
+ std::string::size_type config_len_max = 0;
+ for(std::vector<std::string>::iterator i = configs->begin();
+ i != configs->end(); ++i)
+ {
+ if(i->size() > config_len_max)
+ {
+ config_len_max = i->size();
+ }
+ }
+
+ // Compute the maximum length of the 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::size_type dir_len = 0;
+ dir_len += strlen(this->Makefile->GetCurrentOutputDirectory());
+ dir_len += 1;
+ dir_len += this->GetTargetDirectory(target).size();
+ dir_len += 1;
+ dir_len += config_len_max;
+ dir_len += 1;
+
// Loop through each source in the source group.
std::string objectName;
for(std::vector<const cmSourceFile *>::const_iterator sf =
@@ -1066,7 +1088,7 @@
std::string additionalDeps;
if(this->NeedObjectName.find(*sf) != this->NeedObjectName.end())
{
- objectName = this->GetObjectFileNameWithoutTarget(*(*sf));
+ objectName = this->GetObjectFileNameWithoutTarget(*(*sf), dir_len);
}
else
{
Index: cmLocalGenerator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmLocalGenerator.h,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -d -r1.77 -r1.78
--- cmLocalGenerator.h 12 Mar 2007 14:26:59 -0000 1.77
+++ cmLocalGenerator.h 16 Mar 2007 14:34:25 -0000 1.78
@@ -266,8 +266,10 @@
std::vector<std::string> const& configurationTypes);
// Compute object file names.
- std::string GetObjectFileNameWithoutTarget(const cmSourceFile& source);
- std::string& CreateSafeUniqueObjectFileName(const char* sin);
+ std::string GetObjectFileNameWithoutTarget(const cmSourceFile& source,
+ std::string::size_type dir_len);
+ std::string& CreateSafeUniqueObjectFileName(const char* sin,
+ std::string::size_type dir_len);
void ConfigureRelativePaths();
std::string FindRelativePathTopSource();
Index: cmLocalUnixMakefileGenerator3.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmLocalUnixMakefileGenerator3.cxx,v
retrieving revision 1.201
retrieving revision 1.202
diff -u -d -r1.201 -r1.202
--- cmLocalUnixMakefileGenerator3.cxx 14 Mar 2007 20:29:10 -0000 1.201
+++ cmLocalUnixMakefileGenerator3.cxx 16 Mar 2007 14:34:25 -0000 1.202
@@ -1610,25 +1610,22 @@
const cmSourceFile& source,
std::string* nameWithoutTargetDir)
{
- // Get the object file name independent of target.
- std::string objectName = this->GetObjectFileNameWithoutTarget(source);
- if(nameWithoutTargetDir)
- {
- *nameWithoutTargetDir = objectName;
- }
-
- // Prepend the target directory.
- std::string obj;
- const char* fileTargetDirectory =
- source.GetProperty("MACOSX_PACKAGE_LOCATION");
- if ( fileTargetDirectory )
+ if(const char* fileTargetDirectory =
+ source.GetProperty("MACOSX_PACKAGE_LOCATION"))
{
+ // Special handling for OSX package files.
+ std::string objectName = this->GetObjectFileNameWithoutTarget(source, 0);
+ if(nameWithoutTargetDir)
+ {
+ *nameWithoutTargetDir = objectName;
+ }
objectName = cmSystemTools::GetFilenameName(objectName.c_str());
std::string targetName;
std::string targetNameReal;
std::string targetNamePDB;
target.GetExecutableNames(targetName, targetNameReal,
targetNamePDB, this->ConfigurationName.c_str());
+ std::string obj;
if ( target.GetPropertyAsBool("MACOSX_BUNDLE") )
{
// Construct the full path version of the names.
@@ -1644,14 +1641,32 @@
}
obj = cmSystemTools::RelativePath
(this->Makefile->GetHomeOutputDirectory(), obj.c_str());
+ obj += "/";
+ obj += objectName;
+ return obj;
}
else
{
- obj = this->GetTargetDirectory(target);
+ // Start with the target directory.
+ std::string obj = this->GetTargetDirectory(target);
+ obj += "/";
+
+ // Get the object file name without the target directory.
+ std::string::size_type dir_len = 0;
+ dir_len += strlen(this->Makefile->GetCurrentOutputDirectory());
+ dir_len += 1;
+ dir_len += obj.size();
+ std::string objectName =
+ this->GetObjectFileNameWithoutTarget(source, dir_len);
+ if(nameWithoutTargetDir)
+ {
+ *nameWithoutTargetDir = objectName;
+ }
+
+ // Append the object name to the target directory.
+ obj += objectName;
+ return obj;
}
- obj += "/";
- obj += objectName;
- return obj;
}
//----------------------------------------------------------------------------
Index: cmLocalVisualStudio6Generator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmLocalVisualStudio6Generator.cxx,v
retrieving revision 1.117
retrieving revision 1.118
diff -u -d -r1.117 -r1.118
--- cmLocalVisualStudio6Generator.cxx 10 Mar 2007 11:56:11 -0000 1.117
+++ cmLocalVisualStudio6Generator.cxx 16 Mar 2007 14:34:25 -0000 1.118
@@ -397,7 +397,32 @@
{
this->WriteDSPBeginGroup(fout, name.c_str(), "");
}
-
+
+ // Compute the maximum length of a configuration name.
+ std::string::size_type config_len_max = 0;
+ 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 = *i;
+ std::string::size_type pos = config.find_last_of(" ");
+ config = config.substr(pos+1, std::string::npos);
+ config = config.substr(0, config.size()-1);
+ if(config.size() > config_len_max)
+ {
+ config_len_max = config.size();
+ }
+ }
+
+ // Compute the maximum length of the 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::size_type dir_len = 0;
+ dir_len += strlen(this->Makefile->GetCurrentOutputDirectory());
+ dir_len += 1;
+ dir_len += config_len_max;
+ dir_len += 1;
+
// Loop through each source in the source group.
for(std::vector<const cmSourceFile *>::const_iterator sf =
sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
@@ -412,7 +437,7 @@
{
objectNameDir =
cmSystemTools::GetFilenamePath(
- this->GetObjectFileNameWithoutTarget(*(*sf)));
+ this->GetObjectFileNameWithoutTarget(*(*sf), dir_len));
}
// Add per-source file flags.
Index: cmLocalGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmLocalGenerator.cxx,v
retrieving revision 1.204
retrieving revision 1.205
diff -u -d -r1.204 -r1.205
--- cmLocalGenerator.cxx 14 Mar 2007 20:29:10 -0000 1.204
+++ cmLocalGenerator.cxx 16 Mar 2007 14:34:25 -0000 1.205
@@ -28,6 +28,11 @@
#include "cmTest.h"
#include "cmake.h"
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+# define CM_LG_ENCODE_OBJECT_NAMES
+# include <cmsys/MD5.h>
+#endif
+
#include <cmsys/System.h>
#include <ctype.h> // for isalpha
@@ -2376,8 +2381,81 @@
}
}
+#if defined(CM_LG_ENCODE_OBJECT_NAMES)
+static std::string cmLocalGeneratorMD5(const char* input)
+{
+ char md5out[32];
+ cmsysMD5* md5 = cmsysMD5_New();
+ cmsysMD5_Initialize(md5);
+ cmsysMD5_Append(md5, reinterpret_cast<unsigned char const*>(input), -1);
+ cmsysMD5_FinalizeHex(md5, md5out);
+ cmsysMD5_Delete(md5);
+ return std::string(md5out, 32);
+}
+
+static bool
+cmLocalGeneratorShortenObjectName(std::string& objName,
+ std::string::size_type max_len)
+{
+ // Replace the beginning of the path portion of the object name with
+ // its own md5 sum.
+ std::string::size_type pos = objName.find('/', objName.size()-max_len+32);
+ if(pos != objName.npos)
+ {
+ std::string md5name = cmLocalGeneratorMD5(objName.substr(0, pos).c_str());
+ md5name += objName.substr(pos);
+ objName = md5name;
+
+ // The object name is now short enough.
+ return true;
+ }
+ else
+ {
+ // The object name could not be shortened enough.
+ return false;
+ }
+}
+
+static bool cmLocalGeneratorCheckObjectName(std::string& objName,
+ std::string::size_type dir_len)
+{
+ // Choose a maximum file name length.
+#if defined(_WIN32) || defined(__CYGWIN__)
+ std::string::size_type const max_total_len = 250;
+#else
+ std::string::size_type const max_total_len = 1000;
+#endif
+
+ // Enforce the maximum file name length if possible.
+ std::string::size_type max_obj_len = max_total_len;
+ if(dir_len < max_total_len)
+ {
+ max_obj_len = max_total_len - dir_len;
+ if(objName.size() > max_obj_len)
+ {
+ // The current object file name is too long. Try to shorten it.
+ return cmLocalGeneratorShortenObjectName(objName, max_obj_len);
+ }
+ else
+ {
+ // The object file name is short enough.
+ return true;
+ }
+ }
+ else
+ {
+ // The build directory in which the object will be stored is
+ // already too deep.
+ return false;
+ }
+}
+#endif
+
//----------------------------------------------------------------------------
-std::string& cmLocalGenerator::CreateSafeUniqueObjectFileName(const char* sin)
+std::string&
+cmLocalGenerator
+::CreateSafeUniqueObjectFileName(const char* sin,
+ std::string::size_type dir_len)
{
// Look for an existing mapped name for this object file.
std::map<cmStdString,cmStdString>::iterator it =
@@ -2435,6 +2513,12 @@
while ( !done );
}
+#if defined(CM_LG_ENCODE_OBJECT_NAMES)
+ cmLocalGeneratorCheckObjectName(ssin, dir_len);
+#else
+ (void)dir_len;
+#endif
+
// Insert the newly mapped object file name.
std::map<cmStdString, cmStdString>::value_type e(sin, ssin);
it = this->UniqueObjectNamesMap.insert(e).first;
@@ -2446,7 +2530,9 @@
//----------------------------------------------------------------------------
std::string
-cmLocalGenerator::GetObjectFileNameWithoutTarget(const cmSourceFile& source)
+cmLocalGenerator
+::GetObjectFileNameWithoutTarget(const cmSourceFile& source,
+ std::string::size_type dir_len)
{
// Construct the object file name using the full path to the source
// file which is its only unique identification.
@@ -2517,7 +2603,7 @@
}
// Convert to a safe name.
- return this->CreateSafeUniqueObjectFileName(objectName.c_str());
+ return this->CreateSafeUniqueObjectFileName(objectName.c_str(), dir_len);
}
//----------------------------------------------------------------------------
More information about the Cmake-commits
mailing list