diff options
author | Stephen Kelly <steveire@gmail.com> | 2015-08-04 17:19:43 (GMT) |
---|---|---|
committer | Stephen Kelly <steveire@gmail.com> | 2015-08-05 16:20:45 (GMT) |
commit | 5ff813c7a62d6c37b86bbf9a988a91baa4d5b9e6 (patch) | |
tree | cbffae918664d4c8ddd0b605585916d79643ee0d /Source/cmGeneratorTarget.cxx | |
parent | 38d4ba3564b9a37f8042888ffd63bf736852b6b8 (diff) | |
download | CMake-5ff813c7a62d6c37b86bbf9a988a91baa4d5b9e6.zip CMake-5ff813c7a62d6c37b86bbf9a988a91baa4d5b9e6.tar.gz CMake-5ff813c7a62d6c37b86bbf9a988a91baa4d5b9e6.tar.bz2 |
cmGeneratorTarget: Move LinkInterfaceDependent methods from cmTarget.
Diffstat (limited to 'Source/cmGeneratorTarget.cxx')
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 413 |
1 files changed, 405 insertions, 8 deletions
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index a7b0349..a9245c0 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -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; @@ -1762,6 +1760,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 { |