cmGeneratorTarget: Move LinkInterfaceDependent methods from cmTarget.
This commit is contained in:
parent
38d4ba3564
commit
5ff813c7a6
|
@ -1142,7 +1142,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
|||
context->Config))
|
||||
{
|
||||
context->HadContextSensitiveCondition = true;
|
||||
return target->GetLinkInterfaceDependentBoolProperty(
|
||||
return gtgt->GetLinkInterfaceDependentBoolProperty(
|
||||
propertyName,
|
||||
context->Config) ? "1" : "0";
|
||||
}
|
||||
|
@ -1151,7 +1151,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
|||
{
|
||||
context->HadContextSensitiveCondition = true;
|
||||
const char *propContent =
|
||||
target->GetLinkInterfaceDependentStringProperty(
|
||||
gtgt->GetLinkInterfaceDependentStringProperty(
|
||||
propertyName,
|
||||
context->Config);
|
||||
return propContent ? propContent : "";
|
||||
|
@ -1161,7 +1161,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
|||
{
|
||||
context->HadContextSensitiveCondition = true;
|
||||
const char *propContent =
|
||||
target->GetLinkInterfaceDependentNumberMinProperty(
|
||||
gtgt->GetLinkInterfaceDependentNumberMinProperty(
|
||||
propertyName,
|
||||
context->Config);
|
||||
return propContent ? propContent : "";
|
||||
|
@ -1171,7 +1171,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
|||
{
|
||||
context->HadContextSensitiveCondition = true;
|
||||
const char *propContent =
|
||||
target->GetLinkInterfaceDependentNumberMaxProperty(
|
||||
gtgt->GetLinkInterfaceDependentNumberMaxProperty(
|
||||
propertyName,
|
||||
context->Config);
|
||||
return propContent ? propContent : "";
|
||||
|
@ -1188,7 +1188,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
|||
{
|
||||
context->HadContextSensitiveCondition = true;
|
||||
const char *propContent =
|
||||
target->GetLinkInterfaceDependentNumberMinProperty(
|
||||
gtgt->GetLinkInterfaceDependentNumberMinProperty(
|
||||
propertyName,
|
||||
context->Config);
|
||||
return propContent ? propContent : "";
|
||||
|
@ -1198,7 +1198,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
|||
{
|
||||
context->HadContextSensitiveCondition = true;
|
||||
const char *propContent =
|
||||
target->GetLinkInterfaceDependentNumberMaxProperty(
|
||||
gtgt->GetLinkInterfaceDependentNumberMaxProperty(
|
||||
propertyName,
|
||||
context->Config);
|
||||
return propContent ? propContent : "";
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <queue>
|
||||
|
||||
#include <errno.h>
|
||||
#include "assert.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -753,8 +754,7 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string> &result,
|
|||
const std::string& config) const
|
||||
{
|
||||
const char *prop
|
||||
= this->Target->
|
||||
GetLinkInterfaceDependentStringProperty("AUTOUIC_OPTIONS",
|
||||
= this->GetLinkInterfaceDependentStringProperty("AUTOUIC_OPTIONS",
|
||||
config);
|
||||
if (!prop)
|
||||
{
|
||||
|
@ -1537,7 +1537,7 @@ bool getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
|
|||
const std::string& config,
|
||||
cmTarget::CompatibleType, bool *)
|
||||
{
|
||||
return tgt->Target->GetLinkInterfaceDependentBoolProperty(prop, config);
|
||||
return tgt->GetLinkInterfaceDependentBoolProperty(prop, config);
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -1553,13 +1553,11 @@ const char * getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
|
|||
assert(0 && "String compatibility check function called for boolean");
|
||||
return 0;
|
||||
case cmTarget::StringType:
|
||||
return tgt->Target->GetLinkInterfaceDependentStringProperty(prop, config);
|
||||
return tgt->GetLinkInterfaceDependentStringProperty(prop, config);
|
||||
case cmTarget::NumberMinType:
|
||||
return tgt->Target
|
||||
->GetLinkInterfaceDependentNumberMinProperty(prop, config);
|
||||
return tgt->GetLinkInterfaceDependentNumberMinProperty(prop, config);
|
||||
case cmTarget::NumberMaxType:
|
||||
return tgt->Target
|
||||
->GetLinkInterfaceDependentNumberMaxProperty(prop, config);
|
||||
return tgt->GetLinkInterfaceDependentNumberMaxProperty(prop, config);
|
||||
}
|
||||
assert(0 && "Unreachable!");
|
||||
return 0;
|
||||
|
@ -1761,6 +1759,405 @@ void cmGeneratorTarget::CheckPropertyCompatibility(
|
|||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string compatibilityType(cmTarget::CompatibleType t)
|
||||
{
|
||||
switch(t)
|
||||
{
|
||||
case cmTarget::BoolType:
|
||||
return "Boolean compatibility";
|
||||
case cmTarget::StringType:
|
||||
return "String compatibility";
|
||||
case cmTarget::NumberMaxType:
|
||||
return "Numeric maximum compatibility";
|
||||
case cmTarget::NumberMinType:
|
||||
return "Numeric minimum compatibility";
|
||||
}
|
||||
assert(0 && "Unreachable!");
|
||||
return "";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string compatibilityAgree(cmTarget::CompatibleType t, bool dominant)
|
||||
{
|
||||
switch(t)
|
||||
{
|
||||
case cmTarget::BoolType:
|
||||
case cmTarget::StringType:
|
||||
return dominant ? "(Disagree)\n" : "(Agree)\n";
|
||||
case cmTarget::NumberMaxType:
|
||||
case cmTarget::NumberMinType:
|
||||
return dominant ? "(Dominant)\n" : "(Ignored)\n";
|
||||
}
|
||||
assert(0 && "Unreachable!");
|
||||
return "";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<typename PropertyType>
|
||||
PropertyType getTypedProperty(cmTarget const* tgt, const std::string& prop);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<>
|
||||
bool getTypedProperty<bool>(cmTarget const* tgt, const std::string& prop)
|
||||
{
|
||||
return tgt->GetPropertyAsBool(prop);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<>
|
||||
const char *getTypedProperty<const char *>(cmTarget const* tgt,
|
||||
const std::string& prop)
|
||||
{
|
||||
return tgt->GetProperty(prop);
|
||||
}
|
||||
|
||||
template<typename PropertyType>
|
||||
std::string valueAsString(PropertyType);
|
||||
template<>
|
||||
std::string valueAsString<bool>(bool value)
|
||||
{
|
||||
return value ? "TRUE" : "FALSE";
|
||||
}
|
||||
template<>
|
||||
std::string valueAsString<const char*>(const char* value)
|
||||
{
|
||||
return value ? value : "(unset)";
|
||||
}
|
||||
|
||||
template<typename PropertyType>
|
||||
PropertyType impliedValue(PropertyType);
|
||||
template<>
|
||||
bool impliedValue<bool>(bool)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
template<>
|
||||
const char* impliedValue<const char*>(const char*)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<typename PropertyType>
|
||||
std::pair<bool, PropertyType> consistentProperty(PropertyType lhs,
|
||||
PropertyType rhs,
|
||||
cmTarget::CompatibleType t);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<>
|
||||
std::pair<bool, bool> consistentProperty(bool lhs, bool rhs,
|
||||
cmTarget::CompatibleType)
|
||||
{
|
||||
return std::make_pair(lhs == rhs, lhs);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::pair<bool, const char*> consistentStringProperty(const char *lhs,
|
||||
const char *rhs)
|
||||
{
|
||||
const bool b = strcmp(lhs, rhs) == 0;
|
||||
return std::make_pair(b, b ? lhs : 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::pair<bool, const char*> consistentNumberProperty(const char *lhs,
|
||||
const char *rhs,
|
||||
cmTarget::CompatibleType t)
|
||||
{
|
||||
char *pEnd;
|
||||
|
||||
const char* const null_ptr = 0;
|
||||
|
||||
long lnum = strtol(lhs, &pEnd, 0);
|
||||
if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE)
|
||||
{
|
||||
return std::pair<bool, const char*>(false, null_ptr);
|
||||
}
|
||||
|
||||
long rnum = strtol(rhs, &pEnd, 0);
|
||||
if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE)
|
||||
{
|
||||
return std::pair<bool, const char*>(false, null_ptr);
|
||||
}
|
||||
|
||||
if (t == cmTarget::NumberMaxType)
|
||||
{
|
||||
return std::make_pair(true, std::max(lnum, rnum) == lnum ? lhs : rhs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::make_pair(true, std::min(lnum, rnum) == lnum ? lhs : rhs);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<>
|
||||
std::pair<bool, const char*> consistentProperty(const char *lhs,
|
||||
const char *rhs,
|
||||
cmTarget::CompatibleType t)
|
||||
{
|
||||
if (!lhs && !rhs)
|
||||
{
|
||||
return std::make_pair(true, lhs);
|
||||
}
|
||||
if (!lhs)
|
||||
{
|
||||
return std::make_pair(true, rhs);
|
||||
}
|
||||
if (!rhs)
|
||||
{
|
||||
return std::make_pair(true, lhs);
|
||||
}
|
||||
|
||||
const char* const null_ptr = 0;
|
||||
|
||||
switch(t)
|
||||
{
|
||||
case cmTarget::BoolType:
|
||||
assert(0 && "consistentProperty for strings called with BoolType");
|
||||
return std::pair<bool, const char*>(false, null_ptr);
|
||||
case cmTarget::StringType:
|
||||
return consistentStringProperty(lhs, rhs);
|
||||
case cmTarget::NumberMinType:
|
||||
case cmTarget::NumberMaxType:
|
||||
return consistentNumberProperty(lhs, rhs, t);
|
||||
}
|
||||
assert(0 && "Unreachable!");
|
||||
return std::pair<bool, const char*>(false, null_ptr);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<typename PropertyType>
|
||||
PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
|
||||
const std::string &p,
|
||||
const std::string& config,
|
||||
const char *defaultValue,
|
||||
cmTarget::CompatibleType t,
|
||||
PropertyType *)
|
||||
{
|
||||
PropertyType propContent = getTypedProperty<PropertyType>(tgt, p);
|
||||
const bool explicitlySet = tgt->GetProperties()
|
||||
.find(p)
|
||||
!= tgt->GetProperties().end();
|
||||
const bool impliedByUse =
|
||||
tgt->IsNullImpliedByLinkLibraries(p);
|
||||
assert((impliedByUse ^ explicitlySet)
|
||||
|| (!impliedByUse && !explicitlySet));
|
||||
|
||||
std::vector<cmTarget const*> const& deps =
|
||||
tgt->GetLinkImplementationClosure(config);
|
||||
|
||||
if(deps.empty())
|
||||
{
|
||||
return propContent;
|
||||
}
|
||||
bool propInitialized = explicitlySet;
|
||||
|
||||
std::string report = " * Target \"";
|
||||
report += tgt->GetName();
|
||||
if (explicitlySet)
|
||||
{
|
||||
report += "\" has property content \"";
|
||||
report += valueAsString<PropertyType>(propContent);
|
||||
report += "\"\n";
|
||||
}
|
||||
else if (impliedByUse)
|
||||
{
|
||||
report += "\" property is implied by use.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
report += "\" property not set.\n";
|
||||
}
|
||||
|
||||
std::string interfaceProperty = "INTERFACE_" + p;
|
||||
for(std::vector<cmTarget const*>::const_iterator li =
|
||||
deps.begin();
|
||||
li != deps.end(); ++li)
|
||||
{
|
||||
// An error should be reported if one dependency
|
||||
// has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other
|
||||
// has INTERFACE_POSITION_INDEPENDENT_CODE OFF, or if the
|
||||
// target itself has a POSITION_INDEPENDENT_CODE which disagrees
|
||||
// with a dependency.
|
||||
|
||||
cmTarget const* theTarget = *li;
|
||||
|
||||
const bool ifaceIsSet = theTarget->GetProperties()
|
||||
.find(interfaceProperty)
|
||||
!= theTarget->GetProperties().end();
|
||||
PropertyType ifacePropContent =
|
||||
getTypedProperty<PropertyType>(theTarget,
|
||||
interfaceProperty);
|
||||
|
||||
std::string reportEntry;
|
||||
if (ifaceIsSet)
|
||||
{
|
||||
reportEntry += " * Target \"";
|
||||
reportEntry += theTarget->GetName();
|
||||
reportEntry += "\" property value \"";
|
||||
reportEntry += valueAsString<PropertyType>(ifacePropContent);
|
||||
reportEntry += "\" ";
|
||||
}
|
||||
|
||||
if (explicitlySet)
|
||||
{
|
||||
if (ifaceIsSet)
|
||||
{
|
||||
std::pair<bool, PropertyType> consistent =
|
||||
consistentProperty(propContent,
|
||||
ifacePropContent, t);
|
||||
report += reportEntry;
|
||||
report += compatibilityAgree(t, propContent != consistent.second);
|
||||
if (!consistent.first)
|
||||
{
|
||||
std::ostringstream e;
|
||||
e << "Property " << p << " on target \""
|
||||
<< tgt->GetName() << "\" does\nnot match the "
|
||||
"INTERFACE_" << p << " property requirement\nof "
|
||||
"dependency \"" << theTarget->GetName() << "\".\n";
|
||||
cmSystemTools::Error(e.str().c_str());
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
propContent = consistent.second;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Explicitly set on target and not set in iface. Can't disagree.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (impliedByUse)
|
||||
{
|
||||
propContent = impliedValue<PropertyType>(propContent);
|
||||
|
||||
if (ifaceIsSet)
|
||||
{
|
||||
std::pair<bool, PropertyType> consistent =
|
||||
consistentProperty(propContent,
|
||||
ifacePropContent, t);
|
||||
report += reportEntry;
|
||||
report += compatibilityAgree(t, propContent != consistent.second);
|
||||
if (!consistent.first)
|
||||
{
|
||||
std::ostringstream e;
|
||||
e << "Property " << p << " on target \""
|
||||
<< tgt->GetName() << "\" is\nimplied to be " << defaultValue
|
||||
<< " because it was used to determine the link libraries\n"
|
||||
"already. The INTERFACE_" << p << " property on\ndependency \""
|
||||
<< theTarget->GetName() << "\" is in conflict.\n";
|
||||
cmSystemTools::Error(e.str().c_str());
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
propContent = consistent.second;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Implicitly set on target and not set in iface. Can't disagree.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ifaceIsSet)
|
||||
{
|
||||
if (propInitialized)
|
||||
{
|
||||
std::pair<bool, PropertyType> consistent =
|
||||
consistentProperty(propContent,
|
||||
ifacePropContent, t);
|
||||
report += reportEntry;
|
||||
report += compatibilityAgree(t, propContent != consistent.second);
|
||||
if (!consistent.first)
|
||||
{
|
||||
std::ostringstream e;
|
||||
e << "The INTERFACE_" << p << " property of \""
|
||||
<< theTarget->GetName() << "\" does\nnot agree with the value "
|
||||
"of " << p << " already determined\nfor \""
|
||||
<< tgt->GetName() << "\".\n";
|
||||
cmSystemTools::Error(e.str().c_str());
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
propContent = consistent.second;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
report += reportEntry + "(Interface set)\n";
|
||||
propContent = ifacePropContent;
|
||||
propInitialized = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not set. Nothing to agree on.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tgt->ReportPropertyOrigin(p, valueAsString<PropertyType>(propContent),
|
||||
report, compatibilityType(t));
|
||||
return propContent;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmGeneratorTarget::GetLinkInterfaceDependentBoolProperty(
|
||||
const std::string &p, const std::string& config) const
|
||||
{
|
||||
return checkInterfacePropertyCompatibility<bool>(this->Target, p, config,
|
||||
"FALSE",
|
||||
cmTarget::BoolType, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const char* cmGeneratorTarget::GetLinkInterfaceDependentStringProperty(
|
||||
const std::string &p,
|
||||
const std::string& config) const
|
||||
{
|
||||
return checkInterfacePropertyCompatibility<const char *>(this->Target,
|
||||
p,
|
||||
config,
|
||||
"empty",
|
||||
cmTarget::StringType, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const char * cmGeneratorTarget::GetLinkInterfaceDependentNumberMinProperty(
|
||||
const std::string &p,
|
||||
const std::string& config) const
|
||||
{
|
||||
return checkInterfacePropertyCompatibility<const char *>(this->Target,
|
||||
p,
|
||||
config,
|
||||
"empty",
|
||||
cmTarget::NumberMinType, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const char * cmGeneratorTarget::GetLinkInterfaceDependentNumberMaxProperty(
|
||||
const std::string &p,
|
||||
const std::string& config) const
|
||||
{
|
||||
return checkInterfacePropertyCompatibility<const char *>(this->Target,
|
||||
p,
|
||||
config,
|
||||
"empty",
|
||||
cmTarget::NumberMaxType, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmComputeLinkInformation*
|
||||
cmGeneratorTarget::GetLinkInformation(const std::string& config) const
|
||||
|
|
|
@ -96,6 +96,17 @@ public:
|
|||
bool IsLinkInterfaceDependentNumberMaxProperty(const std::string &p,
|
||||
const std::string& config) const;
|
||||
|
||||
bool GetLinkInterfaceDependentBoolProperty(const std::string &p,
|
||||
const std::string& config) const;
|
||||
|
||||
const char *GetLinkInterfaceDependentStringProperty(const std::string &p,
|
||||
const std::string& config) const;
|
||||
const char *GetLinkInterfaceDependentNumberMinProperty(const std::string &p,
|
||||
const std::string& config) const;
|
||||
const char *GetLinkInterfaceDependentNumberMaxProperty(const std::string &p,
|
||||
const std::string& config) const;
|
||||
|
||||
|
||||
/** Get the full path to the target according to the settings in its
|
||||
makefile and the configuration type. */
|
||||
std::string GetFullPath(const std::string& config="", bool implib = false,
|
||||
|
|
|
@ -2059,7 +2059,9 @@ void cmLocalGenerator::AddCMP0018Flags(std::string &flags,
|
|||
return;
|
||||
}
|
||||
|
||||
if (target->GetLinkInterfaceDependentBoolProperty(
|
||||
cmGeneratorTarget* gtgt =
|
||||
this->GlobalGenerator->GetGeneratorTarget(target);
|
||||
if (gtgt->GetLinkInterfaceDependentBoolProperty(
|
||||
"POSITION_INDEPENDENT_CODE",
|
||||
config))
|
||||
{
|
||||
|
|
|
@ -547,8 +547,11 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target)
|
|||
{
|
||||
qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR");
|
||||
}
|
||||
cmGeneratorTarget *gtgt = target->GetMakefile()
|
||||
->GetGlobalGenerator()
|
||||
->GetGeneratorTarget(target);
|
||||
if (const char *targetQtVersion =
|
||||
target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", ""))
|
||||
gtgt->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", ""))
|
||||
{
|
||||
qtVersion = targetQtVersion;
|
||||
}
|
||||
|
@ -1150,6 +1153,9 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target)
|
|||
|
||||
std::string cmQtAutoGenerators::GetRccExecutable(cmTarget const* target)
|
||||
{
|
||||
cmGeneratorTarget *gtgt = target->GetMakefile()
|
||||
->GetGlobalGenerator()
|
||||
->GetGeneratorTarget(target);
|
||||
cmMakefile *makefile = target->GetMakefile();
|
||||
const char *qtVersion = makefile->GetDefinition("_target_qt_version");
|
||||
if (!qtVersion)
|
||||
|
@ -1160,8 +1166,7 @@ std::string cmQtAutoGenerators::GetRccExecutable(cmTarget const* target)
|
|||
qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR");
|
||||
}
|
||||
if (const char *targetQtVersion =
|
||||
target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION",
|
||||
""))
|
||||
gtgt->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", ""))
|
||||
{
|
||||
qtVersion = targetQtVersion;
|
||||
}
|
||||
|
|
|
@ -4535,141 +4535,6 @@ bool cmTarget::IsNullImpliedByLinkLibraries(const std::string &p) const
|
|||
!= this->LinkImplicitNullProperties.end();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<typename PropertyType>
|
||||
PropertyType getTypedProperty(cmTarget const* tgt, const std::string& prop);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<>
|
||||
bool getTypedProperty<bool>(cmTarget const* tgt, const std::string& prop)
|
||||
{
|
||||
return tgt->GetPropertyAsBool(prop);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<>
|
||||
const char *getTypedProperty<const char *>(cmTarget const* tgt,
|
||||
const std::string& prop)
|
||||
{
|
||||
return tgt->GetProperty(prop);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<typename PropertyType>
|
||||
std::pair<bool, PropertyType> consistentProperty(PropertyType lhs,
|
||||
PropertyType rhs,
|
||||
cmTarget::CompatibleType t);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<>
|
||||
std::pair<bool, bool> consistentProperty(bool lhs, bool rhs,
|
||||
cmTarget::CompatibleType)
|
||||
{
|
||||
return std::make_pair(lhs == rhs, lhs);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::pair<bool, const char*> consistentStringProperty(const char *lhs,
|
||||
const char *rhs)
|
||||
{
|
||||
const bool b = strcmp(lhs, rhs) == 0;
|
||||
return std::make_pair(b, b ? lhs : 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::pair<bool, const char*> consistentNumberProperty(const char *lhs,
|
||||
const char *rhs,
|
||||
cmTarget::CompatibleType t)
|
||||
{
|
||||
char *pEnd;
|
||||
|
||||
const char* const null_ptr = 0;
|
||||
|
||||
long lnum = strtol(lhs, &pEnd, 0);
|
||||
if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE)
|
||||
{
|
||||
return std::pair<bool, const char*>(false, null_ptr);
|
||||
}
|
||||
|
||||
long rnum = strtol(rhs, &pEnd, 0);
|
||||
if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE)
|
||||
{
|
||||
return std::pair<bool, const char*>(false, null_ptr);
|
||||
}
|
||||
|
||||
if (t == cmTarget::NumberMaxType)
|
||||
{
|
||||
return std::make_pair(true, std::max(lnum, rnum) == lnum ? lhs : rhs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::make_pair(true, std::min(lnum, rnum) == lnum ? lhs : rhs);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<>
|
||||
std::pair<bool, const char*> consistentProperty(const char *lhs,
|
||||
const char *rhs,
|
||||
cmTarget::CompatibleType t)
|
||||
{
|
||||
if (!lhs && !rhs)
|
||||
{
|
||||
return std::make_pair(true, lhs);
|
||||
}
|
||||
if (!lhs)
|
||||
{
|
||||
return std::make_pair(true, rhs);
|
||||
}
|
||||
if (!rhs)
|
||||
{
|
||||
return std::make_pair(true, lhs);
|
||||
}
|
||||
|
||||
const char* const null_ptr = 0;
|
||||
|
||||
switch(t)
|
||||
{
|
||||
case cmTarget::BoolType:
|
||||
assert(0 && "consistentProperty for strings called with BoolType");
|
||||
return std::pair<bool, const char*>(false, null_ptr);
|
||||
case cmTarget::StringType:
|
||||
return consistentStringProperty(lhs, rhs);
|
||||
case cmTarget::NumberMinType:
|
||||
case cmTarget::NumberMaxType:
|
||||
return consistentNumberProperty(lhs, rhs, t);
|
||||
}
|
||||
assert(0 && "Unreachable!");
|
||||
return std::pair<bool, const char*>(false, null_ptr);
|
||||
}
|
||||
|
||||
template<typename PropertyType>
|
||||
PropertyType impliedValue(PropertyType);
|
||||
template<>
|
||||
bool impliedValue<bool>(bool)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
template<>
|
||||
const char* impliedValue<const char*>(const char*)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
template<typename PropertyType>
|
||||
std::string valueAsString(PropertyType);
|
||||
template<>
|
||||
std::string valueAsString<bool>(bool value)
|
||||
{
|
||||
return value ? "TRUE" : "FALSE";
|
||||
}
|
||||
template<>
|
||||
std::string valueAsString<const char*>(const char* value)
|
||||
{
|
||||
return value ? value : "(unset)";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmTarget::ReportPropertyOrigin(const std::string &p,
|
||||
|
@ -4710,270 +4575,6 @@ cmTarget::ReportPropertyOrigin(const std::string &p,
|
|||
this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, areport);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string compatibilityType(cmTarget::CompatibleType t)
|
||||
{
|
||||
switch(t)
|
||||
{
|
||||
case cmTarget::BoolType:
|
||||
return "Boolean compatibility";
|
||||
case cmTarget::StringType:
|
||||
return "String compatibility";
|
||||
case cmTarget::NumberMaxType:
|
||||
return "Numeric maximum compatibility";
|
||||
case cmTarget::NumberMinType:
|
||||
return "Numeric minimum compatibility";
|
||||
}
|
||||
assert(0 && "Unreachable!");
|
||||
return "";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string compatibilityAgree(cmTarget::CompatibleType t, bool dominant)
|
||||
{
|
||||
switch(t)
|
||||
{
|
||||
case cmTarget::BoolType:
|
||||
case cmTarget::StringType:
|
||||
return dominant ? "(Disagree)\n" : "(Agree)\n";
|
||||
case cmTarget::NumberMaxType:
|
||||
case cmTarget::NumberMinType:
|
||||
return dominant ? "(Dominant)\n" : "(Ignored)\n";
|
||||
}
|
||||
assert(0 && "Unreachable!");
|
||||
return "";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<typename PropertyType>
|
||||
PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
|
||||
const std::string &p,
|
||||
const std::string& config,
|
||||
const char *defaultValue,
|
||||
cmTarget::CompatibleType t,
|
||||
PropertyType *)
|
||||
{
|
||||
PropertyType propContent = getTypedProperty<PropertyType>(tgt, p);
|
||||
const bool explicitlySet = tgt->GetProperties()
|
||||
.find(p)
|
||||
!= tgt->GetProperties().end();
|
||||
const bool impliedByUse =
|
||||
tgt->IsNullImpliedByLinkLibraries(p);
|
||||
assert((impliedByUse ^ explicitlySet)
|
||||
|| (!impliedByUse && !explicitlySet));
|
||||
|
||||
std::vector<cmTarget const*> const& deps =
|
||||
tgt->GetLinkImplementationClosure(config);
|
||||
|
||||
if(deps.empty())
|
||||
{
|
||||
return propContent;
|
||||
}
|
||||
bool propInitialized = explicitlySet;
|
||||
|
||||
std::string report = " * Target \"";
|
||||
report += tgt->GetName();
|
||||
if (explicitlySet)
|
||||
{
|
||||
report += "\" has property content \"";
|
||||
report += valueAsString<PropertyType>(propContent);
|
||||
report += "\"\n";
|
||||
}
|
||||
else if (impliedByUse)
|
||||
{
|
||||
report += "\" property is implied by use.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
report += "\" property not set.\n";
|
||||
}
|
||||
|
||||
std::string interfaceProperty = "INTERFACE_" + p;
|
||||
for(std::vector<cmTarget const*>::const_iterator li =
|
||||
deps.begin();
|
||||
li != deps.end(); ++li)
|
||||
{
|
||||
// An error should be reported if one dependency
|
||||
// has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other
|
||||
// has INTERFACE_POSITION_INDEPENDENT_CODE OFF, or if the
|
||||
// target itself has a POSITION_INDEPENDENT_CODE which disagrees
|
||||
// with a dependency.
|
||||
|
||||
cmTarget const* theTarget = *li;
|
||||
|
||||
const bool ifaceIsSet = theTarget->GetProperties()
|
||||
.find(interfaceProperty)
|
||||
!= theTarget->GetProperties().end();
|
||||
PropertyType ifacePropContent =
|
||||
getTypedProperty<PropertyType>(theTarget,
|
||||
interfaceProperty);
|
||||
|
||||
std::string reportEntry;
|
||||
if (ifaceIsSet)
|
||||
{
|
||||
reportEntry += " * Target \"";
|
||||
reportEntry += theTarget->GetName();
|
||||
reportEntry += "\" property value \"";
|
||||
reportEntry += valueAsString<PropertyType>(ifacePropContent);
|
||||
reportEntry += "\" ";
|
||||
}
|
||||
|
||||
if (explicitlySet)
|
||||
{
|
||||
if (ifaceIsSet)
|
||||
{
|
||||
std::pair<bool, PropertyType> consistent =
|
||||
consistentProperty(propContent,
|
||||
ifacePropContent, t);
|
||||
report += reportEntry;
|
||||
report += compatibilityAgree(t, propContent != consistent.second);
|
||||
if (!consistent.first)
|
||||
{
|
||||
std::ostringstream e;
|
||||
e << "Property " << p << " on target \""
|
||||
<< tgt->GetName() << "\" does\nnot match the "
|
||||
"INTERFACE_" << p << " property requirement\nof "
|
||||
"dependency \"" << theTarget->GetName() << "\".\n";
|
||||
cmSystemTools::Error(e.str().c_str());
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
propContent = consistent.second;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Explicitly set on target and not set in iface. Can't disagree.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (impliedByUse)
|
||||
{
|
||||
propContent = impliedValue<PropertyType>(propContent);
|
||||
|
||||
if (ifaceIsSet)
|
||||
{
|
||||
std::pair<bool, PropertyType> consistent =
|
||||
consistentProperty(propContent,
|
||||
ifacePropContent, t);
|
||||
report += reportEntry;
|
||||
report += compatibilityAgree(t, propContent != consistent.second);
|
||||
if (!consistent.first)
|
||||
{
|
||||
std::ostringstream e;
|
||||
e << "Property " << p << " on target \""
|
||||
<< tgt->GetName() << "\" is\nimplied to be " << defaultValue
|
||||
<< " because it was used to determine the link libraries\n"
|
||||
"already. The INTERFACE_" << p << " property on\ndependency \""
|
||||
<< theTarget->GetName() << "\" is in conflict.\n";
|
||||
cmSystemTools::Error(e.str().c_str());
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
propContent = consistent.second;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Implicitly set on target and not set in iface. Can't disagree.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ifaceIsSet)
|
||||
{
|
||||
if (propInitialized)
|
||||
{
|
||||
std::pair<bool, PropertyType> consistent =
|
||||
consistentProperty(propContent,
|
||||
ifacePropContent, t);
|
||||
report += reportEntry;
|
||||
report += compatibilityAgree(t, propContent != consistent.second);
|
||||
if (!consistent.first)
|
||||
{
|
||||
std::ostringstream e;
|
||||
e << "The INTERFACE_" << p << " property of \""
|
||||
<< theTarget->GetName() << "\" does\nnot agree with the value "
|
||||
"of " << p << " already determined\nfor \""
|
||||
<< tgt->GetName() << "\".\n";
|
||||
cmSystemTools::Error(e.str().c_str());
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
propContent = consistent.second;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
report += reportEntry + "(Interface set)\n";
|
||||
propContent = ifacePropContent;
|
||||
propInitialized = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not set. Nothing to agree on.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tgt->ReportPropertyOrigin(p, valueAsString<PropertyType>(propContent),
|
||||
report, compatibilityType(t));
|
||||
return propContent;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
|
||||
const std::string& config) const
|
||||
{
|
||||
return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE",
|
||||
BoolType, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const char * cmTarget::GetLinkInterfaceDependentStringProperty(
|
||||
const std::string &p,
|
||||
const std::string& config) const
|
||||
{
|
||||
return checkInterfacePropertyCompatibility<const char *>(this,
|
||||
p,
|
||||
config,
|
||||
"empty",
|
||||
StringType, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const char * cmTarget::GetLinkInterfaceDependentNumberMinProperty(
|
||||
const std::string &p,
|
||||
const std::string& config) const
|
||||
{
|
||||
return checkInterfacePropertyCompatibility<const char *>(this,
|
||||
p,
|
||||
config,
|
||||
"empty",
|
||||
NumberMinType, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const char * cmTarget::GetLinkInterfaceDependentNumberMaxProperty(
|
||||
const std::string &p,
|
||||
const std::string& config) const
|
||||
{
|
||||
return checkInterfacePropertyCompatibility<const char *>(this,
|
||||
p,
|
||||
config,
|
||||
"empty",
|
||||
NumberMaxType, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmTarget::GetObjectLibrariesCMP0026(std::vector<cmTarget*>& objlibs) const
|
||||
|
|
|
@ -553,15 +553,6 @@ public:
|
|||
const std::string& config) const;
|
||||
|
||||
bool IsNullImpliedByLinkLibraries(const std::string &p) const;
|
||||
bool GetLinkInterfaceDependentBoolProperty(const std::string &p,
|
||||
const std::string& config) const;
|
||||
|
||||
const char *GetLinkInterfaceDependentStringProperty(const std::string &p,
|
||||
const std::string& config) const;
|
||||
const char *GetLinkInterfaceDependentNumberMinProperty(const std::string &p,
|
||||
const std::string& config) const;
|
||||
const char *GetLinkInterfaceDependentNumberMaxProperty(const std::string &p,
|
||||
const std::string& config) const;
|
||||
|
||||
std::string GetDebugGeneratorExpressions(const std::string &value,
|
||||
cmTarget::LinkLibraryType llt) const;
|
||||
|
|
Loading…
Reference in New Issue