summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmLocalGenerator.cxx92
-rw-r--r--Source/cmLocalGenerator.h6
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx47
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx29
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx24
-rw-r--r--Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt20
-rw-r--r--Tests/OutOfSource/OutOfSourceSubdir/simple.cxx5
-rw-r--r--Tests/OutOfSource/OutOfSourceSubdir/simple.cxx.in1
8 files changed, 199 insertions, 25 deletions
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index e20bfe1..71d3c51 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -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 @@ cmLocalGenerator
}
}
+#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 @@ std::string& cmLocalGenerator::CreateSafeUniqueObjectFileName(const char* sin)
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::CreateSafeUniqueObjectFileName(const char* sin)
//----------------------------------------------------------------------------
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 @@ cmLocalGenerator::GetObjectFileNameWithoutTarget(const cmSourceFile& source)
}
// Convert to a safe name.
- return this->CreateSafeUniqueObjectFileName(objectName.c_str());
+ return this->CreateSafeUniqueObjectFileName(objectName.c_str(), dir_len);
}
//----------------------------------------------------------------------------
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index b0d0610..6519889 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -266,8 +266,10 @@ protected:
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();
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 4193293..5dc1384 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -1610,25 +1610,22 @@ cmLocalUnixMakefileGenerator3
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 @@ cmLocalUnixMakefileGenerator3
}
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;
}
//----------------------------------------------------------------------------
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index 6a24b01..3a72de6 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -397,7 +397,32 @@ void cmLocalVisualStudio6Generator
{
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 @@ void cmLocalVisualStudio6Generator
{
objectNameDir =
cmSystemTools::GetFilenamePath(
- this->GetObjectFileNameWithoutTarget(*(*sf)));
+ this->GetObjectFileNameWithoutTarget(*(*sf), dir_len));
}
// Add per-source file flags.
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 100d791..e627f0d 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -1055,6 +1055,28 @@ void cmLocalVisualStudio7Generator
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 @@ void cmLocalVisualStudio7Generator
std::string additionalDeps;
if(this->NeedObjectName.find(*sf) != this->NeedObjectName.end())
{
- objectName = this->GetObjectFileNameWithoutTarget(*(*sf));
+ objectName = this->GetObjectFileNameWithoutTarget(*(*sf), dir_len);
}
else
{
diff --git a/Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt b/Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt
index bbdaa55..4daf425 100644
--- a/Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt
+++ b/Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt
@@ -2,8 +2,26 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
IF ("${PROJECT_SOURCE_DIR}" STREQUAL "${ANOTHER_PROJ_SOURCE_DIR}")
SET(BUILD_SHARED_LIBS 1)
+
+ # Construct a source file outside the tree whose full path is close to
+ # the path length limit. This will cause the full path to the object
+ # file in the build tree to exceed the maximum path length which will
+ # test cmLocalGenerator::CreateSafeUniqueObjectFileName.
+ GET_FILENAME_COMPONENT(DEEPDIR
+ ${OutOfSource_BINARY_DIR}/../OutOfSourceDeep/deeper ABSOLUTE)
+ # MAXPATH = 250 less 25 for /and/deeper/simple.cxx part and small safety
+ MATH(EXPR MAXPATH "250 - 25")
+ STRING(LENGTH "${DEEPDIR}" DEEPDIR_LEN)
+ WHILE("${DEEPDIR_LEN}" LESS "${MAXPATH}")
+ SET(DEEPDIR ${DEEPDIR}/and/deeper)
+ STRING(LENGTH "${DEEPDIR}" DEEPDIR_LEN)
+ ENDWHILE("${DEEPDIR_LEN}" LESS "${MAXPATH}")
+ SET(DEEPSRC ${DEEPDIR}/simple.cxx)
+ STRING(LENGTH "${DEEPSRC}" DEEPSRC_LEN)
+ CONFIGURE_FILE(simple.cxx.in ${DEEPSRC} COPYONLY)
+
ADD_LIBRARY(testlib testlib.cxx)
- ADD_EXECUTABLE (simple simple.cxx ../simple.cxx)
+ ADD_EXECUTABLE (simple simple.cxx ../simple.cxx ${DEEPSRC})
TARGET_LINK_LIBRARIES(simple testlib outlib)
ENDIF ("${PROJECT_SOURCE_DIR}" STREQUAL "${ANOTHER_PROJ_SOURCE_DIR}")
diff --git a/Tests/OutOfSource/OutOfSourceSubdir/simple.cxx b/Tests/OutOfSource/OutOfSourceSubdir/simple.cxx
index 124b7f9..0be7195 100644
--- a/Tests/OutOfSource/OutOfSourceSubdir/simple.cxx
+++ b/Tests/OutOfSource/OutOfSourceSubdir/simple.cxx
@@ -5,6 +5,7 @@
#include "testdp.h"
extern int simple();
+extern int simple2();
extern "C" int outlib();
int main ()
@@ -26,5 +27,9 @@ int main ()
{
return -4;
}
+ if(simple2() != 789)
+ {
+ return -5;
+ }
return 0;
}
diff --git a/Tests/OutOfSource/OutOfSourceSubdir/simple.cxx.in b/Tests/OutOfSource/OutOfSourceSubdir/simple.cxx.in
new file mode 100644
index 0000000..8339b7c
--- /dev/null
+++ b/Tests/OutOfSource/OutOfSourceSubdir/simple.cxx.in
@@ -0,0 +1 @@
+int simple2() { return 789; }