|
|
@@ -5,6 +5,7 @@
|
|
|
#include <algorithm>
|
|
|
#include <atomic>
|
|
|
#include <cstddef>
|
|
|
+#include <limits>
|
|
|
#include <map>
|
|
|
#include <mutex>
|
|
|
#include <set>
|
|
|
@@ -172,6 +173,8 @@ public:
|
|
|
bool MultiConfig = false;
|
|
|
IntegerVersion QtVersion = { 4, 0 };
|
|
|
unsigned int ThreadCount = 0;
|
|
|
+ unsigned int MaxCommandLineLength =
|
|
|
+ std::numeric_limits<unsigned int>::max();
|
|
|
// - Directories
|
|
|
std::string AutogenBuildDir;
|
|
|
std::string AutogenIncludeDir;
|
|
|
@@ -333,6 +336,13 @@ public:
|
|
|
std::vector<std::string> const& command,
|
|
|
std::string const& output) const;
|
|
|
|
|
|
+ /*
|
|
|
+ * Check if command line exceeds maximum length supported by OS
|
|
|
+ * (if on Windows) and switch to using a response file instead.
|
|
|
+ */
|
|
|
+ void MaybeWriteResponseFile(std::string const& outputFile,
|
|
|
+ std::vector<std::string>& cmd) const;
|
|
|
+
|
|
|
/** @brief Run an external process. Use only during Process() call! */
|
|
|
bool RunProcess(GenT genType, cmWorkerPool::ProcessResultT& result,
|
|
|
std::vector<std::string> const& command,
|
|
|
@@ -498,10 +508,6 @@ public:
|
|
|
|
|
|
protected:
|
|
|
ParseCacheT::FileHandleT CacheEntry;
|
|
|
-
|
|
|
- private:
|
|
|
- void MaybeWriteMocResponseFile(std::string const& outputFile,
|
|
|
- std::vector<std::string>& cmd) const;
|
|
|
};
|
|
|
|
|
|
/** uic compiles a file. */
|
|
|
@@ -795,6 +801,51 @@ void cmQtAutoMocUicT::JobT::LogCommandError(
|
|
|
this->Gen()->Log().ErrorCommand(genType, message, command, output);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Check if command line exceeds maximum length supported by OS
|
|
|
+ * (if on Windows) and switch to using a response file instead.
|
|
|
+ */
|
|
|
+void cmQtAutoMocUicT::JobT::MaybeWriteResponseFile(
|
|
|
+ std::string const& outputFile, std::vector<std::string>& cmd) const
|
|
|
+{
|
|
|
+#ifdef _WIN32
|
|
|
+ // Ensure cmd is less than CommandLineLengthMax characters
|
|
|
+ size_t commandLineLength = cmd.size(); // account for separating spaces
|
|
|
+ for (std::string const& str : cmd) {
|
|
|
+ commandLineLength += str.length();
|
|
|
+ }
|
|
|
+ if (commandLineLength >= this->BaseConst().MaxCommandLineLength) {
|
|
|
+ // Command line exceeds maximum size allowed by OS
|
|
|
+ // => create response file
|
|
|
+ std::string const responseFile = cmStrCat(outputFile, ".rsp");
|
|
|
+
|
|
|
+ cmsys::ofstream fout(responseFile.c_str());
|
|
|
+ if (!fout) {
|
|
|
+ this->LogError(
|
|
|
+ GenT::MOC,
|
|
|
+ cmStrCat("AUTOMOC was unable to create a response file at\n ",
|
|
|
+ this->MessagePath(responseFile)));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ auto it = cmd.begin();
|
|
|
+ while (++it != cmd.end()) {
|
|
|
+ fout << *it << "\n";
|
|
|
+ }
|
|
|
+ fout.close();
|
|
|
+
|
|
|
+ // Keep all but executable
|
|
|
+ cmd.resize(1);
|
|
|
+
|
|
|
+ // Specify response file
|
|
|
+ cmd.emplace_back(cmStrCat('@', responseFile));
|
|
|
+ }
|
|
|
+#else
|
|
|
+ static_cast<void>(outputFile);
|
|
|
+ static_cast<void>(cmd);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
bool cmQtAutoMocUicT::JobT::RunProcess(GenT genType,
|
|
|
cmWorkerPool::ProcessResultT& result,
|
|
|
std::vector<std::string> const& command,
|
|
|
@@ -836,6 +887,8 @@ void cmQtAutoMocUicT::JobMocPredefsT::Process()
|
|
|
cm::append(cmd, this->MocConst().OptionsDefinitions);
|
|
|
// Add includes
|
|
|
cm::append(cmd, this->MocConst().OptionsIncludes);
|
|
|
+ // Check if response file is necessary
|
|
|
+ MaybeWriteResponseFile(this->MocConst().PredefsFileAbs, cmd);
|
|
|
// Execute command
|
|
|
if (!this->RunProcess(GenT::MOC, result, cmd, reason.get())) {
|
|
|
this->LogCommandError(GenT::MOC,
|
|
|
@@ -2034,7 +2087,7 @@ void cmQtAutoMocUicT::JobCompileMocT::Process()
|
|
|
// Add source file
|
|
|
cmd.push_back(sourceFile);
|
|
|
|
|
|
- MaybeWriteMocResponseFile(outputFile, cmd);
|
|
|
+ MaybeWriteResponseFile(outputFile, cmd);
|
|
|
}
|
|
|
|
|
|
// Execute moc command
|
|
|
@@ -2080,51 +2133,6 @@ void cmQtAutoMocUicT::JobCompileMocT::Process()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Check if command line exceeds maximum length supported by OS
|
|
|
- * (if on Windows) and switch to using a response file instead.
|
|
|
- */
|
|
|
-void cmQtAutoMocUicT::JobCompileMocT::MaybeWriteMocResponseFile(
|
|
|
- std::string const& outputFile, std::vector<std::string>& cmd) const
|
|
|
-{
|
|
|
-#ifdef _WIN32
|
|
|
- // Ensure cmd is less than CommandLineLengthMax characters
|
|
|
- size_t commandLineLength = cmd.size(); // account for separating spaces
|
|
|
- for (std::string const& str : cmd) {
|
|
|
- commandLineLength += str.length();
|
|
|
- }
|
|
|
- if (commandLineLength >= CommandLineLengthMax) {
|
|
|
- // Command line exceeds maximum size allowed by OS
|
|
|
- // => create response file
|
|
|
- std::string const responseFile = cmStrCat(outputFile, ".rsp");
|
|
|
-
|
|
|
- cmsys::ofstream fout(responseFile.c_str());
|
|
|
- if (!fout) {
|
|
|
- this->LogError(
|
|
|
- GenT::MOC,
|
|
|
- cmStrCat("AUTOMOC was unable to create a response file at\n ",
|
|
|
- this->MessagePath(responseFile)));
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- auto it = cmd.begin();
|
|
|
- while (++it != cmd.end()) {
|
|
|
- fout << *it << "\n";
|
|
|
- }
|
|
|
- fout.close();
|
|
|
-
|
|
|
- // Keep all but executable
|
|
|
- cmd.resize(1);
|
|
|
-
|
|
|
- // Specify response file
|
|
|
- cmd.emplace_back(cmStrCat('@', responseFile));
|
|
|
- }
|
|
|
-#else
|
|
|
- static_cast<void>(outputFile);
|
|
|
- static_cast<void>(cmd);
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
void cmQtAutoMocUicT::JobCompileUicT::Process()
|
|
|
{
|
|
|
std::string const& sourceFile = this->Mapping->SourceFile->FileName;
|
|
|
@@ -2377,6 +2385,10 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
|
|
|
!info.GetUInt("QT_VERSION_MINOR", this->BaseConst_.QtVersion.Minor,
|
|
|
true) ||
|
|
|
!info.GetUInt("PARALLEL", this->BaseConst_.ThreadCount, false) ||
|
|
|
+#ifdef _WIN32
|
|
|
+ !info.GetUInt("AUTOGEN_COMMAND_LINE_LENGTH_MAX",
|
|
|
+ this->BaseConst_.MaxCommandLineLength, false) ||
|
|
|
+#endif
|
|
|
!info.GetString("BUILD_DIR", this->BaseConst_.AutogenBuildDir, true) ||
|
|
|
!info.GetStringConfig("INCLUDE_DIR", this->BaseConst_.AutogenIncludeDir,
|
|
|
true) ||
|