diff options
author | Brad King <brad.king@kitware.com> | 2016-07-21 15:27:31 (GMT) |
---|---|---|
committer | CMake Topic Stage <kwrobot@kitware.com> | 2016-07-21 15:27:31 (GMT) |
commit | dbc0ec1648b493b237efd704bec38c757b6da5a5 (patch) | |
tree | 33a000928b0abfb6e7f06cbbf073403bb21c2d2d /Source | |
parent | 850764fc701ce9e1190d5bb20af97ec511763f0b (diff) | |
parent | c7a7c655f0433c7ca4ea6ec5ce78b7f17cbf5140 (diff) | |
download | CMake-dbc0ec1648b493b237efd704bec38c757b6da5a5.zip CMake-dbc0ec1648b493b237efd704bec38c757b6da5a5.tar.gz CMake-dbc0ec1648b493b237efd704bec38c757b6da5a5.tar.bz2 |
Merge topic 'makefile-response-files'
c7a7c655 Makefile: Avoid link line object list lengths nearing system limits
34ba5c53 Makefile: Factor out response file checks into common helper
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmMakefileExecutableTargetGenerator.cxx | 25 | ||||
-rw-r--r-- | Source/cmMakefileLibraryTargetGenerator.cxx | 25 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.cxx | 71 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.h | 3 |
4 files changed, 82 insertions, 42 deletions
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 8730ccd..3b8bf5a 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -277,27 +277,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) } } - // Select whether to use a response file for objects. - bool useResponseFileForObjects = false; - { - std::string responseVar = "CMAKE_"; - responseVar += linkLanguage; - responseVar += "_USE_RESPONSE_FILE_FOR_OBJECTS"; - if (this->Makefile->IsOn(responseVar)) { - useResponseFileForObjects = true; - } - } - - // Select whether to use a response file for libraries. - bool useResponseFileForLibs = false; - { - std::string responseVar = "CMAKE_"; - responseVar += linkLanguage; - responseVar += "_USE_RESPONSE_FILE_FOR_LIBRARIES"; - if (this->Makefile->IsOn(responseVar)) { - useResponseFileForLibs = true; - } - } + bool useResponseFileForObjects = + this->CheckUseResponseFileForObjects(linkLanguage); + bool const useResponseFileForLibs = + this->CheckUseResponseFileForLibraries(linkLanguage); // Expand the rule variables. { diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 7de2db0..68f8ff1 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -429,27 +429,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Determine whether a link script will be used. bool useLinkScript = this->GlobalGenerator->GetUseLinkScript(); - // Select whether to use a response file for objects. - bool useResponseFileForObjects = false; - { - std::string responseVar = "CMAKE_"; - responseVar += linkLanguage; - responseVar += "_USE_RESPONSE_FILE_FOR_OBJECTS"; - if (this->Makefile->IsOn(responseVar)) { - useResponseFileForObjects = true; - } - } - - // Select whether to use a response file for libraries. - bool useResponseFileForLibs = false; - { - std::string responseVar = "CMAKE_"; - responseVar += linkLanguage; - responseVar += "_USE_RESPONSE_FILE_FOR_LIBRARIES"; - if (this->Makefile->IsOn(responseVar)) { - useResponseFileForLibs = true; - } - } + bool useResponseFileForObjects = + this->CheckUseResponseFileForObjects(linkLanguage); + bool const useResponseFileForLibs = + this->CheckUseResponseFileForLibraries(linkLanguage); // For static libraries there might be archiving rules. bool haveStaticLibraryRule = false; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 00b1219..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,73 @@ 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 +{ + // Check for an explicit setting one way or the other. + std::string const responseVar = + "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_OBJECTS"; + if (const char* val = this->Makefile->GetDefinition(responseVar)) { + if (*val) { + return cmSystemTools::IsOn(val); + } + } + + // 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; +} + +bool cmMakefileTargetGenerator::CheckUseResponseFileForLibraries( + std::string const& l) const +{ + // Check for an explicit setting one way or the other. + std::string const responseVar = + "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_LIBRARIES"; + if (const char* val = this->Makefile->GetDefinition(responseVar)) { + if (*val) { + return cmSystemTools::IsOn(val); + } + } + + // We do not need a response file for libraries. + return false; +} + std::string cmMakefileTargetGenerator::CreateResponseFile( const char* name, std::string const& options, std::vector<std::string>& makefile_depends) diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 4284549..29b8887 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -151,6 +151,9 @@ protected: std::string CreateResponseFile(const char* name, std::string const& options, std::vector<std::string>& makefile_depends); + bool CheckUseResponseFileForObjects(std::string const& l) const; + bool CheckUseResponseFileForLibraries(std::string const& l) const; + /** Create list of flags for link libraries. */ void CreateLinkLibs(std::string& linkLibs, bool relink, bool useResponseFile, std::vector<std::string>& makefile_depends, |