summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmExportFileGenerator.cxx6
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx7
-rw-r--r--Source/cmTarget.cxx229
-rw-r--r--Source/cmTarget.h5
-rw-r--r--Tests/CompatibleInterface/CMakeLists.txt13
-rw-r--r--Tests/CompatibleInterface/main.cpp12
-rw-r--r--Tests/ExportImport/Export/CMakeLists.txt9
-rw-r--r--Tests/ExportImport/Import/A/CMakeLists.txt2
-rw-r--r--Tests/ExportImport/Import/A/deps_shared_iface.cpp4
-rw-r--r--Tests/RunCMake/CompatibleInterface/InterfaceString-builtin-prop-result.txt1
-rw-r--r--Tests/RunCMake/CompatibleInterface/InterfaceString-builtin-prop-stderr.txt5
-rw-r--r--Tests/RunCMake/CompatibleInterface/InterfaceString-builtin-prop.cmake11
-rw-r--r--Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depend-self-result.txt1
-rw-r--r--Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depend-self-stderr.txt3
-rw-r--r--Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depend-self.cmake11
-rw-r--r--Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depends-result.txt1
-rw-r--r--Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depends-stderr.txt3
-rw-r--r--Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depends.cmake10
-rw-r--r--Tests/RunCMake/CompatibleInterface/InterfaceString-mismatched-use-result.txt1
-rw-r--r--Tests/RunCMake/CompatibleInterface/InterfaceString-mismatched-use-stderr.txt4
-rw-r--r--Tests/RunCMake/CompatibleInterface/InterfaceString-mismatched-use.cmake9
-rw-r--r--Tests/RunCMake/CompatibleInterface/RunCMakeTest.cmake4
22 files changed, 303 insertions, 48 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.
diff --git a/Tests/CompatibleInterface/CMakeLists.txt b/Tests/CompatibleInterface/CMakeLists.txt
index 7280652..259b5a1 100644
--- a/Tests/CompatibleInterface/CMakeLists.txt
+++ b/Tests/CompatibleInterface/CMakeLists.txt
@@ -14,21 +14,34 @@ set_property(TARGET iface1 APPEND PROPERTY
BOOL_PROP3
BOOL_PROP4
)
+set_property(TARGET iface1 APPEND PROPERTY
+ COMPATIBLE_INTERFACE_STRING
+ STRING_PROP1
+ STRING_PROP2
+ STRING_PROP3
+)
set_property(TARGET iface1 PROPERTY INTERFACE_BOOL_PROP1 ON)
set_property(TARGET iface1 PROPERTY INTERFACE_BOOL_PROP2 ON)
+set_property(TARGET iface1 PROPERTY INTERFACE_STRING_PROP1 prop1)
+set_property(TARGET iface1 PROPERTY INTERFACE_STRING_PROP2 prop2)
add_executable(CompatibleInterface main.cpp)
target_link_libraries(CompatibleInterface iface1)
set_property(TARGET CompatibleInterface PROPERTY BOOL_PROP2 ON)
set_property(TARGET CompatibleInterface PROPERTY BOOL_PROP3 ON)
+set_property(TARGET CompatibleInterface PROPERTY STRING_PROP2 prop2)
+set_property(TARGET CompatibleInterface PROPERTY STRING_PROP3 prop3)
target_compile_definitions(CompatibleInterface
PRIVATE
$<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP1>>:BOOL_PROP1>
$<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP2>>:BOOL_PROP2>
$<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP3>>:BOOL_PROP3>
+ $<$<STREQUAL:$<TARGET_PROPERTY:STRING_PROP1>,prop1>:STRING_PROP1>
+ $<$<STREQUAL:$<TARGET_PROPERTY:STRING_PROP2>,prop2>:STRING_PROP2>
+ $<$<STREQUAL:$<TARGET_PROPERTY:STRING_PROP3>,prop3>:STRING_PROP3>
)
diff --git a/Tests/CompatibleInterface/main.cpp b/Tests/CompatibleInterface/main.cpp
index ae0e985..f5e6e38 100644
--- a/Tests/CompatibleInterface/main.cpp
+++ b/Tests/CompatibleInterface/main.cpp
@@ -11,6 +11,18 @@
#error Expected BOOL_PROP3
#endif
+#ifndef STRING_PROP1
+#error Expected STRING_PROP1
+#endif
+
+#ifndef STRING_PROP2
+#error Expected STRING_PROP2
+#endif
+
+#ifndef STRING_PROP3
+#error Expected STRING_PROP3
+#endif
+
#include "iface2.h"
int main(int argc, char **argv)
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index 5992293..eecfd6a 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -181,7 +181,14 @@ set_property(TARGET testSharedLibRequired
PROPERTY
INTERFACE_CUSTOM_PROP ON
)
-
+set_property(TARGET testSharedLibRequired
+ APPEND PROPERTY
+ COMPATIBLE_INTERFACE_STRING CUSTOM_STRING
+)
+set_property(TARGET testSharedLibRequired
+ PROPERTY
+ INTERFACE_CUSTOM_STRING testcontent
+)
add_library(testSharedLibDepends SHARED testSharedLibDepends.cpp)
set_property(TARGET testSharedLibDepends APPEND PROPERTY
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt
index 4df5771..187c48a 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -170,6 +170,7 @@ target_compile_definitions(deps_shared_iface
testSharedLibDepends
$<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:PIC_PROPERTY_IS_ON>
$<$<BOOL:$<TARGET_PROPERTY:CUSTOM_PROP>>:CUSTOM_PROPERTY_IS_ON>
+ $<$<STREQUAL:$<TARGET_PROPERTY:CUSTOM_STRING>,testcontent>:CUSTOM_STRING_IS_MATCH>
)
if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
@@ -201,4 +202,5 @@ target_compile_definitions(deps_shared_iface2
PRIVATE bld_testSharedLibDepends TEST_SUBDIR_LIB
$<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:PIC_PROPERTY_IS_ON>
$<$<BOOL:$<TARGET_PROPERTY:CUSTOM_PROP>>:CUSTOM_PROPERTY_IS_ON>
+ $<$<STREQUAL:$<TARGET_PROPERTY:CUSTOM_STRING>,testcontent>:CUSTOM_STRING_IS_MATCH>
)
diff --git a/Tests/ExportImport/Import/A/deps_shared_iface.cpp b/Tests/ExportImport/Import/A/deps_shared_iface.cpp
index a33f200..2f0e74a 100644
--- a/Tests/ExportImport/Import/A/deps_shared_iface.cpp
+++ b/Tests/ExportImport/Import/A/deps_shared_iface.cpp
@@ -16,6 +16,10 @@
#error Expected CUSTOM_PROPERTY_IS_ON
#endif
+#ifndef CUSTOM_STRING_IS_MATCH
+#error Expected CUSTOM_STRING_IS_MATCH
+#endif
+
#ifdef TEST_SUBDIR_LIB
#include "subdir.h"
#endif
diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-builtin-prop-result.txt b/Tests/RunCMake/CompatibleInterface/InterfaceString-builtin-prop-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-builtin-prop-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-builtin-prop-stderr.txt b/Tests/RunCMake/CompatibleInterface/InterfaceString-builtin-prop-stderr.txt
new file mode 100644
index 0000000..6a293b4
--- /dev/null
+++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-builtin-prop-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error in CMakeLists.txt:
+ Target "foo" has property "INCLUDE_DIRECTORIES" listed in its
+ COMPATIBLE_INTERFACE_STRING property. This is not allowed. Only
+ user-defined properties may appear listed in the
+ COMPATIBLE_INTERFACE_STRING property.
diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-builtin-prop.cmake b/Tests/RunCMake/CompatibleInterface/InterfaceString-builtin-prop.cmake
new file mode 100644
index 0000000..5221a12
--- /dev/null
+++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-builtin-prop.cmake
@@ -0,0 +1,11 @@
+
+add_library(foo UNKNOWN IMPORTED)
+add_library(bar UNKNOWN IMPORTED)
+
+set_property(TARGET foo APPEND PROPERTY COMPATIBLE_INTERFACE_STRING INCLUDE_DIRECTORIES)
+set_property(TARGET foo PROPERTY INTERFACE_INCLUDE_DIRECTORIES foo_inc)
+set_property(TARGET bar PROPERTY INTERFACE_INCLUDE_DIRECTORIES bar_inc)
+
+add_executable(user main.cpp)
+set_property(TARGET user PROPERTY INCLUDE_DIRECTORIES bar_inc)
+target_link_libraries(user foo bar)
diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depend-self-result.txt b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depend-self-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depend-self-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depend-self-stderr.txt b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depend-self-stderr.txt
new file mode 100644
index 0000000..0476da9
--- /dev/null
+++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depend-self-stderr.txt
@@ -0,0 +1,3 @@
+CMake Error: Property SOMEPROP on target "user" does
+not match the INTERFACE_SOMEPROP property requirement
+of dependency "foo".
diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depend-self.cmake b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depend-self.cmake
new file mode 100644
index 0000000..187f29f
--- /dev/null
+++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depend-self.cmake
@@ -0,0 +1,11 @@
+
+add_library(foo UNKNOWN IMPORTED)
+add_library(bar UNKNOWN IMPORTED)
+
+set_property(TARGET foo APPEND PROPERTY COMPATIBLE_INTERFACE_STRING SOMEPROP)
+set_property(TARGET foo PROPERTY INTERFACE_SOMEPROP prop)
+set_property(TARGET bar PROPERTY INTERFACE_SOMEPROP prop)
+
+add_executable(user main.cpp)
+set_property(TARGET user PROPERTY SOMEPROP different)
+target_link_libraries(user foo bar)
diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depends-result.txt b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depends-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depends-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depends-stderr.txt b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depends-stderr.txt
new file mode 100644
index 0000000..d885c09
--- /dev/null
+++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depends-stderr.txt
@@ -0,0 +1,3 @@
+CMake Error: The INTERFACE_SOMEPROP property of "bar" does
+not agree with the value of SOMEPROP already determined
+for "user".
diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depends.cmake b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depends.cmake
new file mode 100644
index 0000000..73cc3fc
--- /dev/null
+++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatch-depends.cmake
@@ -0,0 +1,10 @@
+
+add_library(foo UNKNOWN IMPORTED)
+add_library(bar UNKNOWN IMPORTED)
+
+set_property(TARGET foo APPEND PROPERTY COMPATIBLE_INTERFACE_STRING SOMEPROP)
+set_property(TARGET foo PROPERTY INTERFACE_SOMEPROP foo)
+set_property(TARGET bar PROPERTY INTERFACE_SOMEPROP bar)
+
+add_executable(user main.cpp)
+target_link_libraries(user foo bar)
diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatched-use-result.txt b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatched-use-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatched-use-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatched-use-stderr.txt b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatched-use-stderr.txt
new file mode 100644
index 0000000..723daec
--- /dev/null
+++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatched-use-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error: Property SOMEPROP on target "user" is
+implied to be empty because it was used to determine the link libraries
+already. The INTERFACE_SOMEPROP property on
+dependency "foo" is in conflict.
diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatched-use.cmake b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatched-use.cmake
new file mode 100644
index 0000000..af3ce8f
--- /dev/null
+++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-mismatched-use.cmake
@@ -0,0 +1,9 @@
+
+add_library(foo UNKNOWN IMPORTED)
+add_library(bar UNKNOWN IMPORTED)
+
+set_property(TARGET foo APPEND PROPERTY COMPATIBLE_INTERFACE_STRING SOMEPROP)
+set_property(TARGET foo PROPERTY INTERFACE_SOMEPROP prop)
+
+add_executable(user main.cpp)
+target_link_libraries(user foo $<$<STREQUAL:$<TARGET_PROPERTY:SOMEPROP>,prop>:bar>)
diff --git a/Tests/RunCMake/CompatibleInterface/RunCMakeTest.cmake b/Tests/RunCMake/CompatibleInterface/RunCMakeTest.cmake
index ba8917b..922ad7f 100644
--- a/Tests/RunCMake/CompatibleInterface/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CompatibleInterface/RunCMakeTest.cmake
@@ -4,3 +4,7 @@ run_cmake(InterfaceBool-mismatch-depends)
run_cmake(InterfaceBool-mismatch-depend-self)
run_cmake(InterfaceBool-mismatched-use)
run_cmake(InterfaceBool-builtin-prop)
+run_cmake(InterfaceString-mismatch-depends)
+run_cmake(InterfaceString-mismatch-depend-self)
+run_cmake(InterfaceString-mismatched-use)
+run_cmake(InterfaceString-builtin-prop)