summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorChristian Pfeiffer <cpfeiffer@live.de>2017-04-18 21:06:39 (GMT)
committerBrad King <brad.king@kitware.com>2017-04-19 15:02:24 (GMT)
commitbbb5c3efe2a17d046506b7c27008c77ea244f0bc (patch)
treeefa83801c7982bd247727af35fa6e7f15a13aedc /Source
parentddd2b02455db9b0ef3604af1b9b10c22af56bff9 (diff)
downloadCMake-bbb5c3efe2a17d046506b7c27008c77ea244f0bc.zip
CMake-bbb5c3efe2a17d046506b7c27008c77ea244f0bc.tar.gz
CMake-bbb5c3efe2a17d046506b7c27008c77ea244f0bc.tar.bz2
Ninja,Makefile: Unify command line limit logic
Move the logic to cmSystemTools to be shared among the generators. Revise the implementation and add comments justifying each possible source for a limit.
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx2
-rw-r--r--Source/cmMakefileTargetGenerator.cxx15
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx46
-rw-r--r--Source/cmSystemTools.cxx40
-rw-r--r--Source/cmSystemTools.h2
5 files changed, 50 insertions, 55 deletions
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index aae01ca..a95d4ee 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -246,7 +246,7 @@ void cmGlobalNinjaGenerator::WriteBuild(
bool useResponseFile = false;
if (cmdLineLimit < 0 ||
(cmdLineLimit > 0 &&
- (args.size() + buildstr.size() + assignments.size()) >
+ (args.size() + buildstr.size() + assignments.size() + 1000) >
static_cast<size_t>(cmdLineLimit))) {
variable_assignments.str(std::string());
cmGlobalNinjaGenerator::WriteVariable(variable_assignments, "RSP_FILE",
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index ed38024..dd5cd7d 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -30,10 +30,6 @@
#include "cm_auto_ptr.hxx"
#include "cmake.h"
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-
cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target)
: cmCommonTargetGenerator(target)
, OSXBundleGenerator(CM_NULLPTR)
@@ -1492,15 +1488,6 @@ 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
{
@@ -1514,7 +1501,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
}
// Check for a system limit.
- if (size_t const limit = calculateCommandLineLengthLimit()) {
+ if (size_t const limit = cmSystemTools::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 CMAKE_CURRENT_BINARY_DIR like the final list will be, so the
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index aaeb659..edab2ba 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -5,11 +5,9 @@
#include <algorithm>
#include <assert.h>
#include <iterator>
-#include <limits>
#include <map>
#include <set>
#include <sstream>
-#include <stddef.h>
#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
@@ -35,10 +33,6 @@
#include "cm_auto_ptr.hxx"
#include "cmake.h"
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-
cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator(
cmGeneratorTarget* target)
: cmNinjaTargetGenerator(target)
@@ -546,36 +540,6 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
return std::vector<std::string>();
}
-static int calculateCommandLineLengthLimit(int linkRuleLength)
-{
- static int const limits[] = {
-#ifdef _WIN32
- 8000,
-#endif
-#if defined(__linux)
- // #define MAX_ARG_STRLEN (PAGE_SIZE * 32) in Linux's binfmts.h
- ((int)sysconf(_SC_PAGESIZE) * 32) - 1000,
-#endif
- std::numeric_limits<int>::max()
- };
-
- size_t const arrSz = cmArraySize(limits);
- int sz = *std::min_element(limits, limits + arrSz);
-#if defined(_SC_ARG_MAX)
- // for instance ARG_MAX is 2096152 on Ubuntu or 262144 on Mac
- int const szArgMax = static_cast<int>(sysconf(_SC_ARG_MAX));
- // a return value of -1 signifies an unrestricted value
- if (szArgMax != -1) {
- sz = std::min(sz, szArgMax - 1000);
- }
-#endif
- if (sz == std::numeric_limits<int>::max()) {
- return 0;
- }
-
- return sz - linkRuleLength;
-}
-
void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
{
cmGeneratorTarget& genTarget = *this->GetGeneratorTarget();
@@ -761,8 +725,9 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
// Device linking currently doesn't support response files so
// do not check if the user has explicitly forced a response file.
- int const commandLineLengthLimit = calculateCommandLineLengthLimit(
- globalGen.GetRuleCmdLength(this->LanguageLinkerDeviceRule()));
+ int const commandLineLengthLimit =
+ static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) -
+ globalGen.GetRuleCmdLength(this->LanguageLinkerDeviceRule());
const std::string rspfile =
std::string(cmake::GetCMakeFilesDirectoryPostSlash()) +
@@ -1048,8 +1013,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
!(this->TargetLinkLanguage == "RC" || this->TargetLinkLanguage == "CUDA");
int commandLineLengthLimit = -1;
if (!lang_supports_response || !this->ForceResponseFile()) {
- commandLineLengthLimit = calculateCommandLineLengthLimit(
- globalGen.GetRuleCmdLength(this->LanguageLinkerRule()));
+ commandLineLengthLimit =
+ static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) -
+ globalGen.GetRuleCmdLength(this->LanguageLinkerRule());
}
const std::string rspfile =
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 8dc6571..f4de125 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -570,6 +570,46 @@ std::vector<std::string> cmSystemTools::ParseArguments(const char* command)
return args;
}
+size_t cmSystemTools::CalculateCommandLineLengthLimit()
+{
+ size_t sz =
+#ifdef _WIN32
+ // There's a maximum of 65536 bytes and thus 32768 WCHARs on Windows
+ // However, cmd.exe itself can only handle 8191 WCHARs and Ninja for
+ // example uses it to spawn processes.
+ size_t(8191);
+#elif defined(__linux)
+ // MAX_ARG_STRLEN is the maximum length of a string permissible for
+ // the execve() syscall on Linux. It's defined as (PAGE_SIZE * 32)
+ // in Linux's binfmts.h
+ static_cast<size_t>(sysconf(_SC_PAGESIZE) * 32);
+#else
+ size_t(0);
+#endif
+
+#if defined(_SC_ARG_MAX)
+ // ARG_MAX is the maximum size of the command and environment
+ // that can be passed to the exec functions on UNIX.
+ // The value in limits.h does not need to be present and may
+ // depend upon runtime memory constraints, hence sysconf()
+ // should be used to query it.
+ long szArgMax = sysconf(_SC_ARG_MAX);
+ // A return value of -1 signifies an undetermined limit, but
+ // it does not imply an infinite limit, and thus is ignored.
+ if (szArgMax != -1) {
+ // We estimate the size of the environment block to be 1000.
+ // This isn't accurate at all, but leaves some headroom.
+ szArgMax = szArgMax < 1000 ? 0 : szArgMax - 1000;
+#if defined(_WIN32) || defined(__linux)
+ sz = std::min(sz, static_cast<size_t>(szArgMax));
+#else
+ sz = static_cast<size_t>(szArgMax);
+#endif
+ }
+#endif
+ return sz;
+}
+
bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
std::string* captureStdOut,
std::string* captureStdErr, int* retVal,
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 86d92be..a8a9995 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -253,6 +253,8 @@ public:
static void ParseUnixCommandLine(const char* command,
std::vector<std::string>& args);
+ static size_t CalculateCommandLineLengthLimit();
+
static void EnableMessages() { s_DisableMessages = false; }
static void DisableMessages() { s_DisableMessages = true; }
static void DisableRunCommandOutput() { s_DisableRunCommandOutput = true; }