summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx104
-rw-r--r--Source/cmGlobalNinjaGenerator.h7
-rw-r--r--Source/cmLocalNinjaGenerator.cxx12
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx48
-rw-r--r--Source/cmNinjaNormalTargetGenerator.h2
5 files changed, 133 insertions, 40 deletions
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 40348e6..4d986ef 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -89,7 +89,10 @@ std::string cmGlobalNinjaGenerator::EncodePath(const std::string &path)
{
std::string result = path;
#ifdef _WIN32
- cmSystemTools::ReplaceString(result, "/", "\\");
+ if(UsingMinGW)
+ cmSystemTools::ReplaceString(result, "\\", "/");
+ else
+ cmSystemTools::ReplaceString(result, "/", "\\");
#endif
return EncodeLiteral(result);
}
@@ -101,7 +104,8 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
const cmNinjaDeps& explicitDeps,
const cmNinjaDeps& implicitDeps,
const cmNinjaDeps& orderOnlyDeps,
- const cmNinjaVars& variables)
+ const cmNinjaVars& variables,
+ int cmdLineLimit)
{
// Make sure there is a rule.
if(rule.empty())
@@ -123,50 +127,59 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
cmGlobalNinjaGenerator::WriteComment(os, comment);
- cmOStringStream builds;
+ cmOStringStream arguments;
// TODO: Better formatting for when there are multiple input/output files.
- // Write outputs files.
- builds << "build";
- for(cmNinjaDeps::const_iterator i = outputs.begin();
- i != outputs.end();
- ++i)
- builds << " " << EncodeIdent(EncodePath(*i), os);
- builds << ":";
-
- // Write the rule.
- builds << " " << rule;
-
// Write explicit dependencies.
for(cmNinjaDeps::const_iterator i = explicitDeps.begin();
i != explicitDeps.end();
++i)
- builds << " " << EncodeIdent(EncodePath(*i), os);
+ arguments << " " << EncodeIdent(EncodePath(*i), os);
// Write implicit dependencies.
if(!implicitDeps.empty())
{
- builds << " |";
+ arguments << " |";
for(cmNinjaDeps::const_iterator i = implicitDeps.begin();
i != implicitDeps.end();
++i)
- builds << " " << EncodeIdent(EncodePath(*i), os);
+ arguments << " " << EncodeIdent(EncodePath(*i), os);
}
// Write order-only dependencies.
if(!orderOnlyDeps.empty())
{
- builds << " ||";
+ arguments << " ||";
for(cmNinjaDeps::const_iterator i = orderOnlyDeps.begin();
i != orderOnlyDeps.end();
++i)
- builds << " " << EncodeIdent(EncodePath(*i), os);
+ arguments << " " << EncodeIdent(EncodePath(*i), os);
}
- builds << "\n";
+ arguments << "\n";
+
+
+ cmOStringStream builds;
+
+ // Write outputs files.
+ builds << "build";
+ for(cmNinjaDeps::const_iterator i = outputs.begin();
+ i != outputs.end();
+ ++i)
+ builds << " " << EncodeIdent(EncodePath(*i), os);
+ builds << ":";
+
- os << builds.str();
+ // Write the rule.
+ builds << " " << rule;
+
+ // check if a response file rule should be used
+ const std::string args = arguments.str();
+ if (cmdLineLimit > 0 && args.size() > (size_t)cmdLineLimit)
+ builds << "_RSPFILE";
+
+ os << builds.str() << args;
// Write the variables bound to this build statement.
for(cmNinjaVars::const_iterator i = variables.begin();
@@ -200,6 +213,7 @@ void cmGlobalNinjaGenerator::AddCustomCommandRule()
"$DESC",
"Rule for running custom commands.",
/*depfile*/ "",
+ /*rspfile*/ "",
/*restat*/ true);
}
@@ -211,10 +225,17 @@ cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command,
const cmNinjaDeps& deps,
const cmNinjaDeps& orderOnlyDeps)
{
+ std::string cmd = command;
+#ifdef _WIN32
+ if (cmd.empty())
+ // TODO Shouldn't an empty command be handled by ninja?
+ cmd = "cmd.exe /c";
+#endif
+
this->AddCustomCommandRule();
cmNinjaVars vars;
- vars["COMMAND"] = command;
+ vars["COMMAND"] = cmd;
vars["DESC"] = EncodeLiteral(description);
cmGlobalNinjaGenerator::WriteBuild(*this->BuildFileStream,
@@ -233,6 +254,7 @@ void cmGlobalNinjaGenerator::WriteRule(std::ostream& os,
const std::string& description,
const std::string& comment,
const std::string& depfile,
+ const std::string& rspfile,
bool restat,
bool generator)
{
@@ -277,6 +299,14 @@ void cmGlobalNinjaGenerator::WriteRule(std::ostream& os,
os << "description = " << description << "\n";
}
+ if(!rspfile.empty())
+ {
+ cmGlobalNinjaGenerator::Indent(os, 1);
+ os << "rspfile = " << rspfile << "\n";
+ cmGlobalNinjaGenerator::Indent(os, 1);
+ os << "rspfile_content = $in" << "\n";
+ }
+
if(restat)
{
cmGlobalNinjaGenerator::Indent(os, 1);
@@ -404,16 +434,19 @@ void cmGlobalNinjaGenerator
cmMakefile *mf,
bool optional)
{
- this->cmGlobalGenerator::EnableLanguage(languages, mf, optional);
std::string path;
for(std::vector<std::string>::const_iterator l = languages.begin();
l != languages.end(); ++l)
{
+ std::vector<std::string> language;
+ language.push_back(*l);
+
if(*l == "NONE")
{
+ this->cmGlobalGenerator::EnableLanguage(language, mf, optional);
continue;
}
- if(*l == "Fortran")
+ else if(*l == "Fortran")
{
std::string message = "The \"";
message += this->GetName();
@@ -422,10 +455,26 @@ void cmGlobalNinjaGenerator
message += "\" yet.";
cmSystemTools::Error(message.c_str());
}
+ else if(*l == "RC")
+ {
+ // check if mingw is used
+ const char* cc = mf->GetDefinition("CMAKE_C_COMPILER");
+ if(cc && std::string(cc).find("gcc.exe") != std::string::npos)
+ {
+ UsingMinGW = true;
+ std::string rc = cmSystemTools::FindProgram("windres");
+ if(rc.empty())
+ rc = "windres.exe";;
+ mf->AddDefinition("CMAKE_RC_COMPILER", rc.c_str());
+ }
+ }
+ this->cmGlobalGenerator::EnableLanguage(language, mf, optional);
this->ResolveLanguageCompiler(*l, mf, optional);
- }
+ }
}
+bool cmGlobalNinjaGenerator::UsingMinGW = false;
+
// Implemented by:
// cmGlobalUnixMakefileGenerator3
// cmGlobalVisualStudio10Generator
@@ -483,6 +532,7 @@ void cmGlobalNinjaGenerator::AddRule(const std::string& name,
const std::string& description,
const std::string& comment,
const std::string& depfile,
+ const std::string& rspfile,
bool restat,
bool generator)
{
@@ -497,6 +547,7 @@ void cmGlobalNinjaGenerator::AddRule(const std::string& name,
description,
comment,
depfile,
+ rspfile,
restat,
generator);
}
@@ -841,6 +892,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
"Re-running CMake...",
"Rule for re-running cmake.",
/*depfile=*/ "",
+ /*rspfile=*/ "",
/*restat=*/ false,
/*generator=*/ true);
@@ -878,6 +930,7 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
"Cleaning all built files...",
"Rule for cleaning all built files.",
/*depfile=*/ "",
+ /*rspfile=*/ "",
/*restat=*/ false,
/*generator=*/ false);
WriteBuild(os,
@@ -898,6 +951,7 @@ void cmGlobalNinjaGenerator::WriteTargetHelp(std::ostream& os)
"All primary targets available:",
"Rule for printing all primary targets available.",
/*depfile=*/ "",
+ /*rspfile=*/ "",
/*restat=*/ false,
/*generator=*/ false);
WriteBuild(os,
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 7b6b9b7..0c740e8 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -81,7 +81,8 @@ public:
const cmNinjaDeps& explicitDeps,
const cmNinjaDeps& implicitDeps,
const cmNinjaDeps& orderOnlyDeps,
- const cmNinjaVars& variables);
+ const cmNinjaVars& variables,
+ int cmdLineLimit = -1);
/**
* Helper to write a build statement with the special 'phony' rule.
@@ -113,6 +114,7 @@ public:
const std::string& description,
const std::string& comment = "",
const std::string& depfile = "",
+ const std::string& rspfile = "" ,
bool restat = false,
bool generator = false);
@@ -226,6 +228,7 @@ public:
const std::string& description,
const std::string& comment = "",
const std::string& depfile = "",
+ const std::string& rspfile = "",
bool restat = false,
bool generator = false);
@@ -341,6 +344,8 @@ private:
TargetAliasMap TargetAliases;
static cmLocalGenerator* LocalGenerator;
+
+ static bool UsingMinGW;
};
#endif // ! cmGlobalNinjaGenerator_h
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index f6a6bc2..d5baaee 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -275,16 +275,16 @@ std::string cmLocalNinjaGenerator::BuildCommandLine(
return ":";
#endif
- // TODO: This will work only on Unix platforms. I don't
- // want to use a link.txt file because I will lose the benefit of the
- // $in variables. A discussion about dealing with multiple commands in
- // a rule is started here:
- // groups.google.com/group/ninja-build/browse_thread/thread/d515f23a78986008
cmOStringStream cmd;
for (std::vector<std::string>::const_iterator li = cmdLines.begin();
li != cmdLines.end(); ++li) {
- if (li != cmdLines.begin())
+ if (li != cmdLines.begin()) {
cmd << " && ";
+#ifdef _WIN32
+ } else if (cmdLines.size() > 1) {
+ cmd << "cmd.exe /c ";
+#endif
+ }
cmd << *li;
}
return cmd.str();
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 1751091..b38619a 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -90,7 +90,10 @@ void cmNinjaNormalTargetGenerator::Generate()
}
else
{
- this->WriteLinkRule();
+ this->WriteLinkRule(false);
+#ifdef _WIN32 // TODO response file support only Linux
+ this->WriteLinkRule(true);
+#endif
this->WriteLinkStatement();
}
@@ -144,17 +147,39 @@ cmNinjaNormalTargetGenerator
void
cmNinjaNormalTargetGenerator
-::WriteLinkRule()
+::WriteLinkRule(bool useResponseFile)
{
cmTarget::TargetType targetType = this->GetTarget()->GetType();
std::string ruleName = this->LanguageLinkerRule();
+ if (useResponseFile)
+ ruleName += "_RSPFILE";
+
+ // Select whether to use a response file for objects.
+ std::string rspfile;
if (!this->GetGlobalGenerator()->HasRule(ruleName)) {
cmLocalGenerator::RuleVariables vars;
vars.RuleLauncher = "RULE_LAUNCH_LINK";
vars.CMTarget = this->GetTarget();
vars.Language = this->TargetLinkLanguage;
- vars.Objects = "$in";
+
+ std::string responseFlag;
+ if (!useResponseFile) {
+ vars.Objects = "$in";
+ } else {
+ // handle response file
+ std::string cmakeLinkVar = std::string("CMAKE_") +
+ this->TargetLinkLanguage + "_RESPONSE_FILE_LINK_FLAG";
+ const char * flag = GetMakefile()->GetDefinition(cmakeLinkVar.c_str());
+ if(flag) {
+ responseFlag = flag;
+ } else {
+ responseFlag = "@";
+ }
+ rspfile = "$out.rsp";
+ responseFlag += rspfile;
+ vars.Objects = responseFlag.c_str();
+ }
std::string objdir =
this->GetLocalGenerator()->GetHomeRelativeOutputPath();
objdir += objdir.empty() ? "" : "/";
@@ -201,7 +226,7 @@ cmNinjaNormalTargetGenerator
vars.LanguageCompileFlags = langFlags.c_str();
}
- // Rule for linking library.
+ // Rule for linking library/executable.
std::vector<std::string> linkCmds = this->ComputeLinkCmd();
for(std::vector<std::string>::iterator i = linkCmds.begin();
i != linkCmds.end();
@@ -214,7 +239,7 @@ cmNinjaNormalTargetGenerator
std::string linkCmd =
this->GetLocalGenerator()->BuildCommandLine(linkCmds);
- // Write the linker rule.
+ // Write the linker rule with response file if needed.
cmOStringStream comment;
comment << "Rule for linking " << this->TargetLinkLanguage << " "
<< this->GetVisibleTypeName() << ".";
@@ -224,7 +249,9 @@ cmNinjaNormalTargetGenerator
this->GetGlobalGenerator()->AddRule(ruleName,
linkCmd,
description.str(),
- comment.str());
+ comment.str(),
+ /*depfile*/ "",
+ rspfile);
}
if (this->TargetNameOut != this->TargetNameReal) {
@@ -456,6 +483,12 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
symlinkVars["POST_BUILD"] = postBuildCmdLine;
}
+ int cmdLineLimit = -1;
+#ifdef _WIN32
+ cmdLineLimit = 8100;
+#else
+ // TODO
+#endif
// Write the build statement for this target.
cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
comment.str(),
@@ -464,7 +497,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
explicitDeps,
implicitDeps,
emptyDeps,
- vars);
+ vars,
+ cmdLineLimit);
if (targetOutput != targetOutputReal) {
if (targetType == cmTarget::EXECUTABLE) {
diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h
index 7acbe8f..3be1c94 100644
--- a/Source/cmNinjaNormalTargetGenerator.h
+++ b/Source/cmNinjaNormalTargetGenerator.h
@@ -30,7 +30,7 @@ private:
std::string LanguageLinkerRule() const;
const char* GetVisibleTypeName() const;
void WriteLanguagesRules();
- void WriteLinkRule();
+ void WriteLinkRule(bool useResponseFile);
void WriteLinkStatement();
void WriteObjectLibStatement();
std::vector<std::string> ComputeLinkCmd();