Browse Source

Merge topic 'INTERFACE_AUTOUIC_OPTIONS'

77f3772 cmTarget: Require a compatible INTERFACE_AUTOUIC_OPTIONS from dependencies.
2e60b5f cmTarget: Report origin of COMPATIBLE_INTERFACE properties.
Brad King 12 years ago
parent
commit
5026696fcc

+ 153 - 139
Source/cmTarget.cxx

@@ -135,7 +135,6 @@ public:
   };
   std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
   std::vector<TargetPropertyEntry*> CompileOptionsEntries;
-  std::vector<TargetPropertyEntry*> AutoUicOptionsEntries;
   std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
   std::vector<cmValueWithOrigin> LinkInterfacePropertyEntries;
 
@@ -143,15 +142,12 @@ public:
                                 CachedLinkInterfaceIncludeDirectoriesEntries;
   mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
                                 CachedLinkInterfaceCompileOptionsEntries;
-  mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
-                                CachedLinkInterfaceAutoUicOptionsEntries;
   mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
                                 CachedLinkInterfaceCompileDefinitionsEntries;
 
   mutable std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
   mutable std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
   mutable std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
-  mutable std::map<std::string, bool> CacheLinkInterfaceAutoUicOptionsDone;
 };
 
 //----------------------------------------------------------------------------
@@ -186,7 +182,6 @@ cmTargetInternals::~cmTargetInternals()
 {
   deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
   deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
-  deleteAndClear(this->CachedLinkInterfaceAutoUicOptionsEntries);
   deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries);
 }
 
@@ -1478,17 +1473,6 @@ void cmTarget::SetProperty(const char* prop, const char* value)
                           new cmTargetInternals::TargetPropertyEntry(cge));
     return;
     }
-  if(strcmp(prop,"AUTOUIC_OPTIONS") == 0)
-    {
-    cmListFileBacktrace lfbt;
-    this->Makefile->GetBacktrace(lfbt);
-    cmGeneratorExpression ge(lfbt);
-    deleteAndClear(this->Internal->AutoUicOptionsEntries);
-    cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
-    this->Internal->AutoUicOptionsEntries.push_back(
-                          new cmTargetInternals::TargetPropertyEntry(cge));
-    return;
-    }
   if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
     {
     cmListFileBacktrace lfbt;
@@ -1563,15 +1547,6 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
               new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
     return;
     }
-  if(strcmp(prop,"AUTOUIC_OPTIONS") == 0)
-    {
-    cmListFileBacktrace lfbt;
-    this->Makefile->GetBacktrace(lfbt);
-    cmGeneratorExpression ge(lfbt);
-    this->Internal->AutoUicOptionsEntries.push_back(
-              new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
-    return;
-    }
   if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
     {
     cmListFileBacktrace lfbt;
@@ -2071,100 +2046,26 @@ static void processCompileOptions(cmTarget const* tgt,
 void cmTarget::GetAutoUicOptions(std::vector<std::string> &result,
                                  const char *config) const
 {
-  std::set<std::string> uniqueOptions;
-  cmListFileBacktrace lfbt;
-
-  cmGeneratorExpressionDAGChecker dagChecker(lfbt,
-                                              this->GetName(),
-                                              "AUTOUIC_OPTIONS", 0, 0);
-
-  std::vector<std::string> debugProperties;
-  const char *debugProp =
-              this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
-  if (debugProp)
-    {
-    cmSystemTools::ExpandListArgument(debugProp, debugProperties);
-    }
-
-  bool debugOptions = !this->DebugCompileOptionsDone
-                    && std::find(debugProperties.begin(),
-                                 debugProperties.end(),
-                                 "AUTOUIC_OPTIONS")
-                        != debugProperties.end();
-
-  if (this->Makefile->IsGeneratingBuildSystem())
-    {
-    this->DebugAutoUicOptionsDone = true;
-    }
-
-  processCompileOptions(this,
-                            this->Internal->AutoUicOptionsEntries,
-                            result,
-                            uniqueOptions,
-                            &dagChecker,
-                            config,
-                            debugOptions);
-
-  std::string configString = config ? config : "";
-  if (!this->Internal->CacheLinkInterfaceAutoUicOptionsDone[configString])
+  const char *prop
+            = this->GetLinkInterfaceDependentStringProperty("AUTOUIC_OPTIONS",
+                                                            config);
+  if (!prop)
     {
-    for (std::vector<cmValueWithOrigin>::const_iterator
-        it = this->Internal->LinkInterfacePropertyEntries.begin(),
-        end = this->Internal->LinkInterfacePropertyEntries.end();
-        it != end; ++it)
-      {
-      if (!cmGeneratorExpression::IsValidTargetName(it->Value)
-          && cmGeneratorExpression::Find(it->Value) == std::string::npos)
-        {
-        continue;
-        }
-      {
-      cmGeneratorExpression ge(lfbt);
-      cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
-                                                        ge.Parse(it->Value);
-      std::string targetResult = cge->Evaluate(this->Makefile, config,
-                                        false, this, 0, 0);
-      if (!this->Makefile->FindTargetToUse(targetResult.c_str()))
-        {
-        continue;
-        }
-      }
-      std::string optionGenex = "$<TARGET_PROPERTY:" +
-                              it->Value + ",INTERFACE_AUTOUIC_OPTIONS>";
-      if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
-        {
-        // Because it->Value is a generator expression, ensure that it
-        // evaluates to the non-empty string before being used in the
-        // TARGET_PROPERTY expression.
-        optionGenex = "$<$<BOOL:" + it->Value + ">:" + optionGenex + ">";
-        }
-      cmGeneratorExpression ge(it->Backtrace);
-      cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
-                                                                optionGenex);
-
-      this->Internal
-        ->CachedLinkInterfaceAutoUicOptionsEntries[configString].push_back(
-                        new cmTargetInternals::TargetPropertyEntry(cge,
-                                                              it->Value));
-      }
+    return;
     }
+  cmListFileBacktrace lfbt;
+  cmGeneratorExpression ge(lfbt);
 
-  processCompileOptions(this,
-    this->Internal->CachedLinkInterfaceAutoUicOptionsEntries[configString],
-                            result,
-                            uniqueOptions,
-                            &dagChecker,
-                            config,
-                            debugOptions);
-
-  if (!this->Makefile->IsGeneratingBuildSystem())
-    {
-    deleteAndClear(this->Internal->CachedLinkInterfaceAutoUicOptionsEntries);
-    }
-  else
-    {
-    this->Internal->CacheLinkInterfaceAutoUicOptionsDone[configString] = true;
-    }
+  cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+                                      this->GetName(),
+                                      "AUTOUIC_OPTIONS", 0, 0);
+  cmSystemTools::ExpandListArgument(ge.Parse(prop)
+                                      ->Evaluate(this->Makefile,
+                                                config,
+                                                false,
+                                                this,
+                                                &dagChecker),
+                                  result);
 }
 
 //----------------------------------------------------------------------------
@@ -2874,24 +2775,6 @@ const char *cmTarget::GetProperty(const char* prop,
       }
     return output.c_str();
     }
-  if(strcmp(prop,"AUTOUIC_OPTIONS") == 0)
-    {
-    static std::string output;
-    output = "";
-    std::string sep;
-    typedef cmTargetInternals::TargetPropertyEntry
-                                TargetPropertyEntry;
-    for (std::vector<TargetPropertyEntry*>::const_iterator
-        it = this->Internal->AutoUicOptionsEntries.begin(),
-        end = this->Internal->AutoUicOptionsEntries.end();
-        it != end; ++it)
-      {
-      output += sep;
-      output += (*it)->ge->GetInput();
-      sep = ";";
-      }
-    return output.c_str();
-    }
   if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
     {
     static std::string output;
@@ -4423,6 +4306,95 @@ const char* impliedValue<const char*>(const char*)
   return "";
 }
 
+
+template<typename PropertyType>
+std::string valueAsString(PropertyType);
+template<>
+std::string valueAsString<bool>(bool value)
+{
+  return value ? "TRUE" : "FALSE";
+}
+template<>
+std::string valueAsString<const char*>(const char* value)
+{
+  return value ? value : "(unset)";
+}
+
+//----------------------------------------------------------------------------
+void
+cmTarget::ReportPropertyOrigin(const std::string &p,
+                               const std::string &result,
+                               const std::string &report,
+                               const std::string &compatibilityType) const
+{
+  std::vector<std::string> debugProperties;
+  const char *debugProp =
+          this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+  if (debugProp)
+    {
+    cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+    }
+
+  bool debugOrigin = !this->DebugCompatiblePropertiesDone[p]
+                    && std::find(debugProperties.begin(),
+                                 debugProperties.end(),
+                                 p)
+                        != debugProperties.end();
+
+  if (this->Makefile->IsGeneratingBuildSystem())
+    {
+    this->DebugCompatiblePropertiesDone[p] = true;
+    }
+  if (!debugOrigin)
+    {
+    return;
+    }
+
+  std::string areport = compatibilityType;
+  areport += std::string(" of property \"") + p + "\" for target \"";
+  areport += std::string(this->GetName());
+  areport += "\" (result: \"";
+  areport += result;
+  areport += "\"):\n" + report;
+
+  cmListFileBacktrace lfbt;
+  this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, areport, lfbt);
+}
+
+//----------------------------------------------------------------------------
+std::string compatibilityType(CompatibleType t)
+{
+  switch(t)
+    {
+    case BoolType:
+      return "Boolean compatibility";
+    case StringType:
+      return "String compatibility";
+    case NumberMaxType:
+      return "Numeric maximum compatibility";
+    case NumberMinType:
+      return "Numeric minimum compatibility";
+    }
+  assert(!"Unreachable!");
+  return "";
+}
+
+//----------------------------------------------------------------------------
+std::string compatibilityAgree(CompatibleType t, bool dominant)
+{
+  switch(t)
+    {
+    case BoolType:
+    case StringType:
+      return dominant ? "(Disagree)\n" : "(Agree)\n";
+    case NumberMaxType:
+    case NumberMinType:
+      return dominant ? "(Dominant)\n" : "(Ignored)\n";
+    }
+  assert(!"Unreachable!");
+  return "";
+}
+
 //----------------------------------------------------------------------------
 template<typename PropertyType>
 PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
@@ -4450,6 +4422,23 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
   const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
   bool propInitialized = explicitlySet;
 
+  std::string report = " * Target \"";
+  report += tgt->GetName();
+  if (explicitlySet)
+    {
+    report += "\" has property content \"";
+    report += valueAsString<PropertyType>(propContent);
+    report += "\"\n";
+    }
+  else if (impliedByUse)
+    {
+    report += "\" property is implied by use.\n";
+    }
+  else
+    {
+    report += "\" property not set.\n";
+    }
+
   for(cmComputeLinkInformation::ItemVector::const_iterator li =
       deps.begin();
       li != deps.end(); ++li)
@@ -4471,12 +4460,25 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
     PropertyType ifacePropContent =
                     getTypedProperty<PropertyType>(li->Target,
                               ("INTERFACE_" + p).c_str(), 0);
+
+    std::string reportEntry;
+    if (ifacePropContent)
+      {
+      reportEntry += " * Target \"";
+      reportEntry += li->Target->GetName();
+      reportEntry += "\" property value \"";
+      reportEntry += valueAsString<PropertyType>(ifacePropContent);
+      reportEntry += "\" ";
+      }
+
     if (explicitlySet)
       {
       if (ifaceIsSet)
         {
         PropertyType consistent = consistentProperty(propContent,
                                                      ifacePropContent, t);
+        report += reportEntry;
+        report += compatibilityAgree(t, propContent != consistent);
         if (!consistent)
           {
           cmOStringStream e;
@@ -4489,7 +4491,6 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
           }
         else
           {
-          // Agree
           propContent = consistent;
           continue;
           }
@@ -4503,10 +4504,19 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
     else if (impliedByUse)
       {
       propContent = impliedValue<PropertyType>(propContent);
+
+      reportEntry += " * Target \"";
+      reportEntry += li->Target->GetName();
+      reportEntry += "\" property value \"";
+      reportEntry += valueAsString<PropertyType>(propContent);
+      reportEntry += "\" ";
+
       if (ifaceIsSet)
         {
         PropertyType consistent = consistentProperty(propContent,
                                                      ifacePropContent, t);
+        report += reportEntry;
+        report += compatibilityAgree(t, propContent != consistent);
         if (!consistent)
           {
           cmOStringStream e;
@@ -4520,7 +4530,6 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
           }
         else
           {
-          // Agree
           propContent = consistent;
           continue;
           }
@@ -4539,6 +4548,8 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
           {
           PropertyType consistent = consistentProperty(propContent,
                                                        ifacePropContent, t);
+          report += reportEntry;
+          report += compatibilityAgree(t, propContent != consistent);
           if (!consistent)
             {
             cmOStringStream e;
@@ -4551,13 +4562,13 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
             }
           else
             {
-            // Agree.
             propContent = consistent;
             continue;
             }
           }
         else
           {
+          report += reportEntry + "(Interface set)\n";
           propContent = ifacePropContent;
           propInitialized = true;
           }
@@ -4569,6 +4580,9 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
         }
       }
     }
+
+  tgt->ReportPropertyOrigin(p, valueAsString<PropertyType>(propContent),
+                            report, compatibilityType(t));
   return propContent;
 }
 
@@ -4682,7 +4696,8 @@ bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p,
     {
     return false;
     }
-  return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_STRING",
+  return (p == "AUTOUIC_OPTIONS") ||
+    isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_STRING",
                                  config);
 }
 
@@ -6101,7 +6116,6 @@ cmTargetInternalPointer::~cmTargetInternalPointer()
 {
   deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
   deleteAndClear(this->Pointer->CompileOptionsEntries);
-  deleteAndClear(this->Pointer->AutoUicOptionsEntries);
   deleteAndClear(this->Pointer->CompileDefinitionsEntries);
   delete this->Pointer;
 }

+ 6 - 1
Source/cmTarget.h

@@ -569,6 +569,11 @@ public:
   bool LinkLanguagePropagatesToDependents() const
   { return this->TargetTypeValue == STATIC_LIBRARY; }
 
+  void ReportPropertyOrigin(const std::string &p,
+                            const std::string &result,
+                            const std::string &report,
+                            const std::string &compatibilityType) const;
+
 private:
   bool HandleLocationPropertyPolicy() const;
 
@@ -691,8 +696,8 @@ private:
   bool IsApple;
   bool IsImportedTarget;
   mutable bool DebugIncludesDone;
+  mutable std::map<std::string, bool> DebugCompatiblePropertiesDone;
   mutable bool DebugCompileOptionsDone;
-  mutable bool DebugAutoUicOptionsDone;
   mutable bool DebugCompileDefinitionsDone;
   mutable std::set<std::string> LinkImplicitNullProperties;
   bool BuildInterfaceIncludesAppended;

+ 7 - 0
Tests/CompatibleInterface/CMakeLists.txt

@@ -31,6 +31,13 @@ set_property(TARGET iface1 APPEND PROPERTY
     NUMBER_MAX_PROP2
 )
 
+set(CMAKE_DEBUG_TARGET_PROPERTIES
+  BOOL_PROP1 BOOL_PROP2 BOOL_PROP3 BOOL_PROP4
+  STRING_PROP1 STRING_PROP2 STRING_PROP3
+  NUMBER_MIN_PROP1 NUMBER_MIN_PROP2
+  NUMBER_MAX_PROP1 NUMBER_MAX_PROP2
+)
+
 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)

+ 3 - 0
Tests/RunCMake/CMakeLists.txt

@@ -94,6 +94,9 @@ if(NOT WIN32)
     add_RunCMake_test(VisibilityPreset)
   endif()
 endif()
+if (QT4_FOUND)
+  set(CompatibleInterface_ARGS -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE})
+endif()
 add_RunCMake_test(CompatibleInterface)
 add_RunCMake_test(Syntax)
 

+ 1 - 0
Tests/RunCMake/CompatibleInterface/AutoUic-result.txt

@@ -0,0 +1 @@
+1

+ 11 - 0
Tests/RunCMake/CompatibleInterface/AutoUic-stderr.txt

@@ -0,0 +1,11 @@
+CMake Error: The INTERFACE_AUTOUIC_OPTIONS property of "OtherI18n" does
+not agree with the value of AUTOUIC_OPTIONS already determined
+for "LibWidget".
+
+CMake Debug Log:
+  String compatibility of property "AUTOUIC_OPTIONS" for target "LibWidget"
+  \(result: "-tr;ki18n"\):
+
+   \* Target "LibWidget" property not set.
+   \* Target "KI18n" property value "-tr;ki18n" \(Interface set\)
+   \* Target "OtherI18n" property value "-tr;otheri18n" \(Disagree\)

+ 22 - 0
Tests/RunCMake/CompatibleInterface/AutoUic.cmake

@@ -0,0 +1,22 @@
+
+find_package(Qt4 REQUIRED)
+
+set(QT_CORE_TARGET Qt4::QtCore)
+set(QT_GUI_TARGET Qt4::QtGui)
+
+set(CMAKE_AUTOUIC ON)
+
+set(CMAKE_DEBUG_TARGET_PROPERTIES AUTOUIC_OPTIONS)
+
+add_library(KI18n INTERFACE)
+set_property(TARGET KI18n APPEND PROPERTY
+  INTERFACE_AUTOUIC_OPTIONS -tr ki18n
+)
+
+add_library(OtherI18n INTERFACE)
+set_property(TARGET OtherI18n APPEND PROPERTY
+  INTERFACE_AUTOUIC_OPTIONS -tr otheri18n
+)
+
+add_library(LibWidget empty.cpp)
+target_link_libraries(LibWidget KI18n OtherI18n ${QT_GUI_TARGET})

+ 1 - 0
Tests/RunCMake/CompatibleInterface/DebugProperties-result.txt

@@ -0,0 +1 @@
+0

+ 73 - 0
Tests/RunCMake/CompatibleInterface/DebugProperties-stderr.txt

@@ -0,0 +1,73 @@
+CMake Debug Log:
+  Boolean compatibility of property "BOOL_PROP1" for target
+  "CompatibleInterface" \(result: "TRUE"\):
+
+   \* Target "CompatibleInterface" property not set.
+   \* Target "iface1" property value "TRUE" \(Interface set\)
++
+CMake Debug Log:
+  Boolean compatibility of property "BOOL_PROP2" for target
+  "CompatibleInterface" \(result: "TRUE"\):
+
+   \* Target "CompatibleInterface" has property content "TRUE"
+   \* Target "iface1" property value "TRUE" \(Agree\)
++
+CMake Debug Log:
+  Boolean compatibility of property "BOOL_PROP3" for target
+  "CompatibleInterface" \(result: "TRUE"\):
+
+   \* Target "CompatibleInterface" has property content "TRUE"
++
+CMake Debug Log:
+  Boolean compatibility of property "BOOL_PROP4" for target
+  "CompatibleInterface" \(result: "FALSE"\):
+
+   \* Target "CompatibleInterface" property not set.
++
+CMake Debug Log:
+  String compatibility of property "STRING_PROP1" for target
+  "CompatibleInterface" \(result: "prop1"\):
+
+   \* Target "CompatibleInterface" property not set.
+   \* Target "iface1" property value "prop1" \(Interface set\)
++
+CMake Debug Log:
+  String compatibility of property "STRING_PROP2" for target
+  "CompatibleInterface" \(result: "prop2"\):
+
+   \* Target "CompatibleInterface" has property content "prop2"
+   \* Target "iface1" property value "prop2" \(Agree\)
++
+CMake Debug Log:
+  String compatibility of property "STRING_PROP3" for target
+  "CompatibleInterface" \(result: "prop3"\):
+
+   \* Target "CompatibleInterface" has property content "prop3"
++
+CMake Debug Log:
+  Numeric minimum compatibility of property "NUMBER_MIN_PROP1" for target
+  "CompatibleInterface" \(result: "50"\):
+
+   \* Target "CompatibleInterface" has property content "50"
+   \* Target "iface1" property value "100" \(Ignored\)
++
+CMake Debug Log:
+  Numeric minimum compatibility of property "NUMBER_MIN_PROP2" for target
+  "CompatibleInterface" \(result: "200"\):
+
+   \* Target "CompatibleInterface" has property content "250"
+   \* Target "iface1" property value "200" \(Dominant\)
++
+CMake Debug Log:
+  Numeric maximum compatibility of property "NUMBER_MAX_PROP1" for target
+  "CompatibleInterface" \(result: "100"\):
+
+   \* Target "CompatibleInterface" has property content "50"
+   \* Target "iface1" property value "100" \(Dominant\)
++
+CMake Debug Log:
+  Numeric maximum compatibility of property "NUMBER_MAX_PROP2" for target
+  "CompatibleInterface" \(result: "250"\):
+
+   \* Target "CompatibleInterface" has property content "250"
+   \* Target "iface1" property value "200" \(Ignored\)

+ 60 - 0
Tests/RunCMake/CompatibleInterface/DebugProperties.cmake

@@ -0,0 +1,60 @@
+
+cmake_minimum_required(VERSION 2.8)
+
+project(CompatibleInterface)
+
+include(GenerateExportHeader)
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+add_library(iface1 INTERFACE)
+set_property(TARGET iface1 APPEND PROPERTY
+  COMPATIBLE_INTERFACE_BOOL
+    BOOL_PROP1
+    BOOL_PROP2
+    BOOL_PROP3
+    BOOL_PROP4
+)
+set_property(TARGET iface1 APPEND PROPERTY
+  COMPATIBLE_INTERFACE_STRING
+    STRING_PROP1
+    STRING_PROP2
+    STRING_PROP3
+)
+set_property(TARGET iface1 APPEND PROPERTY
+  COMPATIBLE_INTERFACE_NUMBER_MIN
+    NUMBER_MIN_PROP1
+    NUMBER_MIN_PROP2
+)
+set_property(TARGET iface1 APPEND PROPERTY
+  COMPATIBLE_INTERFACE_NUMBER_MAX
+    NUMBER_MAX_PROP1
+    NUMBER_MAX_PROP2
+)
+
+set(CMAKE_DEBUG_TARGET_PROPERTIES
+  BOOL_PROP1 BOOL_PROP2 BOOL_PROP3 BOOL_PROP4
+  STRING_PROP1 STRING_PROP2 STRING_PROP3
+  NUMBER_MIN_PROP1 NUMBER_MIN_PROP2
+  NUMBER_MAX_PROP1 NUMBER_MAX_PROP2
+)
+
+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)
+set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MIN_PROP1 100)
+set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MIN_PROP2 200)
+set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MAX_PROP1 100)
+set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MAX_PROP2 200)
+
+add_executable(CompatibleInterface empty.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)
+set_property(TARGET CompatibleInterface PROPERTY NUMBER_MIN_PROP1 50)
+set_property(TARGET CompatibleInterface PROPERTY NUMBER_MIN_PROP2 250)
+set_property(TARGET CompatibleInterface PROPERTY NUMBER_MAX_PROP1 50)
+set_property(TARGET CompatibleInterface PROPERTY NUMBER_MAX_PROP2 250)

+ 6 - 0
Tests/RunCMake/CompatibleInterface/RunCMakeTest.cmake

@@ -9,3 +9,9 @@ run_cmake(InterfaceString-mismatch-depend-self)
 run_cmake(InterfaceString-mismatched-use)
 run_cmake(InterfaceString-builtin-prop)
 run_cmake(InterfaceString-Bool-Conflict)
+run_cmake(DebugProperties)
+
+if (QT_QMAKE_EXECUTABLE})
+  set(RunCMake_TEST_OPTIONS -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE})
+  run_cmake(AutoUic)
+endif()

+ 1 - 0
Tests/RunCMake/CompatibleInterface/empty.cpp

@@ -0,0 +1 @@
+// no content

+ 1 - 0
Tests/RunCMake/PositionIndependentCode/Debug-result.txt

@@ -0,0 +1 @@
+0

+ 6 - 0
Tests/RunCMake/PositionIndependentCode/Debug-stderr.txt

@@ -0,0 +1,6 @@
+CMake Debug Log:
+  Boolean compatibility of property "POSITION_INDEPENDENT_CODE" for target
+  "foo" \(result: "TRUE"\):
+
+   \* Target "foo" has property content "TRUE"
+   \* Target "iface" property value "TRUE" \(Agree\)

+ 8 - 0
Tests/RunCMake/PositionIndependentCode/Debug.cmake

@@ -0,0 +1,8 @@
+
+add_library(iface INTERFACE)
+set_property(TARGET iface PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)
+
+set(CMAKE_DEBUG_TARGET_PROPERTIES POSITION_INDEPENDENT_CODE)
+add_library(foo main.cpp)
+target_link_libraries(foo iface)
+set_property(TARGET foo PROPERTY POSITION_INDEPENDENT_CODE ON)

+ 1 - 0
Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake

@@ -6,3 +6,4 @@ run_cmake(Conflict3)
 run_cmake(Conflict4)
 run_cmake(Conflict5)
 run_cmake(Conflict6)
+run_cmake(Debug)