summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2016-07-20 18:57:18 (GMT)
committerBrad King <brad.king@kitware.com>2016-07-20 19:09:42 (GMT)
commitc7a7c655f0433c7ca4ea6ec5ce78b7f17cbf5140 (patch)
tree7478635923e7b793ec4f875f44ab4dea1b476fc4
parent34ba5c53481e7f2101dafa735504cb98f94ec6db (diff)
downloadCMake-c7a7c655f0433c7ca4ea6ec5ce78b7f17cbf5140.zip
CMake-c7a7c655f0433c7ca4ea6ec5ce78b7f17cbf5140.tar.gz
CMake-c7a7c655f0433c7ca4ea6ec5ce78b7f17cbf5140.tar.bz2
Makefile: Avoid link line object list lengths nearing system limits
Use response files for object file lists that approach the scale of the system `ARG_MAX` limit. Fixes #16206.
-rw-r--r--Source/cmMakefileTargetGenerator.cxx39
1 files changed, 39 insertions, 0 deletions
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index abf50d6..e12fc09 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -31,6 +31,10 @@
#include <ctype.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target)
: cmCommonTargetGenerator(target)
, OSXBundleGenerator(CM_NULLPTR)
@@ -1447,6 +1451,15 @@ void cmMakefileTargetGenerator::CreateLinkScript(
makefile_depends.push_back(linkScriptName);
}
+static size_t calculateCommandLineLengthLimit()
+{
+#if defined(_SC_ARG_MAX)
+ return ((size_t)sysconf(_SC_ARG_MAX)) - 1000;
+#else
+ return 0;
+#endif
+}
+
bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
std::string const& l) const
{
@@ -1459,6 +1472,32 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
}
}
+ // Check for a system limit.
+ if (size_t const limit = calculateCommandLineLengthLimit()) {
+ // Compute the total length of our list of object files with room
+ // for argument separation and quoting. This does not convert paths
+ // relative to START_OUTPUT like the final list will be, so the actual
+ // list will likely be much shorter than this. However, in the worst
+ // case all objects will remain as absolute paths.
+ size_t length = 0;
+ for (std::vector<std::string>::const_iterator i = this->Objects.begin();
+ i != this->Objects.end(); ++i) {
+ length += i->size() + 3;
+ }
+ for (std::vector<std::string>::const_iterator i =
+ this->ExternalObjects.begin();
+ i != this->ExternalObjects.end(); ++i) {
+ length += i->size() + 3;
+ }
+
+ // We need to guarantee room for both objects and libraries, so
+ // if the objects take up more than half then use a response file
+ // for them.
+ if (length > (limit / 2)) {
+ return true;
+ }
+ }
+
// We do not need a response file for objects.
return false;
}