diff options
author | Brad King <brad.king@kitware.com> | 2017-04-21 12:51:42 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2017-04-21 12:51:49 (GMT) |
commit | 718daeb4e6b93527ea8fa0b87091008737b0a897 (patch) | |
tree | 954f79f4e7808943a0954add77a80ea1eec1a316 | |
parent | b5a5b227f9a3d88e1c493427e3983aee28c284eb (diff) | |
parent | bbb5c3efe2a17d046506b7c27008c77ea244f0bc (diff) | |
download | CMake-718daeb4e6b93527ea8fa0b87091008737b0a897.zip CMake-718daeb4e6b93527ea8fa0b87091008737b0a897.tar.gz CMake-718daeb4e6b93527ea8fa0b87091008737b0a897.tar.bz2 |
Merge topic 'unified-commandline-length'
bbb5c3ef Ninja,Makefile: Unify command line limit logic
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !705
-rw-r--r-- | Source/cmGlobalNinjaGenerator.cxx | 2 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.cxx | 15 | ||||
-rw-r--r-- | Source/cmNinjaNormalTargetGenerator.cxx | 46 | ||||
-rw-r--r-- | Source/cmSystemTools.cxx | 40 | ||||
-rw-r--r-- | Source/cmSystemTools.h | 2 |
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 7ace0a3..39625ae 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; } |