diff options
author | Brad King <brad.king@kitware.com> | 2016-07-20 18:57:18 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2016-07-20 19:09:42 (GMT) |
commit | c7a7c655f0433c7ca4ea6ec5ce78b7f17cbf5140 (patch) | |
tree | 7478635923e7b793ec4f875f44ab4dea1b476fc4 | |
parent | 34ba5c53481e7f2101dafa735504cb98f94ec6db (diff) | |
download | CMake-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.cxx | 39 |
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; } |