diff options
author | Brad King <brad.king@kitware.com> | 2013-10-26 14:28:30 (GMT) |
---|---|---|
committer | CMake Topic Stage <kwrobot@kitware.com> | 2013-10-26 14:28:30 (GMT) |
commit | 4025013dd78abeaef772eee1fc532ce275ae4216 (patch) | |
tree | 313d9ed0302f457507c375a1ea32f23db6d47ff5 /Source | |
parent | 5f789db847a86cbdfb94fcf1abd4d561a6942d65 (diff) | |
parent | ff6c401309761f0c0061f1084f2e3150038962a5 (diff) | |
download | CMake-4025013dd78abeaef772eee1fc532ce275ae4216.zip CMake-4025013dd78abeaef772eee1fc532ce275ae4216.tar.gz CMake-4025013dd78abeaef772eee1fc532ce275ae4216.tar.bz2 |
Merge topic 'compatible-interface-numbers'
ff6c401 cmTarget: Add interface for compatible numeric properties
e4e20c1 cmTarget: Add enumeration for consistency to expect from properties.
9877769 cmTarget: Assign consistent content back to the property being evaluated.
816b4a8 cmTarget: Make consistentProperty return consistent content.
030800a cmTarget: Add a template to create correct implied content.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmExportFileGenerator.cxx | 14 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionEvaluator.cxx | 44 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 319 | ||||
-rw-r--r-- | Source/cmTarget.h | 8 |
4 files changed, 352 insertions, 33 deletions
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index b01e499..65f1cc6 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -411,6 +411,12 @@ void getCompatibleInterfaceProperties(cmTarget *target, getPropertyContents(li->Target, "COMPATIBLE_INTERFACE_STRING", ifaceProperties); + getPropertyContents(li->Target, + "COMPATIBLE_INTERFACE_NUMBER_MIN", + ifaceProperties); + getPropertyContents(li->Target, + "COMPATIBLE_INTERFACE_NUMBER_MAX", + ifaceProperties); } } @@ -423,11 +429,19 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties( target, properties); this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_STRING", target, properties); + this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_NUMBER_MIN", + target, properties); + this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_NUMBER_MAX", + target, properties); std::set<std::string> ifaceProperties; getPropertyContents(target, "COMPATIBLE_INTERFACE_BOOL", ifaceProperties); getPropertyContents(target, "COMPATIBLE_INTERFACE_STRING", ifaceProperties); + getPropertyContents(target, "COMPATIBLE_INTERFACE_NUMBER_MIN", + ifaceProperties); + getPropertyContents(target, "COMPATIBLE_INTERFACE_NUMBER_MAX", + ifaceProperties); getCompatibleInterfaceProperties(target, ifaceProperties, 0); diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 33863f4..f92c18e 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -980,10 +980,54 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode context->Config); return propContent ? propContent : ""; } + if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName, + context->Config)) + { + context->HadContextSensitiveCondition = true; + const char *propContent = + target->GetLinkInterfaceDependentNumberMinProperty( + propertyName, + context->Config); + return propContent ? propContent : ""; + } + if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName, + context->Config)) + { + context->HadContextSensitiveCondition = true; + const char *propContent = + target->GetLinkInterfaceDependentNumberMaxProperty( + propertyName, + context->Config); + return propContent ? propContent : ""; + } return linkedTargetsContent; } + if (!target->IsImported() + && dagCheckerParent && !dagCheckerParent->EvaluatingLinkLibraries()) + { + if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName, + context->Config)) + { + context->HadContextSensitiveCondition = true; + const char *propContent = + target->GetLinkInterfaceDependentNumberMinProperty( + propertyName, + context->Config); + return propContent ? propContent : ""; + } + if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName, + context->Config)) + { + context->HadContextSensitiveCondition = true; + const char *propContent = + target->GetLinkInterfaceDependentNumberMaxProperty( + propertyName, + context->Config); + return propContent ? propContent : ""; + } + } for (size_t i = 1; i < cmArraySize(targetPropertyTransitiveWhitelist); ++i) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 70c5f84..ea0b504 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -4455,26 +4455,107 @@ const char *getTypedProperty<const char *>(cmTarget *tgt, const char *prop, return tgt->GetProperty(prop); } +enum CompatibleType +{ + BoolType, + StringType, + NumberMinType, + NumberMaxType +}; + //---------------------------------------------------------------------------- template<typename PropertyType> -bool consistentProperty(PropertyType lhs, PropertyType rhs); +PropertyType consistentProperty(PropertyType lhs, PropertyType rhs, + CompatibleType t); //---------------------------------------------------------------------------- template<> -bool consistentProperty(bool lhs, bool rhs) +bool consistentProperty(bool lhs, bool rhs, CompatibleType) { return lhs == rhs; } //---------------------------------------------------------------------------- +const char * consistentStringProperty(const char *lhs, const char *rhs) +{ + return strcmp(lhs, rhs) == 0 ? lhs : 0; +} + +#if defined(_MSC_VER) && _MSC_VER <= 1200 +template<typename T> const T& +cmMaximum(const T& l, const T& r) {return l > r ? l : r;} +template<typename T> const T& +cmMinimum(const T& l, const T& r) {return l < r ? l : r;} +#else +#define cmMinimum std::min +#define cmMaximum std::max +#endif + +//---------------------------------------------------------------------------- +const char * consistentNumberProperty(const char *lhs, const char *rhs, + CompatibleType t) +{ + double lnum; + double rnum; + if(sscanf(lhs, "%lg", &lnum) != 1 || + sscanf(rhs, "%lg", &rnum) != 1) + { + return 0; + } + + if (t == NumberMaxType) + { + return cmMaximum(lnum, rnum) == lnum ? lhs : rhs; + } + else + { + return cmMinimum(lnum, rnum) == lnum ? lhs : rhs; + } +} + +//---------------------------------------------------------------------------- template<> -bool consistentProperty(const char *lhs, const char *rhs) +const char* consistentProperty(const char *lhs, const char *rhs, + CompatibleType t) { if (!lhs && !rhs) - return true; - if (!lhs || !rhs) - return false; - return strcmp(lhs, rhs) == 0; + { + return ""; + } + if (!lhs) + { + return rhs ? rhs : ""; + } + if (!rhs) + { + return lhs ? lhs : ""; + } + switch(t) + { + case BoolType: + assert(!"consistentProperty for strings called with BoolType"); + return 0; + case StringType: + return consistentStringProperty(lhs, rhs); + case NumberMinType: + case NumberMaxType: + return consistentNumberProperty(lhs, rhs, t); + } + assert(!"Unreachable!"); + return 0; +} + +template<typename PropertyType> +PropertyType impliedValue(PropertyType); +template<> +bool impliedValue<bool>(bool) +{ + return false; +} +template<> +const char* impliedValue<const char*>(const char*) +{ + return ""; } //---------------------------------------------------------------------------- @@ -4483,6 +4564,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt, const std::string &p, const char *config, const char *defaultValue, + CompatibleType t, PropertyType *) { PropertyType propContent = getTypedProperty<PropertyType>(tgt, p.c_str(), @@ -4528,7 +4610,9 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt, { if (ifaceIsSet) { - if (!consistentProperty(propContent, ifacePropContent)) + PropertyType consistent = consistentProperty(propContent, + ifacePropContent, t); + if (!consistent) { cmOStringStream e; e << "Property " << p << " on target \"" @@ -4541,6 +4625,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt, else { // Agree + propContent = consistent; continue; } } @@ -4552,9 +4637,12 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt, } else if (impliedByUse) { + propContent = impliedValue<PropertyType>(propContent); if (ifaceIsSet) { - if (!consistentProperty(propContent, ifacePropContent)) + PropertyType consistent = consistentProperty(propContent, + ifacePropContent, t); + if (!consistent) { cmOStringStream e; e << "Property " << p << " on target \"" @@ -4568,6 +4656,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt, else { // Agree + propContent = consistent; continue; } } @@ -4583,7 +4672,9 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt, { if (propInitialized) { - if (!consistentProperty(propContent, ifacePropContent)) + PropertyType consistent = consistentProperty(propContent, + ifacePropContent, t); + if (!consistent) { cmOStringStream e; e << "The INTERFACE_" << p << " property of \"" @@ -4596,6 +4687,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt, else { // Agree. + propContent = consistent; continue; } } @@ -4620,7 +4712,7 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, const char *config) { return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE", - 0); + BoolType, 0); } //---------------------------------------------------------------------------- @@ -4631,7 +4723,32 @@ const char * cmTarget::GetLinkInterfaceDependentStringProperty( return checkInterfacePropertyCompatibility<const char *>(this, p, config, - "empty", 0); + "empty", + StringType, 0); +} + +//---------------------------------------------------------------------------- +const char * cmTarget::GetLinkInterfaceDependentNumberMinProperty( + const std::string &p, + const char *config) +{ + return checkInterfacePropertyCompatibility<const char *>(this, + p, + config, + "empty", + NumberMinType, 0); +} + +//---------------------------------------------------------------------------- +const char * cmTarget::GetLinkInterfaceDependentNumberMaxProperty( + const std::string &p, + const char *config) +{ + return checkInterfacePropertyCompatibility<const char *>(this, + p, + config, + "empty", + NumberMaxType, 0); } //---------------------------------------------------------------------------- @@ -4703,6 +4820,30 @@ bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p, } //---------------------------------------------------------------------------- +bool cmTarget::IsLinkInterfaceDependentNumberMinProperty(const std::string &p, + const char *config) +{ + if (this->TargetTypeValue == OBJECT_LIBRARY) + { + return false; + } + return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_NUMBER_MIN", + config); +} + +//---------------------------------------------------------------------------- +bool cmTarget::IsLinkInterfaceDependentNumberMaxProperty(const std::string &p, + const char *config) +{ + if (this->TargetTypeValue == OBJECT_LIBRARY) + { + return false; + } + return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_NUMBER_MAX", + config); +} + +//---------------------------------------------------------------------------- void cmTarget::GetLanguages(std::set<cmStdString>& languages) const { for(std::vector<cmSourceFile*>::const_iterator @@ -5680,23 +5821,39 @@ template<typename PropertyType> PropertyType getLinkInterfaceDependentProperty(cmTarget *tgt, const std::string prop, const char *config, + CompatibleType, PropertyType *); template<> bool getLinkInterfaceDependentProperty(cmTarget *tgt, - const std::string prop, - const char *config, bool *) + const std::string prop, + const char *config, + CompatibleType, bool *) { return tgt->GetLinkInterfaceDependentBoolProperty(prop, config); } template<> const char * getLinkInterfaceDependentProperty(cmTarget *tgt, - const std::string prop, - const char *config, - const char **) + const std::string prop, + const char *config, + CompatibleType t, + const char **) { - return tgt->GetLinkInterfaceDependentStringProperty(prop, config); + switch(t) + { + case BoolType: + assert(!"String compatibility check function called for boolean"); + return 0; + case StringType: + return tgt->GetLinkInterfaceDependentStringProperty(prop, config); + case NumberMinType: + return tgt->GetLinkInterfaceDependentNumberMinProperty(prop, config); + case NumberMaxType: + return tgt->GetLinkInterfaceDependentNumberMaxProperty(prop, config); + } + assert(!"Unreachable!"); + return 0; } //---------------------------------------------------------------------------- @@ -5705,6 +5862,7 @@ void checkPropertyConsistency(cmTarget *depender, cmTarget *dependee, const char *propName, std::set<cmStdString> &emitted, const char *config, + CompatibleType t, PropertyType *) { const char *prop = dependee->GetProperty(propName); @@ -5737,7 +5895,7 @@ void checkPropertyConsistency(cmTarget *depender, cmTarget *dependee, if(emitted.insert(*pi).second) { getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config, - 0); + t, 0); if (cmSystemTools::GetErrorOccuredFlag()) { return; @@ -5746,6 +5904,50 @@ void checkPropertyConsistency(cmTarget *depender, cmTarget *dependee, } } +static cmStdString intersect(const std::set<cmStdString> &s1, + const std::set<cmStdString> &s2) +{ + std::set<cmStdString> intersect; + std::set_intersection(s1.begin(),s1.end(), + s2.begin(),s2.end(), + std::inserter(intersect,intersect.begin())); + if (!intersect.empty()) + { + return *intersect.begin(); + } + return ""; +} +static cmStdString intersect(const std::set<cmStdString> &s1, + const std::set<cmStdString> &s2, + const std::set<cmStdString> &s3) +{ + cmStdString result; + result = intersect(s1, s2); + if (!result.empty()) + return result; + result = intersect(s1, s3); + if (!result.empty()) + return result; + return intersect(s2, s3); +} +static cmStdString intersect(const std::set<cmStdString> &s1, + const std::set<cmStdString> &s2, + const std::set<cmStdString> &s3, + const std::set<cmStdString> &s4) +{ + cmStdString result; + result = intersect(s1, s2); + if (!result.empty()) + return result; + result = intersect(s1, s3); + if (!result.empty()) + return result; + result = intersect(s1, s4); + if (!result.empty()) + return result; + return intersect(s2, s3, s4); +} + //---------------------------------------------------------------------------- void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, const char* config) @@ -5754,6 +5956,8 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, std::set<cmStdString> emittedBools; std::set<cmStdString> emittedStrings; + std::set<cmStdString> emittedMinNumbers; + std::set<cmStdString> emittedMaxNumbers; for(cmComputeLinkInformation::ItemVector::const_iterator li = deps.begin(); @@ -5766,35 +5970,84 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, checkPropertyConsistency<bool>(this, li->Target, "COMPATIBLE_INTERFACE_BOOL", - emittedBools, config, 0); + emittedBools, config, BoolType, 0); if (cmSystemTools::GetErrorOccuredFlag()) { return; } checkPropertyConsistency<const char *>(this, li->Target, "COMPATIBLE_INTERFACE_STRING", - emittedStrings, config, 0); + emittedStrings, config, + StringType, 0); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + checkPropertyConsistency<const char *>(this, li->Target, + "COMPATIBLE_INTERFACE_NUMBER_MIN", + emittedMinNumbers, config, + NumberMinType, 0); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + checkPropertyConsistency<const char *>(this, li->Target, + "COMPATIBLE_INTERFACE_NUMBER_MAX", + emittedMaxNumbers, config, + NumberMaxType, 0); if (cmSystemTools::GetErrorOccuredFlag()) { return; } } - for(std::set<cmStdString>::const_iterator li = emittedBools.begin(); - li != emittedBools.end(); ++li) + std::string prop = intersect(emittedBools, + emittedStrings, + emittedMinNumbers, + emittedMaxNumbers); + + if (!prop.empty()) { - const std::set<cmStdString>::const_iterator si = emittedStrings.find(*li); - if (si != emittedStrings.end()) + std::set<std::string> props; + std::set<cmStdString>::const_iterator i = emittedBools.find(prop); + if (i != emittedBools.end()) { - cmOStringStream e; - e << "Property \"" << *li << "\" appears in both the " - "COMPATIBLE_INTERFACE_BOOL and the COMPATIBLE_INTERFACE_STRING " - "property in the dependencies of target \"" << this->GetName() << - "\". This is not allowed. A property may only require compatibility " - "in a boolean interpretation or a string interpretation, but not both."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); - break; + props.insert("COMPATIBLE_INTERFACE_BOOL"); + } + i = emittedStrings.find(prop); + if (i != emittedStrings.end()) + { + props.insert("COMPATIBLE_INTERFACE_STRING"); + } + i = emittedMinNumbers.find(prop); + if (i != emittedMinNumbers.end()) + { + props.insert("COMPATIBLE_INTERFACE_NUMBER_MIN"); + } + i = emittedMaxNumbers.find(prop); + if (i != emittedMaxNumbers.end()) + { + props.insert("COMPATIBLE_INTERFACE_NUMBER_MAX"); } + + std::string propsString = *props.begin(); + props.erase(props.begin()); + while (props.size() > 1) + { + propsString += ", " + *props.begin(); + props.erase(props.begin()); + } + if (props.size() == 1) + { + propsString += " and the " + *props.begin(); + } + cmOStringStream e; + e << "Property \"" << prop << "\" appears in both the " + << propsString << + " property in the dependencies of target \"" << this->GetName() << + "\". This is not allowed. A property may only require compatibility " + "in a boolean interpretation or a string interpretation, but not both."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); } } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index e8f4e08..9d62f5f 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -536,12 +536,20 @@ public: const char *config); bool IsLinkInterfaceDependentStringProperty(const std::string &p, const char *config); + bool IsLinkInterfaceDependentNumberMinProperty(const std::string &p, + const char *config); + bool IsLinkInterfaceDependentNumberMaxProperty(const std::string &p, + const char *config); bool GetLinkInterfaceDependentBoolProperty(const std::string &p, const char *config); const char *GetLinkInterfaceDependentStringProperty(const std::string &p, const char *config); + const char *GetLinkInterfaceDependentNumberMinProperty(const std::string &p, + const char *config); + const char *GetLinkInterfaceDependentNumberMaxProperty(const std::string &p, + const char *config); std::string GetDebugGeneratorExpressions(const std::string &value, cmTarget::LinkLibraryType llt); |