Ninja: also write link libraries to rsp file

and enable rspfile support on Linux, needed for commands longer than e.g. 2096152 characters on Ubuntu.
This commit is contained in:
Peter Kümmel 2012-07-10 09:56:11 +02:00
parent 6274ca6f91
commit 7f647cf5eb
3 changed files with 28 additions and 13 deletions

View File

@ -217,6 +217,7 @@ void cmGlobalNinjaGenerator::AddCustomCommandRule()
"Rule for running custom commands.", "Rule for running custom commands.",
/*depfile*/ "", /*depfile*/ "",
/*rspfile*/ "", /*rspfile*/ "",
/*rspcontent*/ "",
/*restat*/ true); /*restat*/ true);
} }
@ -258,6 +259,7 @@ void cmGlobalNinjaGenerator::WriteRule(std::ostream& os,
const std::string& comment, const std::string& comment,
const std::string& depfile, const std::string& depfile,
const std::string& rspfile, const std::string& rspfile,
const std::string& rspcontent,
bool restat, bool restat,
bool generator) bool generator)
{ {
@ -307,7 +309,8 @@ void cmGlobalNinjaGenerator::WriteRule(std::ostream& os,
cmGlobalNinjaGenerator::Indent(os, 1); cmGlobalNinjaGenerator::Indent(os, 1);
os << "rspfile = " << rspfile << "\n"; os << "rspfile = " << rspfile << "\n";
cmGlobalNinjaGenerator::Indent(os, 1); cmGlobalNinjaGenerator::Indent(os, 1);
os << "rspfile_content = $in" << "\n"; os << "rspfile_content = " <<
(rspcontent.empty() ? "$in" :rspcontent) << "\n";
} }
if(restat) if(restat)
@ -538,6 +541,7 @@ void cmGlobalNinjaGenerator::AddRule(const std::string& name,
const std::string& comment, const std::string& comment,
const std::string& depfile, const std::string& depfile,
const std::string& rspfile, const std::string& rspfile,
const std::string& rspcontent,
bool restat, bool restat,
bool generator) bool generator)
{ {
@ -555,6 +559,7 @@ void cmGlobalNinjaGenerator::AddRule(const std::string& name,
comment, comment,
depfile, depfile,
rspfile, rspfile,
rspcontent,
restat, restat,
generator); generator);
@ -911,6 +916,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
"Rule for re-running cmake.", "Rule for re-running cmake.",
/*depfile=*/ "", /*depfile=*/ "",
/*rspfile=*/ "", /*rspfile=*/ "",
/*rspcontent*/ "",
/*restat=*/ false, /*restat=*/ false,
/*generator=*/ true); /*generator=*/ true);
@ -960,6 +966,7 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
"Rule for cleaning all built files.", "Rule for cleaning all built files.",
/*depfile=*/ "", /*depfile=*/ "",
/*rspfile=*/ "", /*rspfile=*/ "",
/*rspcontent*/ "",
/*restat=*/ false, /*restat=*/ false,
/*generator=*/ false); /*generator=*/ false);
WriteBuild(os, WriteBuild(os,
@ -981,6 +988,7 @@ void cmGlobalNinjaGenerator::WriteTargetHelp(std::ostream& os)
"Rule for printing all primary targets available.", "Rule for printing all primary targets available.",
/*depfile=*/ "", /*depfile=*/ "",
/*rspfile=*/ "", /*rspfile=*/ "",
/*rspcontent*/ "",
/*restat=*/ false, /*restat=*/ false,
/*generator=*/ false); /*generator=*/ false);
WriteBuild(os, WriteBuild(os,

View File

@ -116,7 +116,8 @@ public:
const std::string& description, const std::string& description,
const std::string& comment = "", const std::string& comment = "",
const std::string& depfile = "", const std::string& depfile = "",
const std::string& rspfile = "" , const std::string& rspfile = "",
const std::string& rspcontent = "",
bool restat = false, bool restat = false,
bool generator = false); bool generator = false);
@ -234,6 +235,7 @@ public:
const std::string& comment = "", const std::string& comment = "",
const std::string& depfile = "", const std::string& depfile = "",
const std::string& rspfile = "", const std::string& rspfile = "",
const std::string& rspcontent = "",
bool restat = false, bool restat = false,
bool generator = false); bool generator = false);

View File

@ -75,10 +75,8 @@ void cmNinjaNormalTargetGenerator::Generate()
} }
else else
{ {
this->WriteLinkRule(false); this->WriteLinkRule(false); // write rule without rspfile support
#ifdef _WIN32 // TODO response file support only Linux this->WriteLinkRule(true); // write rule with rspfile support
this->WriteLinkRule(true);
#endif
this->WriteLinkStatement(); this->WriteLinkStatement();
} }
} }
@ -140,6 +138,7 @@ cmNinjaNormalTargetGenerator
// Select whether to use a response file for objects. // Select whether to use a response file for objects.
std::string rspfile; std::string rspfile;
std::string rspcontent;
if (!this->GetGlobalGenerator()->HasRule(ruleName)) { if (!this->GetGlobalGenerator()->HasRule(ruleName)) {
cmLocalGenerator::RuleVariables vars; cmLocalGenerator::RuleVariables vars;
@ -150,6 +149,7 @@ cmNinjaNormalTargetGenerator
std::string responseFlag; std::string responseFlag;
if (!useResponseFile) { if (!useResponseFile) {
vars.Objects = "$in"; vars.Objects = "$in";
vars.LinkLibraries = "$LINK_LIBRARIES";
} else { } else {
// handle response file // handle response file
std::string cmakeLinkVar = std::string("CMAKE_") + std::string cmakeLinkVar = std::string("CMAKE_") +
@ -162,7 +162,9 @@ cmNinjaNormalTargetGenerator
} }
rspfile = "$out.rsp"; rspfile = "$out.rsp";
responseFlag += rspfile; responseFlag += rspfile;
rspcontent = "$in $LINK_LIBRARIES";
vars.Objects = responseFlag.c_str(); vars.Objects = responseFlag.c_str();
vars.LinkLibraries = "";
} }
vars.ObjectDir = "$OBJECT_DIR"; vars.ObjectDir = "$OBJECT_DIR";
@ -189,7 +191,6 @@ cmNinjaNormalTargetGenerator
vars.TargetVersionMajor = targetVersionMajor.c_str(); vars.TargetVersionMajor = targetVersionMajor.c_str();
vars.TargetVersionMinor = targetVersionMinor.c_str(); vars.TargetVersionMinor = targetVersionMinor.c_str();
vars.LinkLibraries = "$LINK_LIBRARIES";
vars.Flags = "$FLAGS"; vars.Flags = "$FLAGS";
vars.LinkFlags = "$LINK_FLAGS"; vars.LinkFlags = "$LINK_FLAGS";
@ -227,7 +228,8 @@ cmNinjaNormalTargetGenerator
description.str(), description.str(),
comment.str(), comment.str(),
/*depfile*/ "", /*depfile*/ "",
rspfile); rspfile,
rspcontent);
} }
if (this->TargetNameOut != this->TargetNameReal) { if (this->TargetNameOut != this->TargetNameReal) {
@ -478,12 +480,15 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
symlinkVars["POST_BUILD"] = postBuildCmdLine; symlinkVars["POST_BUILD"] = postBuildCmdLine;
} }
int cmdLineLimit; int linkRuleLength = this->GetGlobalGenerator()->
#ifdef _WIN32
cmdLineLimit = 8000 - this->GetGlobalGenerator()->
GetRuleCmdLength(this->LanguageLinkerRule()); GetRuleCmdLength(this->LanguageLinkerRule());
#ifdef _WIN32
int commandLineLengthLimit = 8000 - linkRuleLength;
#elif __linux
// for instance ARG_MAX is 2096152 on Ubuntu
int commandLineLengthLimit = sysconf(_SC_ARG_MAX) - linkRuleLength - 1000;
#else #else
cmdLineLimit = -1; // TODO int commandLineLengthLimit = -1;
#endif #endif
// Write the build statement for this target. // Write the build statement for this target.
@ -495,7 +500,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
implicitDeps, implicitDeps,
emptyDeps, emptyDeps,
vars, vars,
cmdLineLimit); commandLineLengthLimit);
if (targetOutput != targetOutputReal) { if (targetOutput != targetOutputReal) {
if (targetType == cmTarget::EXECUTABLE) { if (targetType == cmTarget::EXECUTABLE) {