Merge topic 'no-std-stringstream'
32313fd
Merge branch 'ninja-rspfile' into no-std-stringstreame3a1f72
Ninja: find mingw's resource compilerc60557e
Ninja: don't break because of empty commands128fe5d
Ninja: also create rspfile rules0266c9b
Ninja: check for valid pointer5aab7f9
Ninja: 30000 is too long for windows cmdad4a768
Ninja: add response file support on Windows
This commit is contained in:
commit
aa2c6d0493
|
@ -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,10 +127,41 @@ 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 explicit dependencies.
|
||||
for(cmNinjaDeps::const_iterator i = explicitDeps.begin();
|
||||
i != explicitDeps.end();
|
||||
++i)
|
||||
arguments << " " << EncodeIdent(EncodePath(*i), os);
|
||||
|
||||
// Write implicit dependencies.
|
||||
if(!implicitDeps.empty())
|
||||
{
|
||||
arguments << " |";
|
||||
for(cmNinjaDeps::const_iterator i = implicitDeps.begin();
|
||||
i != implicitDeps.end();
|
||||
++i)
|
||||
arguments << " " << EncodeIdent(EncodePath(*i), os);
|
||||
}
|
||||
|
||||
// Write order-only dependencies.
|
||||
if(!orderOnlyDeps.empty())
|
||||
{
|
||||
arguments << " ||";
|
||||
for(cmNinjaDeps::const_iterator i = orderOnlyDeps.begin();
|
||||
i != orderOnlyDeps.end();
|
||||
++i)
|
||||
arguments << " " << EncodeIdent(EncodePath(*i), os);
|
||||
}
|
||||
|
||||
arguments << "\n";
|
||||
|
||||
|
||||
cmOStringStream builds;
|
||||
|
||||
// Write outputs files.
|
||||
builds << "build";
|
||||
for(cmNinjaDeps::const_iterator i = outputs.begin();
|
||||
|
@ -135,38 +170,16 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
|
|||
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);
|
||||
// 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";
|
||||
|
||||
// Write implicit dependencies.
|
||||
if(!implicitDeps.empty())
|
||||
{
|
||||
builds << " |";
|
||||
for(cmNinjaDeps::const_iterator i = implicitDeps.begin();
|
||||
i != implicitDeps.end();
|
||||
++i)
|
||||
builds << " " << EncodeIdent(EncodePath(*i), os);
|
||||
}
|
||||
|
||||
// Write order-only dependencies.
|
||||
if(!orderOnlyDeps.empty())
|
||||
{
|
||||
builds << " ||";
|
||||
for(cmNinjaDeps::const_iterator i = orderOnlyDeps.begin();
|
||||
i != orderOnlyDeps.end();
|
||||
++i)
|
||||
builds << " " << EncodeIdent(EncodePath(*i), os);
|
||||
}
|
||||
|
||||
builds << "\n";
|
||||
|
||||
os << builds.str();
|
||||
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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue