summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2013-10-26 14:28:30 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2013-10-26 14:28:30 (GMT)
commit4025013dd78abeaef772eee1fc532ce275ae4216 (patch)
tree313d9ed0302f457507c375a1ea32f23db6d47ff5 /Source
parent5f789db847a86cbdfb94fcf1abd4d561a6942d65 (diff)
parentff6c401309761f0c0061f1084f2e3150038962a5 (diff)
downloadCMake-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.cxx14
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx44
-rw-r--r--Source/cmTarget.cxx319
-rw-r--r--Source/cmTarget.h8
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);