diff options
author | Stephen Kelly <steveire@gmail.com> | 2013-10-22 17:51:36 (GMT) |
---|---|---|
committer | Stephen Kelly <steveire@gmail.com> | 2013-10-24 06:42:05 (GMT) |
commit | ff6c401309761f0c0061f1084f2e3150038962a5 (patch) | |
tree | f8e0aea06167be6fb1fa62a14228585083111283 /Source | |
parent | e4e20c1d194152a97043e94f1bd5ef9476812682 (diff) | |
download | CMake-ff6c401309761f0c0061f1084f2e3150038962a5.zip CMake-ff6c401309761f0c0061f1084f2e3150038962a5.tar.gz CMake-ff6c401309761f0c0061f1084f2e3150038962a5.tar.bz2 |
cmTarget: Add interface for compatible numeric properties
When using the boost MPL library, one can set a define to increase
the limit of how many variadic elements should be supported. The
default for BOOST_MPL_LIMIT_VECTOR_SIZE is 20:
http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/limit-vector-size.html
If the foo library requires that to be set to 30, and the independent
bar library requires it to be set to 40, consumers of both need to set
it to 40.
add_library(foo INTERFACE)
set_property(TARGET foo PROPERTY INTERFACE_boost_mpl_vector_size 30)
set_property(TARGET foo PROPERTY COMPATIBLE_INTERFACE_NUMBER_MAX boost_mpl_vector_size)
target_compile_definitions(foo INTERFACE BOOST_MPL_LIMIT_VECTOR_SIZE=$<TARGET_PROPERTY:boost_mpl_vector_size>)
add_library(bar INTERFACE)
set_property(TARGET bar PROPERTY INTERFACE_boost_mpl_vector_size 40)
# Technically the next two lines are redundant, but as foo and bar are
# independent, they both set these interfaces.
set_property(TARGET bar PROPERTY COMPATIBLE_INTERFACE_NUMBER_MAX boost_mpl_vector_size)
target_compile_definitions(bar INTERFACE BOOST_MPL_LIMIT_VECTOR_SIZE=$<TARGET_PROPERTY:boost_mpl_vector_size>)
add_executable(user)
target_link_libraries(user foo bar)
Because the TARGET_PROPERTY reads the boost_mpl_vector_size property
from the HEAD of the dependency graph (the user target), and because
that property appears in the COMPATIBLE_INTERFACE_NUMBER_MAX of
the dependencies of the user target, the maximum value for it is
chosen for the compile definition, ie, 40.
There are also use-cases for choosing the minimum value of a number.
In Qt, deprecated API can be disabled by version. Setting the
definition QT_DISABLE_DEPRECATED_BEFORE=0 disables no deprecated
API. Setting it to 0x501000 disables API which was deprecated before
Qt 5.1 etc.
If two dependencies require the use of API which was deprecated in
different Qt versions, then COMPATIBLE_INTERFACE_NUMBER_MIN can be
used to ensure that both can compile.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmExportFileGenerator.cxx | 14 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionEvaluator.cxx | 44 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 209 | ||||
-rw-r--r-- | Source/cmTarget.h | 8 |
4 files changed, 262 insertions, 13 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 91a7be8..c42ba95 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -4453,7 +4453,9 @@ const char *getTypedProperty<const char *>(cmTarget *tgt, const char *prop, enum CompatibleType { BoolType, - StringType + StringType, + NumberMinType, + NumberMaxType }; //---------------------------------------------------------------------------- @@ -4474,6 +4476,38 @@ 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<> const char* consistentProperty(const char *lhs, const char *rhs, @@ -4498,6 +4532,9 @@ const char* consistentProperty(const char *lhs, const char *rhs, return 0; case StringType: return consistentStringProperty(lhs, rhs); + case NumberMinType: + case NumberMaxType: + return consistentNumberProperty(lhs, rhs, t); } assert(!"Unreachable!"); return 0; @@ -4686,6 +4723,30 @@ const char * cmTarget::GetLinkInterfaceDependentStringProperty( } //---------------------------------------------------------------------------- +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); +} + +//---------------------------------------------------------------------------- bool isLinkDependentProperty(cmTarget *tgt, const std::string &p, const char *interfaceProperty, const char *config) @@ -4754,6 +4815,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 @@ -5759,6 +5844,10 @@ const char * getLinkInterfaceDependentProperty(cmTarget *tgt, 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; @@ -5812,6 +5901,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) @@ -5820,6 +5953,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(); @@ -5845,23 +5980,71 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, { 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); |