Ninja: don't use shell when cmake is called directly
When linking with cmake and vs_link_* the command line could be too long for cmd.exe, which needs not to be called in this case. (was not cached by a test) Introduce rules which don't use the shell and use this rule when there are no pre or post step. For free we get a small speedup, because cmd is then not called. Also be more accurate when estimating the command line length.
This commit is contained in:
parent
220fdc16fc
commit
6546086004
|
@ -106,6 +106,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
|
||||||
const cmNinjaDeps& implicitDeps,
|
const cmNinjaDeps& implicitDeps,
|
||||||
const cmNinjaDeps& orderOnlyDeps,
|
const cmNinjaDeps& orderOnlyDeps,
|
||||||
const cmNinjaVars& variables,
|
const cmNinjaVars& variables,
|
||||||
|
bool suppressShell,
|
||||||
int cmdLineLimit)
|
int cmdLineLimit)
|
||||||
{
|
{
|
||||||
// Make sure there is a rule.
|
// Make sure there is a rule.
|
||||||
|
@ -177,8 +178,15 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
|
||||||
|
|
||||||
// check if a response file rule should be used
|
// check if a response file rule should be used
|
||||||
const std::string args = arguments.str();
|
const std::string args = arguments.str();
|
||||||
if (cmdLineLimit > 0 && args.size() > (size_t)cmdLineLimit)
|
if (suppressShell)
|
||||||
|
{
|
||||||
|
builds << "_NOSHELL";
|
||||||
|
}
|
||||||
|
else if (cmdLineLimit > 0 &&
|
||||||
|
args.size() + builds.str().size() > (size_t)cmdLineLimit)
|
||||||
|
{
|
||||||
builds << "_RSPFILE";
|
builds << "_RSPFILE";
|
||||||
|
}
|
||||||
|
|
||||||
os << builds.str() << args;
|
os << builds.str() << args;
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,7 @@ public:
|
||||||
const cmNinjaDeps& implicitDeps,
|
const cmNinjaDeps& implicitDeps,
|
||||||
const cmNinjaDeps& orderOnlyDeps,
|
const cmNinjaDeps& orderOnlyDeps,
|
||||||
const cmNinjaVars& variables,
|
const cmNinjaVars& variables,
|
||||||
|
bool suppressShell = false,
|
||||||
int cmdLineLimit = -1);
|
int cmdLineLimit = -1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -264,6 +264,14 @@ void cmLocalNinjaGenerator::AppendCustomCommandDeps(const cmCustomCommand *cc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string cmLocalNinjaGenerator::nopCommand() const {
|
||||||
|
#ifdef _WIN32
|
||||||
|
return "cd .";
|
||||||
|
#else
|
||||||
|
return ":";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
std::string cmLocalNinjaGenerator::BuildCommandLine(
|
std::string cmLocalNinjaGenerator::BuildCommandLine(
|
||||||
const std::vector<std::string> &cmdLines)
|
const std::vector<std::string> &cmdLines)
|
||||||
{
|
{
|
||||||
|
@ -272,9 +280,10 @@ std::string cmLocalNinjaGenerator::BuildCommandLine(
|
||||||
// don't use POST_BUILD.
|
// don't use POST_BUILD.
|
||||||
if (cmdLines.empty())
|
if (cmdLines.empty())
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return "cd.";
|
return "";
|
||||||
#else
|
#else
|
||||||
return ":";
|
// TODO use _NOSHELL rule also on Linux
|
||||||
|
return nopCommand();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::ostringstream cmd;
|
std::ostringstream cmd;
|
||||||
|
|
|
@ -111,6 +111,7 @@ private:
|
||||||
|
|
||||||
void AppendCustomCommandDeps(const cmCustomCommand *cc,
|
void AppendCustomCommandDeps(const cmCustomCommand *cc,
|
||||||
cmNinjaDeps &ninjaDeps);
|
cmNinjaDeps &ninjaDeps);
|
||||||
|
std::string nopCommand() const;
|
||||||
std::string BuildCommandLine(const std::vector<std::string> &cmdLines);
|
std::string BuildCommandLine(const std::vector<std::string> &cmdLines);
|
||||||
void AppendCustomCommandLines(const cmCustomCommand *cc,
|
void AppendCustomCommandLines(const cmCustomCommand *cc,
|
||||||
std::vector<std::string> &cmdLines);
|
std::vector<std::string> &cmdLines);
|
||||||
|
|
|
@ -75,9 +75,13 @@ void cmNinjaNormalTargetGenerator::Generate()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->WriteLinkRule(false);
|
this->WriteLinkRule();
|
||||||
#ifdef _WIN32 // TODO response file support only Linux
|
#ifdef _WIN32
|
||||||
this->WriteLinkRule(true);
|
// TODO remove hardcoded strings
|
||||||
|
this->WriteLinkRule("_RSPFILE");
|
||||||
|
this->WriteLinkRule("_NOSHELL");
|
||||||
|
#else
|
||||||
|
// TODO response file support only Linux
|
||||||
#endif
|
#endif
|
||||||
this->WriteLinkStatement();
|
this->WriteLinkStatement();
|
||||||
}
|
}
|
||||||
|
@ -131,12 +135,18 @@ cmNinjaNormalTargetGenerator
|
||||||
|
|
||||||
void
|
void
|
||||||
cmNinjaNormalTargetGenerator
|
cmNinjaNormalTargetGenerator
|
||||||
::WriteLinkRule(bool useResponseFile)
|
::WriteLinkRule(const std::string& postfix)
|
||||||
{
|
{
|
||||||
cmTarget::TargetType targetType = this->GetTarget()->GetType();
|
cmTarget::TargetType targetType = this->GetTarget()->GetType();
|
||||||
std::string ruleName = this->LanguageLinkerRule();
|
std::string ruleName = this->LanguageLinkerRule();
|
||||||
if (useResponseFile)
|
|
||||||
ruleName += "_RSPFILE";
|
bool useResponseFile = false;
|
||||||
|
bool suppressShell = false;
|
||||||
|
if (!postfix.empty()) {
|
||||||
|
ruleName += postfix;
|
||||||
|
useResponseFile = (postfix == "_RSPFILE");
|
||||||
|
suppressShell = (postfix == "_NOSHELL");
|
||||||
|
}
|
||||||
|
|
||||||
// Select whether to use a response file for objects.
|
// Select whether to use a response file for objects.
|
||||||
std::string rspfile;
|
std::string rspfile;
|
||||||
|
@ -210,8 +220,10 @@ cmNinjaNormalTargetGenerator
|
||||||
{
|
{
|
||||||
this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
|
this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
|
||||||
}
|
}
|
||||||
|
if (!suppressShell) {
|
||||||
linkCmds.insert(linkCmds.begin(), "$PRE_LINK");
|
linkCmds.insert(linkCmds.begin(), "$PRE_LINK");
|
||||||
linkCmds.push_back("$POST_BUILD");
|
linkCmds.push_back("$POST_BUILD");
|
||||||
|
}
|
||||||
std::string linkCmd =
|
std::string linkCmd =
|
||||||
this->GetLocalGenerator()->BuildCommandLine(linkCmds);
|
this->GetLocalGenerator()->BuildCommandLine(linkCmds);
|
||||||
|
|
||||||
|
@ -331,6 +343,7 @@ cmNinjaNormalTargetGenerator
|
||||||
|
|
||||||
void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
||||||
{
|
{
|
||||||
|
cmLocalNinjaGenerator* locGtor = this->GetLocalGenerator();
|
||||||
cmTarget::TargetType targetType = this->GetTarget()->GetType();
|
cmTarget::TargetType targetType = this->GetTarget()->GetType();
|
||||||
|
|
||||||
// Write comments.
|
// Write comments.
|
||||||
|
@ -368,7 +381,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
||||||
cmNinjaDeps explicitDeps = this->GetObjects(),
|
cmNinjaDeps explicitDeps = this->GetObjects(),
|
||||||
implicitDeps = this->ComputeLinkDeps();
|
implicitDeps = this->ComputeLinkDeps();
|
||||||
|
|
||||||
this->GetLocalGenerator()->GetTargetFlags(vars["LINK_LIBRARIES"],
|
locGtor->GetTargetFlags(vars["LINK_LIBRARIES"],
|
||||||
vars["FLAGS"],
|
vars["FLAGS"],
|
||||||
vars["LINK_FLAGS"],
|
vars["LINK_FLAGS"],
|
||||||
*this->GetTarget());
|
*this->GetTarget());
|
||||||
|
@ -378,8 +391,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
||||||
// Compute architecture specific link flags. Yes, these go into a different
|
// Compute architecture specific link flags. Yes, these go into a different
|
||||||
// variable for executables, probably due to a mistake made when duplicating
|
// variable for executables, probably due to a mistake made when duplicating
|
||||||
// code between the Makefile executable and library generators.
|
// code between the Makefile executable and library generators.
|
||||||
this->GetLocalGenerator()
|
locGtor->AddArchitectureFlags(targetType == cmTarget::EXECUTABLE
|
||||||
->AddArchitectureFlags(targetType == cmTarget::EXECUTABLE
|
|
||||||
? vars["FLAGS"]
|
? vars["FLAGS"]
|
||||||
: vars["ARCH_FLAGS"],
|
: vars["ARCH_FLAGS"],
|
||||||
this->GetTarget(),
|
this->GetTarget(),
|
||||||
|
@ -395,7 +407,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
||||||
|
|
||||||
if (!install_name_dir.empty()) {
|
if (!install_name_dir.empty()) {
|
||||||
vars["INSTALLNAME_DIR"] =
|
vars["INSTALLNAME_DIR"] =
|
||||||
this->GetLocalGenerator()->Convert(install_name_dir.c_str(),
|
locGtor->Convert(install_name_dir.c_str(),
|
||||||
cmLocalGenerator::NONE,
|
cmLocalGenerator::NONE,
|
||||||
cmLocalGenerator::SHELL, false);
|
cmLocalGenerator::SHELL, false);
|
||||||
}
|
}
|
||||||
|
@ -404,7 +416,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
||||||
|
|
||||||
std::string path;
|
std::string path;
|
||||||
if (!this->TargetNameImport.empty()) {
|
if (!this->TargetNameImport.empty()) {
|
||||||
path = this->GetLocalGenerator()->ConvertToOutputFormat(
|
path = locGtor->ConvertToOutputFormat(
|
||||||
targetOutputImplib.c_str(), cmLocalGenerator::SHELL);
|
targetOutputImplib.c_str(), cmLocalGenerator::SHELL);
|
||||||
vars["TARGET_IMPLIB"] = path;
|
vars["TARGET_IMPLIB"] = path;
|
||||||
EnsureParentDirectoryExists(path);
|
EnsureParentDirectoryExists(path);
|
||||||
|
@ -416,7 +428,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
||||||
mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID"))
|
mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID"))
|
||||||
{
|
{
|
||||||
path = this->GetTargetPDB();
|
path = this->GetTargetPDB();
|
||||||
vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
|
vars["TARGET_PDB"] = locGtor->ConvertToOutputFormat(
|
||||||
ConvertToNinjaPath(path.c_str()).c_str(),
|
ConvertToNinjaPath(path.c_str()).c_str(),
|
||||||
cmLocalGenerator::SHELL);
|
cmLocalGenerator::SHELL);
|
||||||
EnsureParentDirectoryExists(path);
|
EnsureParentDirectoryExists(path);
|
||||||
|
@ -446,38 +458,45 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
||||||
for (std::vector<cmCustomCommand>::const_iterator
|
for (std::vector<cmCustomCommand>::const_iterator
|
||||||
ci = cmdLists[i]->begin();
|
ci = cmdLists[i]->begin();
|
||||||
ci != cmdLists[i]->end(); ++ci) {
|
ci != cmdLists[i]->end(); ++ci) {
|
||||||
this->GetLocalGenerator()->AppendCustomCommandLines(&*ci,
|
locGtor->AppendCustomCommandLines(&*ci, *cmdLineLists[i]);
|
||||||
*cmdLineLists[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have any PRE_LINK commands, we need to go back to HOME_OUTPUT for
|
// If we have any PRE_LINK commands, we need to go back to HOME_OUTPUT for
|
||||||
// the link commands.
|
// the link commands.
|
||||||
if (!preLinkCmdLines.empty()) {
|
if (!preLinkCmdLines.empty()) {
|
||||||
path = this->GetLocalGenerator()->ConvertToOutputFormat(
|
path = locGtor->ConvertToOutputFormat(
|
||||||
this->GetMakefile()->GetHomeOutputDirectory(),
|
this->GetMakefile()->GetHomeOutputDirectory(),
|
||||||
cmLocalGenerator::SHELL);
|
cmLocalGenerator::SHELL);
|
||||||
preLinkCmdLines.push_back("cd " + path);
|
preLinkCmdLines.push_back("cd " + path);
|
||||||
|
vars["PRE_LINK"] = locGtor->BuildCommandLine(preLinkCmdLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
vars["PRE_LINK"] =
|
|
||||||
this->GetLocalGenerator()->BuildCommandLine(preLinkCmdLines);
|
|
||||||
std::string postBuildCmdLine =
|
|
||||||
this->GetLocalGenerator()->BuildCommandLine(postBuildCmdLines);
|
|
||||||
|
|
||||||
cmNinjaVars symlinkVars;
|
cmNinjaVars symlinkVars;
|
||||||
|
if (!postBuildCmdLines.empty()) {
|
||||||
|
std::string postBuildCmdLine =
|
||||||
|
locGtor->BuildCommandLine(postBuildCmdLines);
|
||||||
|
|
||||||
if (targetOutput == targetOutputReal) {
|
if (targetOutput == targetOutputReal) {
|
||||||
vars["POST_BUILD"] = postBuildCmdLine;
|
vars["POST_BUILD"] = postBuildCmdLine;
|
||||||
} else {
|
} else {
|
||||||
vars["POST_BUILD"] = ":";
|
vars["POST_BUILD"] = ":";
|
||||||
symlinkVars["POST_BUILD"] = postBuildCmdLine;
|
symlinkVars["POST_BUILD"] = postBuildCmdLine;
|
||||||
}
|
}
|
||||||
|
if (preLinkCmdLines.empty()) {
|
||||||
|
// rule with PRE_LINK will be selected, feed it
|
||||||
|
vars["PRE_LINK"] = locGtor->nopCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool suppressShell = preLinkCmdLines.empty() && postBuildCmdLines.empty();
|
||||||
|
|
||||||
int cmdLineLimit = -1;
|
int cmdLineLimit = -1;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
cmdLineLimit = 8100;
|
cmdLineLimit = 8000;
|
||||||
#else
|
#else
|
||||||
// TODO
|
// cmdLineLimit = ?? TODO
|
||||||
|
isCmdSequenc = true;
|
||||||
#endif
|
#endif
|
||||||
// Write the build statement for this target.
|
// Write the build statement for this target.
|
||||||
cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
|
cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
|
||||||
|
@ -488,6 +507,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
||||||
implicitDeps,
|
implicitDeps,
|
||||||
emptyDeps,
|
emptyDeps,
|
||||||
vars,
|
vars,
|
||||||
|
suppressShell,
|
||||||
cmdLineLimit);
|
cmdLineLimit);
|
||||||
|
|
||||||
if (targetOutput != targetOutputReal) {
|
if (targetOutput != targetOutputReal) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ private:
|
||||||
std::string LanguageLinkerRule() const;
|
std::string LanguageLinkerRule() const;
|
||||||
const char* GetVisibleTypeName() const;
|
const char* GetVisibleTypeName() const;
|
||||||
void WriteLanguagesRules();
|
void WriteLanguagesRules();
|
||||||
void WriteLinkRule(bool useResponseFile);
|
void WriteLinkRule(const std::string& postfix = "");
|
||||||
void WriteLinkStatement();
|
void WriteLinkStatement();
|
||||||
void WriteObjectLibStatement();
|
void WriteObjectLibStatement();
|
||||||
std::vector<std::string> ComputeLinkCmd();
|
std::vector<std::string> ComputeLinkCmd();
|
||||||
|
|
Loading…
Reference in New Issue