Cache context-independent includes on evaluation.

Generator expressions whose output depends on the configuration
now record that fact. The GetIncludeDirectories method can use
that result to cache the include directories for later calls.

GetIncludeDirectories is called multiple times for a target
for each configuration, so this should restore performance for
multi-config generators.
This commit is contained in:
Stephen Kelly 2013-02-03 07:33:15 +01:00
parent 089fe1c13d
commit e48d84209c
5 changed files with 66 additions and 14 deletions

View File

@ -88,6 +88,7 @@ const char *cmCompiledGeneratorExpression::Evaluate(
context.Config = config; context.Config = config;
context.Quiet = quiet; context.Quiet = quiet;
context.HadError = false; context.HadError = false;
context.HadContextSensitiveCondition = false;
context.HeadTarget = headTarget; context.HeadTarget = headTarget;
context.CurrentTarget = currentTarget ? currentTarget : headTarget; context.CurrentTarget = currentTarget ? currentTarget : headTarget;
context.Backtrace = this->Backtrace; context.Backtrace = this->Backtrace;
@ -109,6 +110,10 @@ const char *cmCompiledGeneratorExpression::Evaluate(
break; break;
} }
} }
if (!context.HadError)
{
this->HadContextSensitiveCondition = context.HadContextSensitiveCondition;
}
this->Targets = context.Targets; this->Targets = context.Targets;
// TODO: Return a std::string from here instead? // TODO: Return a std::string from here instead?
@ -118,7 +123,8 @@ const char *cmCompiledGeneratorExpression::Evaluate(
cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
cmListFileBacktrace const& backtrace, cmListFileBacktrace const& backtrace,
const char *input) const char *input)
: Backtrace(backtrace), Input(input ? input : "") : Backtrace(backtrace), Input(input ? input : ""),
HadContextSensitiveCondition(false)
{ {
cmGeneratorExpressionLexer l; cmGeneratorExpressionLexer l;
std::vector<cmGeneratorExpressionToken> tokens = std::vector<cmGeneratorExpressionToken> tokens =

View File

@ -100,6 +100,10 @@ public:
{ {
return this->Backtrace; return this->Backtrace;
} }
bool GetHadContextSensitiveCondition() const
{
return this->HadContextSensitiveCondition;
}
private: private:
cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace, cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace,
@ -118,6 +122,7 @@ private:
mutable std::set<cmTarget*> Targets; mutable std::set<cmTarget*> Targets;
mutable std::map<cmStdString, cmStdString> SeenTargetProperties; mutable std::map<cmStdString, cmStdString> SeenTargetProperties;
mutable std::string Output; mutable std::string Output;
mutable bool HadContextSensitiveCondition;
}; };
#endif #endif

View File

@ -238,6 +238,7 @@ static const struct ConfigurationNode : public cmGeneratorExpressionNode
const GeneratorExpressionContent *, const GeneratorExpressionContent *,
cmGeneratorExpressionDAGChecker *) const cmGeneratorExpressionDAGChecker *) const
{ {
context->HadContextSensitiveCondition = true;
return context->Config ? context->Config : ""; return context->Config ? context->Config : "";
} }
} configurationNode; } configurationNode;
@ -262,6 +263,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
"Expression syntax not recognized."); "Expression syntax not recognized.");
return std::string(); return std::string();
} }
context->HadContextSensitiveCondition = true;
if (!context->Config) if (!context->Config)
{ {
return parameters.front().empty() ? "1" : "0"; return parameters.front().empty() ? "1" : "0";
@ -455,12 +457,14 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
} }
if (propertyName == "POSITION_INDEPENDENT_CODE") if (propertyName == "POSITION_INDEPENDENT_CODE")
{ {
context->HadContextSensitiveCondition = true;
return target->GetLinkInterfaceDependentBoolProperty( return target->GetLinkInterfaceDependentBoolProperty(
"POSITION_INDEPENDENT_CODE", context->Config) ? "1" : "0"; "POSITION_INDEPENDENT_CODE", context->Config) ? "1" : "0";
} }
if (target->IsLinkInterfaceDependentBoolProperty(propertyName, if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
context->Config)) context->Config))
{ {
context->HadContextSensitiveCondition = true;
return target->GetLinkInterfaceDependentBoolProperty( return target->GetLinkInterfaceDependentBoolProperty(
propertyName, propertyName,
context->Config) ? "1" : "0"; context->Config) ? "1" : "0";
@ -468,6 +472,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
if (target->IsLinkInterfaceDependentStringProperty(propertyName, if (target->IsLinkInterfaceDependentStringProperty(propertyName,
context->Config)) context->Config))
{ {
context->HadContextSensitiveCondition = true;
const char *propContent = const char *propContent =
target->GetLinkInterfaceDependentStringProperty( target->GetLinkInterfaceDependentStringProperty(
propertyName, propertyName,
@ -486,12 +491,19 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
if (targetPropertyTransitiveWhitelist[i] == propertyName) if (targetPropertyTransitiveWhitelist[i] == propertyName)
{ {
cmGeneratorExpression ge(context->Backtrace); cmGeneratorExpression ge(context->Backtrace);
return ge.Parse(prop)->Evaluate(context->Makefile, cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
std::string result = cge->Evaluate(context->Makefile,
context->Config, context->Config,
context->Quiet, context->Quiet,
context->HeadTarget, context->HeadTarget,
target, target,
&dagChecker); &dagChecker);
if (cge->GetHadContextSensitiveCondition())
{
context->HadContextSensitiveCondition = true;
}
return result;
} }
} }
return prop; return prop;
@ -585,6 +597,9 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode
"be used with add_custom_command."); "be used with add_custom_command.");
return std::string(); return std::string();
} }
context->HadContextSensitiveCondition = true;
for (size_t i = 0; for (size_t i = 0;
i < (sizeof(targetPolicyWhitelist) / i < (sizeof(targetPolicyWhitelist) /
sizeof(*targetPolicyWhitelist)); sizeof(*targetPolicyWhitelist));
@ -716,12 +731,18 @@ private:
} }
cmGeneratorExpression ge(context->Backtrace); cmGeneratorExpression ge(context->Backtrace);
return ge.Parse(propContent)->Evaluate(context->Makefile, cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(propContent);
std::string result = cge->Evaluate(context->Makefile,
context->Config, context->Config,
context->Quiet, context->Quiet,
context->HeadTarget, context->HeadTarget,
target, target,
&dagChecker); &dagChecker);
if (cge->GetHadContextSensitiveCondition())
{
context->HadContextSensitiveCondition = true;
}
return result;
} }
} linkedNode; } linkedNode;

View File

@ -32,6 +32,7 @@ struct cmGeneratorExpressionContext
// directly or indirectly in the property. // directly or indirectly in the property.
bool Quiet; bool Quiet;
bool HadError; bool HadError;
bool HadContextSensitiveCondition;
}; };
struct cmGeneratorExpressionDAGChecker; struct cmGeneratorExpressionDAGChecker;

View File

@ -134,6 +134,7 @@ public:
: ge(cge) : ge(cge)
{} {}
const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge; const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
std::vector<std::string> CachedIncludes;
}; };
std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries; std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries;
}; };
@ -2778,22 +2779,36 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
end = this->Internal->IncludeDirectoriesEntries.end(); end = this->Internal->IncludeDirectoriesEntries.end();
it != end; ++it) it != end; ++it)
{ {
std::vector<std::string> entryIncludes;
cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(this->Makefile, bool testIsOff = true;
config, bool cacheIncludes = false;
false, std::vector<std::string> entryIncludes = (*it)->CachedIncludes;
this, if(!entryIncludes.empty())
&dagChecker), {
entryIncludes); testIsOff = false;
}
else
{
cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(this->Makefile,
config,
false,
this,
&dagChecker),
entryIncludes);
if (!(*it)->ge->GetHadContextSensitiveCondition())
{
cacheIncludes = true;
}
}
std::string usedIncludes; std::string usedIncludes;
for(std::vector<std::string>::const_iterator for(std::vector<std::string>::iterator
li = entryIncludes.begin(); li != entryIncludes.end(); ++li) li = entryIncludes.begin(); li != entryIncludes.end(); ++li)
{ {
std::string inc = *li; if (testIsOff && !cmSystemTools::IsOff(li->c_str()))
if (!cmSystemTools::IsOff(inc.c_str()))
{ {
cmSystemTools::ConvertToUnixSlashes(inc); cmSystemTools::ConvertToUnixSlashes(*li);
} }
std::string inc = *li;
if(uniqueIncludes.insert(inc).second) if(uniqueIncludes.insert(inc).second)
{ {
@ -2804,6 +2819,10 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
} }
} }
} }
if (cacheIncludes)
{
(*it)->CachedIncludes = entryIncludes;
}
if (!usedIncludes.empty()) if (!usedIncludes.empty())
{ {
this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG,