diff options
author | Brad King <brad.king@kitware.com> | 2013-01-25 18:38:06 (GMT) |
---|---|---|
committer | CMake Topic Stage <kwrobot@kitware.com> | 2013-01-25 18:38:06 (GMT) |
commit | 2046de2a39e993d0f892f2f38f0ba7543f8505a6 (patch) | |
tree | ac4e03e00ae90507e4a6aaba77d9d137eb908ab5 /Source | |
parent | a4eb27fbab81087fde72f2058b60a67f1f9298da (diff) | |
parent | 2fb2c32f9b304bc71b039754f9b9170fd6f27a6f (diff) | |
download | CMake-2046de2a39e993d0f892f2f38f0ba7543f8505a6.zip CMake-2046de2a39e993d0f892f2f38f0ba7543f8505a6.tar.gz CMake-2046de2a39e993d0f892f2f38f0ba7543f8505a6.tar.bz2 |
Merge topic 'compatible-interface-strings'
2fb2c32 Add the COMPATIBLE_INTERFACE_STRING property.
cd66b91 Make calculation of link-interface-dependent properties type-sensitive.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmExportFileGenerator.cxx | 6 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionEvaluator.cxx | 7 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 229 | ||||
-rw-r--r-- | Source/cmTarget.h | 5 |
4 files changed, 200 insertions, 47 deletions
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index ef1fc5f..96e0aea 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -217,6 +217,9 @@ void getCompatibleInterfaceProperties(cmTarget *target, getPropertyContents(li->Target, "COMPATIBLE_INTERFACE_BOOL", ifaceProperties); + getPropertyContents(li->Target, + "COMPATIBLE_INTERFACE_STRING", + ifaceProperties); } } @@ -227,10 +230,13 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties( { this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL", target, properties); + this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_STRING", + target, properties); std::set<std::string> ifaceProperties; getPropertyContents(target, "COMPATIBLE_INTERFACE_BOOL", ifaceProperties); + getPropertyContents(target, "COMPATIBLE_INTERFACE_STRING", ifaceProperties); getCompatibleInterfaceProperties(target, ifaceProperties, 0); diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index c468c39..0c61a12 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -462,6 +462,13 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode propertyName, context->Config) ? "1" : "0"; } + if (target->IsLinkInterfaceDependentStringProperty(propertyName, + context->Config)) + { + return target->GetLinkInterfaceDependentStringProperty( + propertyName, + context->Config); + } return std::string(); } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 2b912f3..e3be510 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -908,6 +908,17 @@ void cmTarget::DefineProperties(cmake *cm) "property is not set, then it is ignored."); cm->DefineProperty + ("COMPATIBLE_INTERFACE_STRING", cmProperty::TARGET, + "Properties which must be string-compatible with their link interface", + "The COMPATIBLE_INTERFACE_STRING property may contain a list of " + "properties for this target which must be the same when evaluated as " + "a string in the INTERFACE of all linked dependencies. For example, " + "if a property \"FOO\" appears in the list, then the \"INTERFACE_FOO\" " + "property content in all dependencies must be equal with each " + "other, and with the \"FOO\" property in this target. If the " + "property is not set, then it is ignored."); + + cm->DefineProperty ("POST_INSTALL_SCRIPT", cmProperty::TARGET, "Deprecated install support.", "The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the " @@ -4500,22 +4511,69 @@ void cmTarget::AddLinkDependentTargetsForProperties( } //---------------------------------------------------------------------------- -bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, - const char *config) +template<typename PropertyType> +PropertyType getTypedProperty(cmTarget *tgt, const char *prop, + PropertyType *); + +//---------------------------------------------------------------------------- +template<> +bool getTypedProperty<bool>(cmTarget *tgt, const char *prop, bool *) +{ + return tgt->GetPropertyAsBool(prop); +} + +//---------------------------------------------------------------------------- +template<> +const char *getTypedProperty<const char *>(cmTarget *tgt, const char *prop, + const char **) +{ + return tgt->GetProperty(prop); +} + +//---------------------------------------------------------------------------- +template<typename PropertyType> +bool consistentProperty(PropertyType lhs, PropertyType rhs); + +//---------------------------------------------------------------------------- +template<> +bool consistentProperty(bool lhs, bool rhs) +{ + return lhs == rhs; +} + +//---------------------------------------------------------------------------- +template<> +bool consistentProperty(const char *lhs, const char *rhs) +{ + if (!lhs && !rhs) + return true; + if (!lhs || !rhs) + return false; + return strcmp(lhs, rhs) == 0; +} + +//---------------------------------------------------------------------------- +template<typename PropertyType> +PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt, + const std::string &p, + const char *config, + const char *defaultValue, + PropertyType *) { - bool propContent = this->GetPropertyAsBool(p.c_str()); - const bool explicitlySet = this->GetProperties() + PropertyType propContent = getTypedProperty<PropertyType>(tgt, p.c_str(), + 0); + const bool explicitlySet = tgt->GetProperties() .find(p.c_str()) - != this->GetProperties().end(); + != tgt->GetProperties().end(); std::set<std::string> dependentTargets; - this->GetLinkDependentTargetsForProperty(p, + tgt->GetLinkDependentTargetsForProperty(p, dependentTargets); const bool impliedByUse = - this->IsNullImpliedByLinkLibraries(p); + tgt->IsNullImpliedByLinkLibraries(p); assert((impliedByUse ^ explicitlySet) || (!impliedByUse && !explicitlySet)); - cmComputeLinkInformation *info = this->GetLinkInformation(config); + cmComputeLinkInformation *info = tgt->GetLinkInformation(config); const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); bool propInitialized = explicitlySet; @@ -4537,17 +4595,18 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, const bool ifaceIsSet = li->Target->GetProperties() .find("INTERFACE_" + p) != li->Target->GetProperties().end(); - const bool ifacePropContent = li->Target->GetPropertyAsBool( - ("INTERFACE_" + p).c_str()); + PropertyType ifacePropContent = + getTypedProperty<PropertyType>(li->Target, + ("INTERFACE_" + p).c_str(), 0); if (explicitlySet) { if (ifaceIsSet) { - if (propContent != ifacePropContent) + if (!consistentProperty(propContent, ifacePropContent)) { cmOStringStream e; e << "Property " << p << " on target \"" - << this->GetName() << "\" does\nnot match the " + << tgt->GetName() << "\" does\nnot match the " "INTERFACE_" << p << " property requirement\nof " "dependency \"" << li->Target->GetName() << "\".\n"; cmSystemTools::Error(e.str().c_str()); @@ -4569,13 +4628,13 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, { if (ifaceIsSet) { - if (propContent != ifacePropContent) + if (!consistentProperty(propContent, ifacePropContent)) { cmOStringStream e; e << "Property " << p << " on target \"" - << this->GetName() << "\" is\nimplied to be FALSE because it " - "was used to determine the link libraries\nalready. The " - "INTERFACE_" << p << " property on\ndependency \"" + << tgt->GetName() << "\" is\nimplied to be " << defaultValue + << " because it was used to determine the link libraries\n" + "already. The INTERFACE_" << p << " property on\ndependency \"" << li->Target->GetName() << "\" is in conflict.\n"; cmSystemTools::Error(e.str().c_str()); break; @@ -4598,13 +4657,13 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, { if (propInitialized) { - if (propContent != ifacePropContent) + if (!consistentProperty(propContent, ifacePropContent)) { cmOStringStream e; e << "The INTERFACE_" << p << " property of \"" << li->Target->GetName() << "\" does\nnot agree with the value " "of " << p << " already determined\nfor \"" - << this->GetName() << "\".\n"; + << tgt->GetName() << "\".\n"; cmSystemTools::Error(e.str().c_str()); break; } @@ -4631,6 +4690,25 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, } //---------------------------------------------------------------------------- +bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, + const char *config) +{ + return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE", + 0); +} + +//---------------------------------------------------------------------------- +const char * cmTarget::GetLinkInterfaceDependentStringProperty( + const std::string &p, + const char *config) +{ + return checkInterfacePropertyCompatibility<const char *>(this, + p, + config, + "empty", 0); +} + +//---------------------------------------------------------------------------- bool isLinkDependentProperty(cmTarget *tgt, const std::string &p, const char *interfaceProperty, const char *config) @@ -4678,6 +4756,14 @@ bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p, } //---------------------------------------------------------------------------- +bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p, + const char *config) +{ + return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_STRING", + config); +} + +//---------------------------------------------------------------------------- void cmTarget::GetLanguages(std::set<cmStdString>& languages) const { for(std::vector<cmSourceFile*>::const_iterator @@ -5417,6 +5503,73 @@ std::string cmTarget::CheckCMP0004(std::string const& item) return lib; } +template<typename PropertyType> +PropertyType getLinkInterfaceDependentProperty(cmTarget *tgt, + const std::string prop, + const char *config, + PropertyType *); + +template<> +bool getLinkInterfaceDependentProperty(cmTarget *tgt, + const std::string prop, + const char *config, bool *) +{ + return tgt->GetLinkInterfaceDependentBoolProperty(prop, config); +} + +template<> +const char * getLinkInterfaceDependentProperty(cmTarget *tgt, + const std::string prop, + const char *config, + const char **) +{ + return tgt->GetLinkInterfaceDependentStringProperty(prop, config); +} + +//---------------------------------------------------------------------------- +template<typename PropertyType> +void checkPropertyConsistency(cmTarget *depender, cmTarget *dependee, + const char *propName, + std::set<cmStdString> &emitted, + const char *config, + PropertyType *) +{ + const char *prop = dependee->GetProperty(propName); + if (!prop) + { + return; + } + + std::vector<std::string> props; + cmSystemTools::ExpandListArgument(prop, props); + + for(std::vector<std::string>::iterator pi = props.begin(); + pi != props.end(); ++pi) + { + if (depender->GetMakefile()->GetCMakeInstance() + ->GetIsPropertyDefined(pi->c_str(), + cmProperty::TARGET)) + { + cmOStringStream e; + e << "Target \"" << dependee->GetName() << "\" has property \"" + << *pi << "\" listed in its " << propName << " property. " + "This is not allowed. Only user-defined properties may appear " + "listed in the " << propName << " property."; + depender->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + if(emitted.insert(*pi).second) + { + getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config, + 0); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + } + } +} + //---------------------------------------------------------------------------- void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, const char* config) @@ -5433,38 +5586,20 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, { continue; } - const char *prop = li->Target->GetProperty("COMPATIBLE_INTERFACE_BOOL"); - if (!prop) + + checkPropertyConsistency<bool>(this, li->Target, + "COMPATIBLE_INTERFACE_BOOL", + emitted, config, 0); + if (cmSystemTools::GetErrorOccuredFlag()) { - continue; + return; } - - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(prop, props); - - for(std::vector<std::string>::iterator pi = props.begin(); - pi != props.end(); ++pi) + checkPropertyConsistency<const char *>(this, li->Target, + "COMPATIBLE_INTERFACE_STRING", + emitted, config, 0); + if (cmSystemTools::GetErrorOccuredFlag()) { - if (this->Makefile->GetCMakeInstance() - ->GetIsPropertyDefined(pi->c_str(), - cmProperty::TARGET)) - { - cmOStringStream e; - e << "Target \"" << li->Target->GetName() << "\" has property \"" - << *pi << "\" listed in its COMPATIBLE_INTERFACE_BOOL property. " - "This is not allowed. Only user-defined properties may appear " - "listed in the COMPATIBLE_INTERFACE_BOOL property."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); - return; - } - if(emitted.insert(*pi).second) - { - this->GetLinkInterfaceDependentBoolProperty(*pi, config); - if (cmSystemTools::GetErrorOccuredFlag()) - { - return; - } - } + return; } } } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 9909bae..4457bec 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -501,12 +501,17 @@ public: bool IsNullImpliedByLinkLibraries(const std::string &p); bool IsLinkInterfaceDependentBoolProperty(const std::string &p, const char *config); + bool IsLinkInterfaceDependentStringProperty(const std::string &p, + const char *config); void AddLinkDependentTargetsForProperties( const std::map<cmStdString, cmStdString> &map); bool GetLinkInterfaceDependentBoolProperty(const std::string &p, const char *config); + + const char *GetLinkInterfaceDependentStringProperty(const std::string &p, + const char *config); private: /** * A list of direct dependencies. Use in conjunction with DependencyMap. |