summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2015-08-21 13:29:02 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2015-08-21 13:29:02 (GMT)
commitc450686ef20597d43d4f019b315275cc8a6ba4a2 (patch)
tree8f6f507617f4b565c627c01e3273c4e756a438c3 /Source
parent870d839f0d050e1db117c945d478938db657072e (diff)
parent3c37d2642d9000a2d01bc46ad0ea74a741bdb658 (diff)
downloadCMake-c450686ef20597d43d4f019b315275cc8a6ba4a2.zip
CMake-c450686ef20597d43d4f019b315275cc8a6ba4a2.tar.gz
CMake-c450686ef20597d43d4f019b315275cc8a6ba4a2.tar.bz2
Merge topic 'OUTPUT_NAME-genex-no-recursion'
3c37d264 cmGeneratorTarget: Avoid recursion in GetOutputName method
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGeneratorTarget.cxx93
-rw-r--r--Source/cmGeneratorTarget.h4
2 files changed, 62 insertions, 35 deletions
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 299c112..530acfe 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -270,48 +270,71 @@ const char *cmGeneratorTarget::GetProperty(const std::string& prop) const
std::string cmGeneratorTarget::GetOutputName(const std::string& config,
bool implib) const
{
- std::vector<std::string> props;
- std::string type = this->Target->GetOutputTargetType(implib);
- std::string configUpper = cmSystemTools::UpperCase(config);
- if(!type.empty() && !configUpper.empty())
- {
- // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG>
- props.push_back(type + "_OUTPUT_NAME_" + configUpper);
- }
- if(!type.empty())
+ // Lookup/compute/cache the output name for this configuration.
+ OutputNameKey key(config, implib);
+ cmGeneratorTarget::OutputNameMapType::iterator i =
+ this->OutputNameMap.find(key);
+ if(i == this->OutputNameMap.end())
{
- // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME
- props.push_back(type + "_OUTPUT_NAME");
- }
- if(!configUpper.empty())
- {
- // OUTPUT_NAME_<CONFIG>
- props.push_back("OUTPUT_NAME_" + configUpper);
- // <CONFIG>_OUTPUT_NAME
- props.push_back(configUpper + "_OUTPUT_NAME");
- }
- // OUTPUT_NAME
- props.push_back("OUTPUT_NAME");
+ // Add empty name in map to detect potential recursion.
+ OutputNameMapType::value_type entry(key, "");
+ i = this->OutputNameMap.insert(entry).first;
- std::string outName;
- for(std::vector<std::string>::const_iterator i = props.begin();
- i != props.end(); ++i)
- {
- if (const char* outNameProp = this->Target->GetProperty(*i))
+ // Compute output name.
+ std::vector<std::string> props;
+ std::string type = this->Target->GetOutputTargetType(implib);
+ std::string configUpper = cmSystemTools::UpperCase(config);
+ if(!type.empty() && !configUpper.empty())
{
- outName = outNameProp;
- break;
+ // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG>
+ props.push_back(type + "_OUTPUT_NAME_" + configUpper);
+ }
+ if(!type.empty())
+ {
+ // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME
+ props.push_back(type + "_OUTPUT_NAME");
+ }
+ if(!configUpper.empty())
+ {
+ // OUTPUT_NAME_<CONFIG>
+ props.push_back("OUTPUT_NAME_" + configUpper);
+ // <CONFIG>_OUTPUT_NAME
+ props.push_back(configUpper + "_OUTPUT_NAME");
+ }
+ // OUTPUT_NAME
+ props.push_back("OUTPUT_NAME");
+
+ std::string outName;
+ for(std::vector<std::string>::const_iterator it = props.begin();
+ it != props.end(); ++it)
+ {
+ if (const char* outNameProp = this->Target->GetProperty(*it))
+ {
+ outName = outNameProp;
+ break;
+ }
}
- }
- if (outName.empty())
+ if(outName.empty())
+ {
+ outName = this->GetName();
+ }
+
+ // Now evaluate genex and update the previously-prepared map entry.
+ cmGeneratorExpression ge;
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(outName);
+ i->second = cge->Evaluate(this->Makefile, config);
+ }
+ else if(i->second.empty())
{
- outName = this->GetName();
+ // An empty map entry indicates we have been called recursively
+ // from the above block.
+ this->Makefile->GetCMakeInstance()->IssueMessage(
+ cmake::FATAL_ERROR,
+ "Target '" + this->GetName() + "' OUTPUT_NAME depends on itself.",
+ this->Target->GetBacktrace());
}
-
- cmGeneratorExpression ge;
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(outName);
- return cge->Evaluate(this->Makefile, config);
+ return i->second;
}
//----------------------------------------------------------------------------
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 68e7a8a..15b3335 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -375,6 +375,10 @@ private:
};
mutable std::map<std::string, LinkImplClosure> LinkImplClosureMap;
+ typedef std::pair<std::string, bool> OutputNameKey;
+ typedef std::map<OutputNameKey, std::string> OutputNameMapType;
+ mutable OutputNameMapType OutputNameMap;
+
public:
std::vector<cmTarget const*> const&
GetLinkImplementationClosure(const std::string& config) const;