diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 1a77d7ce0a..587e18a081 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -1842,10 +1842,14 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( int cmcmd_cmake_ninja_dyndep(std::vector::const_iterator argBeg, std::vector::const_iterator argEnd) { + std::vector arg_full = + cmSystemTools::HandleResponseFile(argBeg, argEnd); + std::string arg_dd; std::string arg_tdi; std::vector arg_ddis; - for (std::vector::const_iterator a = argBeg; a != argEnd; ++a) { + for (std::vector::const_iterator a = arg_full.begin(); + a != arg_full.end(); ++a) { std::string const& arg = *a; if (cmHasLiteralPrefix(arg, "--tdi=")) { arg_tdi = arg.substr(6); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index e0b2217b78..7e29681d60 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -557,13 +557,26 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) // Write the rule for ninja dyndep file generation. std::vector ddCmds; +#ifdef _WIN32 + // Windows command line length is limited -> use response file for dyndep + // rules + std::string ddRspFile = "$out.rsp"; + std::string ddRspContent = "$in"; + std::string ddInput = "@" + ddRspFile; +#else + std::string ddRspFile; + std::string ddRspContent; + std::string ddInput = "$in"; +#endif + // Run CMake dependency scanner on preprocessed output. std::string const cmake = this->GetLocalGenerator()->ConvertToOutputFormat( cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); ddCmds.push_back(cmake + " -E cmake_ninja_dyndep" " --tdi=" + tdi + " --dd=$out" - " $in"); + " " + + ddInput); std::string const ddCmdLine = this->GetLocalGenerator()->BuildCommandLine(ddCmds); @@ -575,9 +588,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) this->GetGlobalGenerator()->AddRule( this->LanguageDyndepRule(lang), ddCmdLine, ddDesc.str(), ddComment.str(), /*depfile*/ "", - /*deps*/ "", - /*rspfile*/ "", - /*rspcontent*/ "", + /*deps*/ "", ddRspFile, ddRspContent, /*restat*/ "", /*generator*/ false); } diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 6d620d9f0f..8978e1855c 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -505,6 +505,39 @@ void cmSystemTools::ParseUnixCommandLine(const char* command, argv.Store(args); } +std::vector cmSystemTools::HandleResponseFile( + std::vector::const_iterator argBeg, + std::vector::const_iterator argEnd) +{ + std::vector arg_full; + for (std::vector::const_iterator a = argBeg; a != argEnd; ++a) { + std::string const& arg = *a; + if (cmHasLiteralPrefix(arg, "@")) { + cmsys::ifstream responseFile(arg.substr(1).c_str(), std::ios::in); + if (!responseFile) { + std::string error = "failed to open for reading ("; + error += cmSystemTools::GetLastSystemError(); + error += "):\n "; + error += arg.substr(1); + cmSystemTools::Error(error.c_str()); + } else { + std::string line; + cmSystemTools::GetLineFromStream(responseFile, line); + std::vector args2; +#ifdef _WIN32 + cmSystemTools::ParseWindowsCommandLine(line.c_str(), args2); +#else + cmSystemTools::ParseUnixCommandLine(line.c_str(), args2); +#endif + arg_full.insert(arg_full.end(), args2.begin(), args2.end()); + } + } else { + arg_full.push_back(arg); + } + } + return arg_full; +} + std::vector cmSystemTools::ParseArguments(const char* command) { std::vector args; diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index d0902b1f9f..9de7967287 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -253,6 +253,13 @@ public: static void ParseUnixCommandLine(const char* command, std::vector& args); + /** + * Handle response file in an argument list and return a new argument list + * **/ + static std::vector HandleResponseFile( + std::vector::const_iterator argBeg, + std::vector::const_iterator argEnd); + static size_t CalculateCommandLineLengthLimit(); static void EnableMessages() { s_DisableMessages = false; }