Ninja: Generate separate compile and link rules for each target
Our <LANG>_COMPILER and <LANG>_<TARGET_TYPE>_LINKER rule generation has access to a specific cmTarget so the results may depend on it. Instead generate separate rules for each target using an encoded target name. In particular, this makes CTEST_USE_LAUNCHERS report proper target information.
This commit is contained in:
parent
00ccfff2bc
commit
a390de65e0
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
const char* cmGlobalNinjaGenerator::NINJA_BUILD_FILE = "build.ninja";
|
const char* cmGlobalNinjaGenerator::NINJA_BUILD_FILE = "build.ninja";
|
||||||
const char* cmGlobalNinjaGenerator::NINJA_RULES_FILE = "rules.ninja";
|
const char* cmGlobalNinjaGenerator::NINJA_RULES_FILE = "rules.ninja";
|
||||||
|
@ -57,6 +58,28 @@ void cmGlobalNinjaGenerator::WriteComment(std::ostream& os,
|
||||||
os << "# " << replace.substr(lpos) << "\n\n";
|
os << "# " << replace.substr(lpos) << "\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string cmGlobalNinjaGenerator::EncodeRuleName(std::string const& name)
|
||||||
|
{
|
||||||
|
// Ninja rule names must match "[a-zA-Z0-9_.-]+". Use ".xx" to encode
|
||||||
|
// "." and all invalid characters as hexadecimal.
|
||||||
|
std::string encoded;
|
||||||
|
for (std::string::const_iterator i = name.begin();
|
||||||
|
i != name.end(); ++i)
|
||||||
|
{
|
||||||
|
if (isalnum(*i) || *i == '_' || *i == '-')
|
||||||
|
{
|
||||||
|
encoded += *i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char buf[16];
|
||||||
|
sprintf(buf, ".%02x", static_cast<unsigned int>(*i));
|
||||||
|
encoded += buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return encoded;
|
||||||
|
}
|
||||||
|
|
||||||
static bool IsIdentChar(char c)
|
static bool IsIdentChar(char c)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
|
@ -120,7 +143,8 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
|
||||||
const cmNinjaDeps& orderOnlyDeps,
|
const cmNinjaDeps& orderOnlyDeps,
|
||||||
const cmNinjaVars& variables,
|
const cmNinjaVars& variables,
|
||||||
const std::string& rspfile,
|
const std::string& rspfile,
|
||||||
int cmdLineLimit)
|
int cmdLineLimit,
|
||||||
|
bool* usedResponseFile)
|
||||||
{
|
{
|
||||||
// Make sure there is a rule.
|
// Make sure there is a rule.
|
||||||
if(rule.empty())
|
if(rule.empty())
|
||||||
|
@ -205,6 +229,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
|
||||||
std::string buildstr = build;
|
std::string buildstr = build;
|
||||||
std::string assignments = variable_assignments.str();
|
std::string assignments = variable_assignments.str();
|
||||||
const std::string& args = arguments;
|
const std::string& args = arguments;
|
||||||
|
bool useResponseFile = false;
|
||||||
if (cmdLineLimit > 0
|
if (cmdLineLimit > 0
|
||||||
&& args.size() + buildstr.size() + assignments.size()
|
&& args.size() + buildstr.size() + assignments.size()
|
||||||
> (size_t) cmdLineLimit) {
|
> (size_t) cmdLineLimit) {
|
||||||
|
@ -213,6 +238,11 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
|
||||||
cmGlobalNinjaGenerator::WriteVariable(variable_assignments,
|
cmGlobalNinjaGenerator::WriteVariable(variable_assignments,
|
||||||
"RSP_FILE", rspfile, "", 1);
|
"RSP_FILE", rspfile, "", 1);
|
||||||
assignments += variable_assignments.str();
|
assignments += variable_assignments.str();
|
||||||
|
useResponseFile = true;
|
||||||
|
}
|
||||||
|
if (usedResponseFile)
|
||||||
|
{
|
||||||
|
*usedResponseFile = useResponseFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
os << buildstr << args << assignments;
|
os << buildstr << args << assignments;
|
||||||
|
|
|
@ -61,6 +61,7 @@ public:
|
||||||
/// Write a divider in the given output stream @a os.
|
/// Write a divider in the given output stream @a os.
|
||||||
static void WriteDivider(std::ostream& os);
|
static void WriteDivider(std::ostream& os);
|
||||||
|
|
||||||
|
static std::string EncodeRuleName(std::string const& name);
|
||||||
static std::string EncodeIdent(const std::string &ident, std::ostream &vars);
|
static std::string EncodeIdent(const std::string &ident, std::ostream &vars);
|
||||||
static std::string EncodeLiteral(const std::string &lit);
|
static std::string EncodeLiteral(const std::string &lit);
|
||||||
std::string EncodePath(const std::string &path);
|
std::string EncodePath(const std::string &path);
|
||||||
|
@ -87,7 +88,8 @@ public:
|
||||||
const cmNinjaDeps& orderOnlyDeps,
|
const cmNinjaDeps& orderOnlyDeps,
|
||||||
const cmNinjaVars& variables,
|
const cmNinjaVars& variables,
|
||||||
const std::string& rspfile = std::string(),
|
const std::string& rspfile = std::string(),
|
||||||
int cmdLineLimit = -1);
|
int cmdLineLimit = -1,
|
||||||
|
bool* usedResponseFile = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to write a build statement with the special 'phony' rule.
|
* Helper to write a build statement with the special 'phony' rule.
|
||||||
|
|
|
@ -94,8 +94,6 @@ void cmNinjaNormalTargetGenerator::Generate()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->WriteLinkRule(false); // write rule without rspfile support
|
|
||||||
this->WriteLinkRule(true); // write rule with rspfile support
|
|
||||||
this->WriteLinkStatement();
|
this->WriteLinkStatement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,7 +158,9 @@ cmNinjaNormalTargetGenerator
|
||||||
return this->TargetLinkLanguage
|
return this->TargetLinkLanguage
|
||||||
+ "_"
|
+ "_"
|
||||||
+ cmTarget::GetTargetTypeName(this->GetTarget()->GetType())
|
+ cmTarget::GetTargetTypeName(this->GetTarget()->GetType())
|
||||||
+ "_LINKER";
|
+ "_LINKER__"
|
||||||
|
+ cmGlobalNinjaGenerator::EncodeRuleName(this->GetTarget()->GetName())
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -169,8 +169,6 @@ cmNinjaNormalTargetGenerator
|
||||||
{
|
{
|
||||||
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 += "_RSP_FILE";
|
|
||||||
|
|
||||||
// Select whether to use a response file for objects.
|
// Select whether to use a response file for objects.
|
||||||
std::string rspfile;
|
std::string rspfile;
|
||||||
|
@ -661,6 +659,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the build statement for this target.
|
// Write the build statement for this target.
|
||||||
|
bool usedResponseFile = false;
|
||||||
globalGen.WriteBuild(this->GetBuildFileStream(),
|
globalGen.WriteBuild(this->GetBuildFileStream(),
|
||||||
comment.str(),
|
comment.str(),
|
||||||
this->LanguageLinkerRule(),
|
this->LanguageLinkerRule(),
|
||||||
|
@ -670,7 +669,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
||||||
orderOnlyDeps,
|
orderOnlyDeps,
|
||||||
vars,
|
vars,
|
||||||
rspfile,
|
rspfile,
|
||||||
commandLineLengthLimit);
|
commandLineLengthLimit,
|
||||||
|
&usedResponseFile);
|
||||||
|
this->WriteLinkRule(usedResponseFile);
|
||||||
|
|
||||||
if (targetOutput != targetOutputReal && !target.IsFrameworkOnApple())
|
if (targetOutput != targetOutputReal && !target.IsFrameworkOnApple())
|
||||||
{
|
{
|
||||||
|
|
|
@ -97,6 +97,13 @@ std::string const& cmNinjaTargetGenerator::GetConfigName() const
|
||||||
return this->LocalGenerator->GetConfigName();
|
return this->LocalGenerator->GetConfigName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string cmNinjaTargetGenerator::LanguageCompilerRule(
|
||||||
|
const std::string& lang) const
|
||||||
|
{
|
||||||
|
return lang + "_COMPILER__" +
|
||||||
|
cmGlobalNinjaGenerator::EncodeRuleName(this->Target->GetName());
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Picked up from cmMakefileTargetGenerator. Refactor it.
|
// TODO: Picked up from cmMakefileTargetGenerator. Refactor it.
|
||||||
const char* cmNinjaTargetGenerator::GetFeature(const std::string& feature)
|
const char* cmNinjaTargetGenerator::GetFeature(const std::string& feature)
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,8 +67,7 @@ protected:
|
||||||
|
|
||||||
std::string const& GetConfigName() const;
|
std::string const& GetConfigName() const;
|
||||||
|
|
||||||
std::string LanguageCompilerRule(const std::string& lang) const
|
std::string LanguageCompilerRule(const std::string& lang) const;
|
||||||
{ return lang + "_COMPILER"; }
|
|
||||||
|
|
||||||
const char* GetFeature(const std::string& feature);
|
const char* GetFeature(const std::string& feature);
|
||||||
bool GetFeatureAsBool(const std::string& feature);
|
bool GetFeatureAsBool(const std::string& feature);
|
||||||
|
|
Loading…
Reference in New Issue