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.
This commit is contained in:
Brad King 2016-07-20 14:57:18 -04:00
parent 34ba5c5348
commit c7a7c655f0
1 changed files with 39 additions and 0 deletions

View File

@ -31,6 +31,10 @@
#include <ctype.h> #include <ctype.h>
#ifndef _WIN32
#include <unistd.h>
#endif
cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target) cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target)
: cmCommonTargetGenerator(target) : cmCommonTargetGenerator(target)
, OSXBundleGenerator(CM_NULLPTR) , OSXBundleGenerator(CM_NULLPTR)
@ -1447,6 +1451,15 @@ void cmMakefileTargetGenerator::CreateLinkScript(
makefile_depends.push_back(linkScriptName); 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( bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
std::string const& l) const 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. // We do not need a response file for objects.
return false; return false;
} }