Make calculation of link-interface-dependent properties type-sensitive.

This commit is contained in:
Stephen Kelly 2013-01-06 13:49:16 +01:00
parent 21fc6c46df
commit cd66b9131d
1 changed files with 118 additions and 48 deletions

View File

@ -4500,22 +4500,50 @@ void cmTarget::AddLinkDependentTargetsForProperties(
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, template<typename PropertyType>
const char *config) PropertyType getTypedProperty(cmTarget *tgt, const char *prop,
PropertyType *);
//----------------------------------------------------------------------------
template<>
bool getTypedProperty<bool>(cmTarget *tgt, const char *prop, bool *)
{ {
bool propContent = this->GetPropertyAsBool(p.c_str()); return tgt->GetPropertyAsBool(prop);
const bool explicitlySet = this->GetProperties() }
//----------------------------------------------------------------------------
template<typename PropertyType>
bool consistentProperty(PropertyType lhs, PropertyType rhs);
//----------------------------------------------------------------------------
template<>
bool consistentProperty(bool lhs, bool rhs)
{
return lhs == rhs;
}
//----------------------------------------------------------------------------
template<typename PropertyType>
PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt,
const std::string &p,
const char *config,
const char *defaultValue,
PropertyType *)
{
PropertyType propContent = getTypedProperty<PropertyType>(tgt, p.c_str(),
0);
const bool explicitlySet = tgt->GetProperties()
.find(p.c_str()) .find(p.c_str())
!= this->GetProperties().end(); != tgt->GetProperties().end();
std::set<std::string> dependentTargets; std::set<std::string> dependentTargets;
this->GetLinkDependentTargetsForProperty(p, tgt->GetLinkDependentTargetsForProperty(p,
dependentTargets); dependentTargets);
const bool impliedByUse = const bool impliedByUse =
this->IsNullImpliedByLinkLibraries(p); tgt->IsNullImpliedByLinkLibraries(p);
assert((impliedByUse ^ explicitlySet) assert((impliedByUse ^ explicitlySet)
|| (!impliedByUse && !explicitlySet)); || (!impliedByUse && !explicitlySet));
cmComputeLinkInformation *info = this->GetLinkInformation(config); cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
bool propInitialized = explicitlySet; bool propInitialized = explicitlySet;
@ -4537,17 +4565,18 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
const bool ifaceIsSet = li->Target->GetProperties() const bool ifaceIsSet = li->Target->GetProperties()
.find("INTERFACE_" + p) .find("INTERFACE_" + p)
!= li->Target->GetProperties().end(); != li->Target->GetProperties().end();
const bool ifacePropContent = li->Target->GetPropertyAsBool( PropertyType ifacePropContent =
("INTERFACE_" + p).c_str()); getTypedProperty<PropertyType>(li->Target,
("INTERFACE_" + p).c_str(), 0);
if (explicitlySet) if (explicitlySet)
{ {
if (ifaceIsSet) if (ifaceIsSet)
{ {
if (propContent != ifacePropContent) if (!consistentProperty(propContent, ifacePropContent))
{ {
cmOStringStream e; cmOStringStream e;
e << "Property " << p << " on target \"" e << "Property " << p << " on target \""
<< this->GetName() << "\" does\nnot match the " << tgt->GetName() << "\" does\nnot match the "
"INTERFACE_" << p << " property requirement\nof " "INTERFACE_" << p << " property requirement\nof "
"dependency \"" << li->Target->GetName() << "\".\n"; "dependency \"" << li->Target->GetName() << "\".\n";
cmSystemTools::Error(e.str().c_str()); cmSystemTools::Error(e.str().c_str());
@ -4569,13 +4598,13 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
{ {
if (ifaceIsSet) if (ifaceIsSet)
{ {
if (propContent != ifacePropContent) if (!consistentProperty(propContent, ifacePropContent))
{ {
cmOStringStream e; cmOStringStream e;
e << "Property " << p << " on target \"" e << "Property " << p << " on target \""
<< this->GetName() << "\" is\nimplied to be FALSE because it " << tgt->GetName() << "\" is\nimplied to be " << defaultValue
"was used to determine the link libraries\nalready. The " << " because it was used to determine the link libraries\n"
"INTERFACE_" << p << " property on\ndependency \"" "already. The INTERFACE_" << p << " property on\ndependency \""
<< li->Target->GetName() << "\" is in conflict.\n"; << li->Target->GetName() << "\" is in conflict.\n";
cmSystemTools::Error(e.str().c_str()); cmSystemTools::Error(e.str().c_str());
break; break;
@ -4598,13 +4627,13 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
{ {
if (propInitialized) if (propInitialized)
{ {
if (propContent != ifacePropContent) if (!consistentProperty(propContent, ifacePropContent))
{ {
cmOStringStream e; cmOStringStream e;
e << "The INTERFACE_" << p << " property of \"" e << "The INTERFACE_" << p << " property of \""
<< li->Target->GetName() << "\" does\nnot agree with the value " << li->Target->GetName() << "\" does\nnot agree with the value "
"of " << p << " already determined\nfor \"" "of " << p << " already determined\nfor \""
<< this->GetName() << "\".\n"; << tgt->GetName() << "\".\n";
cmSystemTools::Error(e.str().c_str()); cmSystemTools::Error(e.str().c_str());
break; break;
} }
@ -4630,6 +4659,14 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
return propContent; return propContent;
} }
//----------------------------------------------------------------------------
bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
const char *config)
{
return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE",
0);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool isLinkDependentProperty(cmTarget *tgt, const std::string &p, bool isLinkDependentProperty(cmTarget *tgt, const std::string &p,
const char *interfaceProperty, const char *interfaceProperty,
@ -5417,6 +5454,64 @@ std::string cmTarget::CheckCMP0004(std::string const& item)
return lib; return lib;
} }
template<typename PropertyType>
PropertyType getLinkInterfaceDependentProperty(cmTarget *tgt,
const std::string prop,
const char *config,
PropertyType *);
template<>
bool getLinkInterfaceDependentProperty(cmTarget *tgt,
const std::string prop,
const char *config, bool *)
{
return tgt->GetLinkInterfaceDependentBoolProperty(prop, config);
}
//----------------------------------------------------------------------------
template<typename PropertyType>
void checkPropertyConsistency(cmTarget *depender, cmTarget *dependee,
const char *propName,
std::set<cmStdString> &emitted,
const char *config,
PropertyType *)
{
const char *prop = dependee->GetProperty(propName);
if (!prop)
{
return;
}
std::vector<std::string> props;
cmSystemTools::ExpandListArgument(prop, props);
for(std::vector<std::string>::iterator pi = props.begin();
pi != props.end(); ++pi)
{
if (depender->GetMakefile()->GetCMakeInstance()
->GetIsPropertyDefined(pi->c_str(),
cmProperty::TARGET))
{
cmOStringStream e;
e << "Target \"" << dependee->GetName() << "\" has property \""
<< *pi << "\" listed in its " << propName << " property. "
"This is not allowed. Only user-defined properties may appear "
"listed in the " << propName << " property.";
depender->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
if(emitted.insert(*pi).second)
{
getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config,
0);
if (cmSystemTools::GetErrorOccuredFlag())
{
return;
}
}
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info,
const char* config) const char* config)
@ -5433,41 +5528,16 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info,
{ {
continue; continue;
} }
const char *prop = li->Target->GetProperty("COMPATIBLE_INTERFACE_BOOL");
if (!prop)
{
continue;
}
std::vector<std::string> props; checkPropertyConsistency<bool>(this, li->Target,
cmSystemTools::ExpandListArgument(prop, props); "COMPATIBLE_INTERFACE_BOOL",
emitted, config, 0);
for(std::vector<std::string>::iterator pi = props.begin();
pi != props.end(); ++pi)
{
if (this->Makefile->GetCMakeInstance()
->GetIsPropertyDefined(pi->c_str(),
cmProperty::TARGET))
{
cmOStringStream e;
e << "Target \"" << li->Target->GetName() << "\" has property \""
<< *pi << "\" listed in its COMPATIBLE_INTERFACE_BOOL property. "
"This is not allowed. Only user-defined properties may appear "
"listed in the COMPATIBLE_INTERFACE_BOOL property.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
if(emitted.insert(*pi).second)
{
this->GetLinkInterfaceDependentBoolProperty(*pi, config);
if (cmSystemTools::GetErrorOccuredFlag()) if (cmSystemTools::GetErrorOccuredFlag())
{ {
return; return;
} }
} }
} }
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmComputeLinkInformation* cmComputeLinkInformation*