소스 검색

Merge topic 'INTERFACE_LINK_LIBRARIES-prop'

3e30d9e TLL: Don't populate old link interface if CMP0022 is NEW.
574fec9 Export: Generate INTERFACE_LINK_LIBRARIES property on targets.
d0a76ea Introduce the INTERFACE_LINK_LIBRARIES property.
ddde61c Introduce the LINK_ONLY generator expression.
5aa9731 GenexEval: Add abstracted access to link interface for a target.
Brad King 12 년 전
부모
커밋
b6e0972262
89개의 변경된 파일914개의 추가작업 그리고 30개의 파일을 삭제
  1. 9 0
      Source/cmExportBuildFileGenerator.cxx
  2. 2 0
      Source/cmExportCommand.cxx
  3. 6 1
      Source/cmExportCommand.h
  4. 50 0
      Source/cmExportFileGenerator.cxx
  5. 11 0
      Source/cmExportFileGenerator.h
  6. 19 0
      Source/cmExportInstallFileGenerator.cxx
  7. 17 2
      Source/cmGeneratorExpressionDAGChecker.cxx
  8. 5 0
      Source/cmGeneratorExpressionDAGChecker.h
  9. 26 5
      Source/cmGeneratorExpressionEvaluator.cxx
  10. 30 3
      Source/cmInstallCommand.cxx
  11. 5 0
      Source/cmInstallCommand.h
  12. 3 0
      Source/cmInstallExportGenerator.cxx
  13. 2 1
      Source/cmInstallExportGenerator.h
  14. 31 0
      Source/cmPolicies.cxx
  15. 1 0
      Source/cmPolicies.h
  16. 203 9
      Source/cmTarget.cxx
  17. 8 0
      Source/cmTarget.h
  18. 25 1
      Source/cmTargetLinkLibrariesCommand.cxx
  19. 15 8
      Source/cmTargetLinkLibrariesCommand.h
  20. 2 0
      Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
  21. 18 0
      Tests/CMakeCommands/target_link_libraries/cmp0022/CMakeLists.txt
  22. 7 0
      Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022exe.cpp
  23. 9 0
      Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022ifacelib.cpp
  24. 9 0
      Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022ifacelib.h
  25. 7 0
      Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022lib.cpp
  26. 6 0
      Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022lib.h
  27. 10 0
      Tests/CMakeLists.txt
  28. 29 0
      Tests/ExportImport/Export/CMakeLists.txt
  29. 7 0
      Tests/ExportImport/Export/cmp0022.cpp
  30. 4 0
      Tests/ExportImport/Export/cmp0022.h
  31. 1 0
      Tests/ExportImport/Export/cmp0022_vs6_1.cpp
  32. 1 0
      Tests/ExportImport/Export/cmp0022_vs6_2.cpp
  33. 10 0
      Tests/ExportImport/Import/A/CMakeLists.txt
  34. 12 0
      Tests/ExportImport/Import/A/cmp0022NEW_test.cpp
  35. 1 0
      Tests/ExportImport/Import/A/cmp0022NEW_test_vs6_1.cpp
  36. 1 0
      Tests/ExportImport/Import/A/cmp0022NEW_test_vs6_2.cpp
  37. 12 0
      Tests/ExportImport/Import/A/cmp0022OLD_test.cpp
  38. 1 0
      Tests/ExportImport/Import/A/cmp0022OLD_test_vs6_1.cpp
  39. 1 0
      Tests/ExportImport/Import/A/cmp0022OLD_test_vs6_2.cpp
  40. 49 0
      Tests/InterfaceLinkLibraries/CMakeLists.txt
  41. 15 0
      Tests/InterfaceLinkLibraries/bang.cpp
  42. 4 0
      Tests/InterfaceLinkLibraries/bang.h
  43. 1 0
      Tests/InterfaceLinkLibraries/bang_vs6_1.cpp
  44. 1 0
      Tests/InterfaceLinkLibraries/bang_vs6_2.cpp
  45. 26 0
      Tests/InterfaceLinkLibraries/bar.cpp
  46. 7 0
      Tests/InterfaceLinkLibraries/bar.h
  47. 1 0
      Tests/InterfaceLinkLibraries/bar_vs6_1.cpp
  48. 1 0
      Tests/InterfaceLinkLibraries/bar_vs6_2.cpp
  49. 1 0
      Tests/InterfaceLinkLibraries/bar_vs6_3.cpp
  50. 1 0
      Tests/InterfaceLinkLibraries/bar_vs6_4.cpp
  51. 15 0
      Tests/InterfaceLinkLibraries/foo.cpp
  52. 4 0
      Tests/InterfaceLinkLibraries/foo.h
  53. 1 0
      Tests/InterfaceLinkLibraries/foo_vs6_1.cpp
  54. 1 0
      Tests/InterfaceLinkLibraries/foo_vs6_2.cpp
  55. 1 0
      Tests/InterfaceLinkLibraries/foo_vs6_3.cpp
  56. 1 0
      Tests/InterfaceLinkLibraries/foo_vs6_4.cpp
  57. 19 0
      Tests/InterfaceLinkLibraries/main.cpp
  58. 1 0
      Tests/InterfaceLinkLibraries/main_vs6_1.cpp
  59. 1 0
      Tests/InterfaceLinkLibraries/main_vs6_2.cpp
  60. 1 0
      Tests/InterfaceLinkLibraries/main_vs6_3.cpp
  61. 1 0
      Tests/InterfaceLinkLibraries/main_vs6_4.cpp
  62. 1 0
      Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-link_libraries-stderr.txt
  63. 9 0
      Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-link_libraries.cmake
  64. 1 0
      Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-stderr.txt
  65. 8 0
      Tests/RunCMake/CMP0022/CMP0022-NOWARN-static.cmake
  66. 1 0
      Tests/RunCMake/CMP0022/CMP0022-WARN-static-result.txt
  67. 10 0
      Tests/RunCMake/CMP0022/CMP0022-WARN-static-stderr.txt
  68. 11 0
      Tests/RunCMake/CMP0022/CMP0022-WARN-static.cmake
  69. 8 0
      Tests/RunCMake/CMP0022/CMP0022-WARN-stderr.txt
  70. 1 0
      Tests/RunCMake/CMP0022/CMP0022-WARN-tll-result.txt
  71. 8 0
      Tests/RunCMake/CMP0022/CMP0022-WARN-tll-stderr.txt
  72. 11 0
      Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake
  73. 11 0
      Tests/RunCMake/CMP0022/CMP0022-WARN.cmake
  74. 1 0
      Tests/RunCMake/CMP0022/CMP0022-export-result.txt
  75. 4 0
      Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt
  76. 11 0
      Tests/RunCMake/CMP0022/CMP0022-export.cmake
  77. 1 0
      Tests/RunCMake/CMP0022/CMP0022-install-export-result.txt
  78. 4 0
      Tests/RunCMake/CMP0022/CMP0022-install-export-stderr.txt
  79. 12 0
      Tests/RunCMake/CMP0022/CMP0022-install-export.cmake
  80. 3 0
      Tests/RunCMake/CMP0022/CMakeLists.txt
  81. 9 0
      Tests/RunCMake/CMP0022/RunCMakeTest.cmake
  82. 2 0
      Tests/RunCMake/CMP0022/dep1/CMakeLists.txt
  83. 2 0
      Tests/RunCMake/CMP0022/dep2/CMakeLists.txt
  84. 5 0
      Tests/RunCMake/CMP0022/dep3/CMakeLists.txt
  85. 7 0
      Tests/RunCMake/CMP0022/empty.cpp
  86. 1 0
      Tests/RunCMake/CMP0022/empty_vs6_1.cpp
  87. 1 0
      Tests/RunCMake/CMP0022/empty_vs6_2.cpp
  88. 1 0
      Tests/RunCMake/CMP0022/empty_vs6_3.cpp
  89. 1 0
      Tests/RunCMake/CMakeLists.txt

+ 9 - 0
Source/cmExportBuildFileGenerator.cxx

@@ -77,6 +77,15 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
                                     properties, missingTargets);
     this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
                                   te, properties);
+    const bool newCMP0022Behavior =
+                              te->GetPolicyStatusCMP0022() != cmPolicies::WARN
+                           && te->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+    if (newCMP0022Behavior)
+      {
+      this->PopulateInterfaceLinkLibrariesProperty(te,
+                                    cmGeneratorExpression::BuildInterface,
+                                    properties, missingTargets);
+      }
     this->PopulateCompatibleInterfaceProperties(te, properties);
 
     this->GenerateInterfaceProperties(te, os, properties);

+ 2 - 0
Source/cmExportCommand.cxx

@@ -30,6 +30,7 @@ cmExportCommand::cmExportCommand()
 ,Append(&Helper, "APPEND", &ArgumentGroup)
 ,Namespace(&Helper, "NAMESPACE", &ArgumentGroup)
 ,Filename(&Helper, "FILE", &ArgumentGroup)
+,ExportOld(&Helper, "EXPORT_LINK_INTERFACE_LIBRARIES", &ArgumentGroup)
 {
   // at first TARGETS
   this->Targets.Follows(0);
@@ -158,6 +159,7 @@ bool cmExportCommand
   ebfg.SetAppendMode(this->Append.IsEnabled());
   ebfg.SetExports(&targets);
   ebfg.SetCommand(this);
+  ebfg.SetExportOld(this->ExportOld.IsEnabled());
 
   // Compute the set of configurations exported.
   std::vector<std::string> configurationTypes;

+ 6 - 1
Source/cmExportCommand.h

@@ -63,7 +63,7 @@ public:
     {
     return
       "  export(TARGETS [target1 [target2 [...]]] [NAMESPACE <namespace>]\n"
-      "         [APPEND] FILE <filename>)\n"
+      "         [APPEND] FILE <filename> [EXPORT_LINK_INTERFACE_LIBRARIES])\n"
       "Create a file <filename> that may be included by outside projects to "
       "import targets from the current project's build tree.  "
       "This is useful during cross-compiling to build utility executables "
@@ -73,6 +73,10 @@ public:
       "prepended to all target names written to the file.  "
       "If the APPEND option is given the generated code will be appended "
       "to the file instead of overwriting it.  "
+      "The EXPORT_LINK_INTERFACE_LIBRARIES keyword, if present, causes the "
+      "contents of the properties matching "
+      "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? to be exported, when "
+      "policy CMP0022 is NEW.  "
       "If a library target is included in the export but "
       "a target to which it links is not included the behavior is "
       "unspecified."
@@ -104,6 +108,7 @@ private:
   cmCAEnabler Append;
   cmCAString Namespace;
   cmCAString Filename;
+  cmCAEnabler ExportOld;
 
   friend class cmExportBuildFileGenerator;
   std::string ErrorMessage;

+ 50 - 0
Source/cmExportFileGenerator.cxx

@@ -30,6 +30,7 @@
 cmExportFileGenerator::cmExportFileGenerator()
 {
   this->AppendMode = false;
+  this->ExportOld = false;
 }
 
 //----------------------------------------------------------------------------
@@ -168,6 +169,39 @@ void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
     }
 }
 
+void cmExportFileGenerator::GenerateRequiredCMakeVersion(std::ostream& os,
+                                                    const char *versionString)
+{
+  os << "if(CMAKE_VERSION VERSION_LESS " << versionString << ")\n"
+        "  message(FATAL_ERROR \"This file relies on consumers using "
+        "CMake " << versionString << " or greater.\")\n"
+        "endif()\n\n";
+}
+
+//----------------------------------------------------------------------------
+bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
+                      cmTarget *target,
+                      cmGeneratorExpression::PreprocessContext preprocessRule,
+                      ImportPropertyMap &properties,
+                      std::vector<std::string> &missingTargets)
+{
+  const char *input = target->GetProperty("INTERFACE_LINK_LIBRARIES");
+  if (input)
+    {
+    std::string prepro = cmGeneratorExpression::Preprocess(input,
+                                                           preprocessRule);
+    if (!prepro.empty())
+      {
+      this->ResolveTargetsInGeneratorExpressions(prepro, target,
+                                                 missingTargets,
+                                                 ReplaceFreeTargets);
+      properties["INTERFACE_LINK_LIBRARIES"] = prepro;
+      return true;
+      }
+    }
+  return false;
+}
+
 //----------------------------------------------------------------------------
 static bool isSubDirectory(const char* a, const char* b)
 {
@@ -583,6 +617,22 @@ cmExportFileGenerator
     return;
     }
 
+  const bool newCMP0022Behavior =
+                        target->GetPolicyStatusCMP0022() != cmPolicies::WARN
+                     && target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+
+  if(newCMP0022Behavior && !this->ExportOld)
+    {
+    cmMakefile *mf = target->GetMakefile();
+    cmOStringStream e;
+    e << "Target \"" << target->GetName() << "\" has policy CMP0022 enabled, "
+         "but also has old-style INTERFACE_LINK_LIBRARIES properties "
+         "populated, but it was exported without the "
+         "EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties";
+    mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+    return;
+    }
+
   if (!*propContent)
     {
     properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = "";

+ 11 - 0
Source/cmExportFileGenerator.h

@@ -35,6 +35,8 @@ public:
   /** Set the namespace in which to place exported target names.  */
   void SetNamespace(const char* ns) { this->Namespace = ns; }
 
+  void SetExportOld(bool exportOld) { this->ExportOld = exportOld; }
+
   /** Add a configuration to be exported.  */
   void AddConfiguration(const char* config);
 
@@ -101,6 +103,10 @@ protected:
                                  cmGeneratorExpression::PreprocessContext,
                                  ImportPropertyMap &properties,
                                  std::vector<std::string> &missingTargets);
+  bool PopulateInterfaceLinkLibrariesProperty(cmTarget *target,
+                                 cmGeneratorExpression::PreprocessContext,
+                                 ImportPropertyMap &properties,
+                                 std::vector<std::string> &missingTargets);
   void PopulateInterfaceProperty(const char *propName, cmTarget *target,
                                  ImportPropertyMap &properties);
   void PopulateCompatibleInterfaceProperties(cmTarget *target,
@@ -128,9 +134,14 @@ protected:
                           std::vector<std::string> &missingTargets,
                           FreeTargetsReplace replace = NoReplaceFreeTargets);
 
+  void GenerateRequiredCMakeVersion(std::ostream& os,
+                                    const char *versionString);
+
   // The namespace in which the exports are placed in the generated file.
   std::string Namespace;
 
+  bool ExportOld;
+
   // The set of configurations to export.
   std::vector<std::string> Configurations;
 

+ 19 - 0
Source/cmExportInstallFileGenerator.cxx

@@ -113,6 +113,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
 
   std::vector<std::string> missingTargets;
 
+  bool require2_8_12 = false;
   // Create all the imported targets.
   for(std::vector<cmTarget*>::const_iterator
         tei = allTargets.begin();
@@ -134,6 +135,20 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
                                   te,
                                   cmGeneratorExpression::InstallInterface,
                                   properties, missingTargets);
+
+    const bool newCMP0022Behavior =
+                              te->GetPolicyStatusCMP0022() != cmPolicies::WARN
+                           && te->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+    if (newCMP0022Behavior)
+      {
+      if (this->PopulateInterfaceLinkLibrariesProperty(te,
+                                    cmGeneratorExpression::InstallInterface,
+                                    properties, missingTargets)
+          && !this->ExportOld)
+        {
+        require2_8_12 = true;
+        }
+      }
     this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
                                   te, properties);
     this->PopulateCompatibleInterfaceProperties(te, properties);
@@ -141,6 +156,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
     this->GenerateInterfaceProperties(te, os, properties);
     }
 
+  if (require2_8_12)
+    {
+    this->GenerateRequiredCMakeVersion(os, "2.8.11.20130626");
+    }
 
   // Now load per-configuration properties for them.
   os << "# Load information for each installed configuration.\n"

+ 17 - 2
Source/cmGeneratorExpressionDAGChecker.cxx

@@ -22,7 +22,7 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
                 const GeneratorExpressionContent *content,
                 cmGeneratorExpressionDAGChecker *parent)
   : Parent(parent), Target(target), Property(property),
-    Content(content), Backtrace(backtrace)
+    Content(content), Backtrace(backtrace), TransitivePropertiesOnly(false)
 {
   const cmGeneratorExpressionDAGChecker *top = this;
   const cmGeneratorExpressionDAGChecker *p = this->Parent;
@@ -138,6 +138,20 @@ cmGeneratorExpressionDAGChecker::checkGraph() const
   return DAG;
 }
 
+//----------------------------------------------------------------------------
+bool cmGeneratorExpressionDAGChecker::GetTransitivePropertiesOnly()
+{
+  const cmGeneratorExpressionDAGChecker *top = this;
+  const cmGeneratorExpressionDAGChecker *parent = this->Parent;
+  while (parent)
+    {
+    top = parent;
+    parent = parent->Parent;
+    }
+
+  return top->TransitivePropertiesOnly;
+}
+
 //----------------------------------------------------------------------------
 bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char *tgt)
 {
@@ -160,7 +174,8 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char *tgt)
        || strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0
        || strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0
        || strncmp(prop, "LINK_INTERFACE_LIBRARIES_", 25) == 0
-       || strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 34) == 0);
+       || strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 34) == 0)
+       || strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
 }
 
 //----------------------------------------------------------------------------

+ 5 - 0
Source/cmGeneratorExpressionDAGChecker.h

@@ -54,6 +54,10 @@ struct cmGeneratorExpressionDAGChecker
 
 CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(DECLARE_TRANSITIVE_PROPERTY_METHOD)
 
+  bool GetTransitivePropertiesOnly();
+  void SetTransitivePropertiesOnly()
+    { this->TransitivePropertiesOnly = true; }
+
 private:
   Result checkGraph() const;
 
@@ -65,6 +69,7 @@ private:
   const GeneratorExpressionContent * const Content;
   const cmListFileBacktrace Backtrace;
   Result CheckResult;
+  bool TransitivePropertiesOnly;
 };
 
 #endif

+ 26 - 5
Source/cmGeneratorExpressionEvaluator.cxx

@@ -491,6 +491,24 @@ static const struct VersionEqualNode : public cmGeneratorExpressionNode
   }
 } versionEqualNode;
 
+//----------------------------------------------------------------------------
+static const struct LinkOnlyNode : public cmGeneratorExpressionNode
+{
+  LinkOnlyNode() {}
+
+  std::string Evaluate(const std::vector<std::string> &parameters,
+                       cmGeneratorExpressionContext *,
+                       const GeneratorExpressionContent *,
+                       cmGeneratorExpressionDAGChecker *dagChecker) const
+  {
+    if(!dagChecker->GetTransitivePropertiesOnly())
+      {
+      return parameters.front();
+      }
+    return "";
+  }
+} linkOnlyNode;
+
 //----------------------------------------------------------------------------
 static const struct ConfigurationNode : public cmGeneratorExpressionNode
 {
@@ -900,13 +918,14 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
     if (std::find_if(transBegin, transEnd,
               TransitiveWhitelistCompare(propertyName)) != transEnd)
       {
-      const cmTarget::LinkInterface *iface = target->GetLinkInterface(
-                                                    context->Config,
-                                                    headTarget);
-      if(iface)
+
+      std::vector<std::string> libs;
+      target->GetTransitivePropertyLinkLibraries(context->Config,
+                                                 headTarget, libs);
+      if (!libs.empty())
         {
         linkedTargetsContent =
-                  getLinkedTargetsContent(iface->Libraries, target,
+                  getLinkedTargetsContent(libs, target,
                                           headTarget,
                                           context, &dagChecker,
                                           interfacePropertyName);
@@ -1395,6 +1414,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
     return &installPrefixNode;
   else if (identifier == "JOIN")
     return &joinNode;
+  else if (identifier == "LINK_ONLY")
+    return &linkOnlyNode;
   return 0;
 
 }

+ 30 - 3
Source/cmInstallCommand.cxx

@@ -1196,6 +1196,8 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
   cmInstallCommandArguments ica(this->DefaultComponentName);
   cmCAString exp(&ica.Parser, "EXPORT");
   cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup);
+  cmCAEnabler exportOld(&ica.Parser, "EXPORT_LINK_INTERFACE_LIBRARIES",
+                        &ica.ArgumentGroup);
   cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
   exp.Follows(0);
 
@@ -1268,15 +1270,40 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
       }
     }
 
+  cmExportSet *exportSet = this->Makefile->GetLocalGenerator()
+                    ->GetGlobalGenerator()->GetExportSets()[exp.GetString()];
+  if (exportOld.IsEnabled())
+    {
+    for(std::vector<cmTargetExport*>::const_iterator
+          tei = exportSet->GetTargetExports()->begin();
+        tei != exportSet->GetTargetExports()->end(); ++tei)
+      {
+      cmTargetExport const* te = *tei;
+      const bool newCMP0022Behavior =
+                      te->Target->GetPolicyStatusCMP0022() != cmPolicies::WARN
+                   && te->Target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+
+      if(!newCMP0022Behavior)
+        {
+        cmOStringStream e;
+        e << "INSTALL(EXPORT) given keyword \""
+          << "EXPORT_LINK_INTERFACE_LIBRARIES" << "\", but target \""
+          << te->Target->GetName()
+          << "\" does not have policy CMP0022 set to NEW.";
+        this->SetError(e.str().c_str());
+        return false;
+        }
+      }
+    }
+
   // Create the export install generator.
   cmInstallExportGenerator* exportGenerator =
     new cmInstallExportGenerator(
-      this->Makefile->GetLocalGenerator()
-          ->GetGlobalGenerator()->GetExportSets()[exp.GetString()],
+      exportSet,
       ica.GetDestination().c_str(),
       ica.GetPermissions().c_str(), ica.GetConfigurations(),
       ica.GetComponent().c_str(), fname.c_str(),
-      name_space.GetCString(), this->Makefile);
+      name_space.GetCString(), exportOld.IsEnabled(), this->Makefile);
   this->Makefile->AddInstallGenerator(exportGenerator);
 
   return true;

+ 5 - 0
Source/cmInstallCommand.h

@@ -291,6 +291,7 @@ public:
       "          [NAMESPACE <namespace>] [FILE <name>.cmake]\n"
       "          [PERMISSIONS permissions...]\n"
       "          [CONFIGURATIONS [Debug|Release|...]]\n"
+      "          [EXPORT_LINK_INTERFACE_LIBRARIES]\n"
       "          [COMPONENT <component>])\n"
       "The EXPORT form generates and installs a CMake file containing code "
       "to import targets from the installation tree into another project.  "
@@ -306,6 +307,10 @@ public:
       "installed when one of the named configurations is installed.  "
       "Additionally, the generated import file will reference only the "
       "matching target configurations.  "
+      "The EXPORT_LINK_INTERFACE_LIBRARIES keyword, if present, causes the "
+      "contents of the properties matching "
+      "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? to be exported, when "
+      "policy CMP0022 is NEW.  "
       "If a COMPONENT option is specified that does not match that given "
       "to the targets associated with <export-name> the behavior is "
       "undefined.  "

+ 3 - 0
Source/cmInstallExportGenerator.cxx

@@ -33,12 +33,14 @@ cmInstallExportGenerator::cmInstallExportGenerator(
   std::vector<std::string> const& configurations,
   const char* component,
   const char* filename, const char* name_space,
+  bool exportOld,
   cmMakefile* mf)
   :cmInstallGenerator(destination, configurations, component)
   ,ExportSet(exportSet)
   ,FilePermissions(file_permissions)
   ,FileName(filename)
   ,Namespace(name_space)
+  ,ExportOld(exportOld)
   ,Makefile(mf)
 {
   this->EFGen = new cmExportInstallFileGenerator(this);
@@ -137,6 +139,7 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
   // Generate the import file for this export set.
   this->EFGen->SetExportFile(this->MainImportFile.c_str());
   this->EFGen->SetNamespace(this->Namespace.c_str());
+  this->EFGen->SetExportOld(this->ExportOld);
   if(this->ConfigurationTypes->empty())
     {
     if(this->ConfigurationName && *this->ConfigurationName)

+ 2 - 1
Source/cmInstallExportGenerator.h

@@ -31,7 +31,7 @@ public:
                            const std::vector<std::string>& configurations,
                            const char* component,
                            const char* filename, const char* name_space,
-                           cmMakefile* mf);
+                           bool exportOld, cmMakefile* mf);
   ~cmInstallExportGenerator();
 
   cmExportSet* GetExportSet() {return this->ExportSet;}
@@ -52,6 +52,7 @@ protected:
   std::string FilePermissions;
   std::string FileName;
   std::string Namespace;
+  bool ExportOld;
   cmMakefile* Makefile;
 
   std::string TempDir;

+ 31 - 0
Source/cmPolicies.cxx

@@ -544,6 +544,37 @@ cmPolicies::cmPolicies()
     "The NEW behavior for this policy is to issue a FATAL_ERROR if "
     "INCLUDE_DIRECTORIES contains a relative path.",
     2,8,11,20130516, cmPolicies::WARN);
+
+  this->DefinePolicy(
+    CMP0022, "CMP0022",
+    "INTERFACE_LINK_LIBRARIES defines the link interface.",
+    "CMake 2.8.11 constructed the 'link interface' of a target from "
+    "properties matching (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?.  "
+    "The modern way to specify config-sensitive content is to use generator "
+    "expressions and the IMPORTED_ prefix makes uniform processing of the "
+    "link interface with generator expressions impossible.  The "
+    "INTERFACE_LINK_LIBRARIES target property was introduced as a "
+    "replacement in CMake 2.8.12. This new property is named consistently "
+    "with the INTERFACE_COMPILE_DEFINITIONS, INTERFACE_INCLUDE_DIRECTORIES "
+    "and INTERFACE_COMPILE_OPTIONS properties.  For in-build targets, CMake "
+    "will use the INTERFACE_LINK_LIBRARIES property as the source of the "
+    "link interface only if policy CMP0022 is NEW.  "
+    "When exporting a target which has this policy set to NEW, only the "
+    "INTERFACE_LINK_LIBRARIES property will be processed and generated for "
+    "the IMPORTED target by default.  A new option to the install(EXPORT) "
+    "and export commands allows export of the old-style properties for "
+    "compatibility with downstream users of CMake versions older than "
+    "2.8.12.  "
+    "The target_link_libraries command will no longer populate the "
+    "properties matching LINK_INTERFACE_LIBRARIES(_<CONFIG>)? if this policy "
+    "is NEW."
+    "\n"
+    "The OLD behavior for this policy is to ignore the "
+    "INTERFACE_LINK_LIBRARIES property for in-build targets.  "
+    "The NEW behavior for this policy is to use the INTERFACE_LINK_LIBRARIES "
+    "property for in-build targets, and ignore the old properties matching "
+    "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?.",
+    2,8,11,20130516, cmPolicies::WARN);
 }
 
 cmPolicies::~cmPolicies()

+ 1 - 0
Source/cmPolicies.h

@@ -72,6 +72,7 @@ public:
     CMP0020, ///< Automatically link Qt executables to qtmain target
     CMP0021, ///< Fatal error on relative paths in INCLUDE_DIRECTORIES
     /// target property
+    CMP0022, ///< INTERFACE_LINK_LIBRARIES defines the link interface
 
     /** \brief Always the last entry.
      *

+ 203 - 9
Source/cmTarget.cxx

@@ -197,6 +197,7 @@ cmTarget::cmTarget()
   this->PolicyStatusCMP0008 = cmPolicies::WARN;
   this->PolicyStatusCMP0020 = cmPolicies::WARN;
   this->PolicyStatusCMP0021 = cmPolicies::WARN;
+  this->PolicyStatusCMP0022 = cmPolicies::WARN;
   this->LinkLibrariesAnalyzed = false;
   this->HaveInstallRule = false;
   this->DLLPlatform = false;
@@ -474,7 +475,7 @@ void cmTarget::DefineProperties(cmake *cm)
      "imported library.  "
      "The list "
      "should be disjoint from the list of interface libraries in the "
-     "IMPORTED_LINK_INTERFACE_LIBRARIES property.  On platforms requiring "
+     "INTERFACE_LINK_LIBRARIES property.  On platforms requiring "
      "dependent shared libraries to be found at link time CMake uses this "
      "list to add appropriate files or paths to the link command line.  "
      "Ignored for non-imported targets.");
@@ -495,7 +496,10 @@ void cmTarget::DefineProperties(cmake *cm)
      "The libraries will be included on the link line for the target.  "
      "Unlike the LINK_INTERFACE_LIBRARIES property, this property applies "
      "to all imported target types, including STATIC libraries.  "
-     "This property is ignored for non-imported targets.");
+     "This property is ignored for non-imported targets.\n"
+     "This property is ignored if the target also has a non-empty "
+     "INTERFACE_LINK_LIBRARIES property.\n"
+     "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
 
   cm->DefineProperty
     ("IMPORTED_LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET,
@@ -503,7 +507,10 @@ void cmTarget::DefineProperties(cmake *cm)
      "Configuration names correspond to those provided by the project "
      "from which the target is imported.  "
      "If set, this property completely overrides the generic property "
-     "for the named configuration.");
+     "for the named configuration.\n"
+     "This property is ignored if the target also has a non-empty "
+     "INTERFACE_LINK_LIBRARIES property.\n"
+     "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
 
   cm->DefineProperty
     ("IMPORTED_LINK_INTERFACE_LANGUAGES", cmProperty::TARGET,
@@ -820,7 +827,10 @@ void cmTarget::DefineProperties(cmake *cm)
      "This property is initialized by the value of the variable "
      "CMAKE_LINK_INTERFACE_LIBRARIES if it is set when a target is "
      "created.  "
-     "This property is ignored for STATIC libraries.");
+     "This property is ignored for STATIC libraries.\n"
+     "This property is overriden by the INTERFACE_LINK_LIBRARIES property if "
+     "policy CMP0022 is NEW.\n"
+     "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
 
   cm->DefineProperty
     ("LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET,
@@ -828,7 +838,23 @@ void cmTarget::DefineProperties(cmake *cm)
      "This is the configuration-specific version of "
      "LINK_INTERFACE_LIBRARIES.  "
      "If set, this property completely overrides the generic property "
-     "for the named configuration.");
+     "for the named configuration.\n"
+     "This property is overriden by the INTERFACE_LINK_LIBRARIES property if "
+     "policy CMP0022 is NEW.\n"
+     "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
+
+  cm->DefineProperty
+    ("INTERFACE_LINK_LIBRARIES", cmProperty::TARGET,
+     "List public interface libraries for a shared library or executable.",
+     "This property contains the list of transitive link dependencies.  "
+     "When the target is linked into another target the libraries "
+     "listed (and recursively their link interface libraries) will be "
+     "provided to the other target also.  "
+     "This property is overriden by the LINK_INTERFACE_LIBRARIES or "
+     "LINK_INTERFACE_LIBRARIES_<CONFIG> property if "
+     "policy CMP0022 is OLD or unset.\n"
+     "\n"
+     CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
 
   cm->DefineProperty
     ("INTERFACE_INCLUDE_DIRECTORIES", cmProperty::TARGET,
@@ -1678,6 +1704,8 @@ void cmTarget::SetMakefile(cmMakefile* mf)
     this->Makefile->GetPolicyStatus(cmPolicies::CMP0020);
   this->PolicyStatusCMP0021 =
     this->Makefile->GetPolicyStatus(cmPolicies::CMP0021);
+  this->PolicyStatusCMP0022 =
+    this->Makefile->GetPolicyStatus(cmPolicies::CMP0022);
 }
 
 //----------------------------------------------------------------------------
@@ -2293,6 +2321,14 @@ void cmTarget::MergeLinkLibraries( cmMakefile& mf,
     {
     // We call this so that the dependencies get written to the cache
     this->AddLinkLibrary( mf, selfname, i->first.c_str(), i->second );
+
+    if (this->GetType() == cmTarget::STATIC_LIBRARY)
+      {
+      this->AppendProperty("INTERFACE_LINK_LIBRARIES",
+            ("$<LINK_ONLY:" +
+            this->GetDebugGeneratorExpressions(i->first.c_str(), i->second) +
+            ">").c_str());
+      }
     }
   this->PrevLinkedLibraries = libs;
 }
@@ -3527,6 +3563,29 @@ static void cmTargetCheckLINK_INTERFACE_LIBRARIES(
   context->IssueMessage(cmake::FATAL_ERROR, e.str());
 }
 
+//----------------------------------------------------------------------------
+static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value,
+                                                  cmMakefile* context)
+{
+  // Look for link-type keywords in the value.
+  static cmsys::RegularExpression
+    keys("(^|;)(debug|optimized|general)(;|$)");
+  if(!keys.find(value))
+    {
+    return;
+    }
+
+  // Report an error.
+  cmOStringStream e;
+
+  e << "Property INTERFACE_LINK_LIBRARIES may not contain link-type "
+    "keyword \"" << keys.match(2) << "\".  The INTERFACE_LINK_LIBRARIES "
+    "property may contain configuration-sensitive generator-expressions "
+    "which may be used to specify per-configuration rules.";
+
+  context->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
 //----------------------------------------------------------------------------
 void cmTarget::CheckProperty(const char* prop, cmMakefile* context)
 {
@@ -3545,6 +3604,13 @@ void cmTarget::CheckProperty(const char* prop, cmMakefile* context)
       cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true);
       }
     }
+  if(strncmp(prop, "INTERFACE_LINK_LIBRARIES", 24) == 0)
+    {
+    if(const char* value = this->GetProperty(prop))
+      {
+      cmTargetCheckINTERFACE_LINK_LIBRARIES(value, context);
+      }
+    }
 }
 
 //----------------------------------------------------------------------------
@@ -5880,11 +5946,16 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
 
   // Get the link interface.
   {
-  std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
-  linkProp += suffix;
-
+  std::string linkProp = "INTERFACE_LINK_LIBRARIES";
   const char *propertyLibs = this->GetProperty(linkProp.c_str());
 
+  if (!propertyLibs)
+    {
+    linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
+    linkProp += suffix;
+    propertyLibs = this->GetProperty(linkProp.c_str());
+    }
+
   if(!propertyLibs)
     {
     linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
@@ -6001,6 +6072,48 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config,
   return i->second.Exists? &i->second : 0;
 }
 
+//----------------------------------------------------------------------------
+void cmTarget::GetTransitivePropertyLinkLibraries(
+                                      const char* config,
+                                      cmTarget *headTarget,
+                                      std::vector<std::string> &libs)
+{
+  cmTarget::LinkInterface const* iface = this->GetLinkInterface(config,
+                                                                headTarget);
+  if (!iface)
+    {
+    return;
+    }
+  if(this->GetType() != STATIC_LIBRARY
+      || this->GetPolicyStatusCMP0022() == cmPolicies::WARN
+      || this->GetPolicyStatusCMP0022() == cmPolicies::OLD)
+    {
+    libs = iface->Libraries;
+    return;
+    }
+
+  const char* linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
+  const char* interfaceLibs = this->GetProperty(linkIfaceProp);
+
+  if (!interfaceLibs)
+    {
+    return;
+    }
+
+  // The interface libraries have been explicitly set.
+  cmListFileBacktrace lfbt;
+  cmGeneratorExpression ge(lfbt);
+  cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
+                                              linkIfaceProp, 0, 0);
+  dagChecker.SetTransitivePropertiesOnly();
+  cmSystemTools::ExpandListArgument(ge.Parse(interfaceLibs)->Evaluate(
+                                      this->Makefile,
+                                      config,
+                                      false,
+                                      headTarget,
+                                      this, &dagChecker), libs);
+}
+
 //----------------------------------------------------------------------------
 bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
                                     cmTarget *headTarget)
@@ -6019,6 +6132,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
   // An explicit list of interface libraries may be set for shared
   // libraries and executables that export symbols.
   const char* explicitLibraries = 0;
+  const char* newExplicitLibraries =
+                                this->GetProperty("INTERFACE_LINK_LIBRARIES");
   std::string linkIfaceProp;
   if(this->GetType() == cmTarget::SHARED_LIBRARY ||
      this->IsExecutableWithExports())
@@ -6034,6 +6149,81 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
       linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
       explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
       }
+    if (newExplicitLibraries
+        && (!explicitLibraries ||
+            (explicitLibraries
+              && strcmp(newExplicitLibraries, explicitLibraries) != 0)))
+      {
+      switch(this->GetPolicyStatusCMP0022())
+        {
+        case cmPolicies::WARN:
+          {
+          cmOStringStream w;
+          w << (this->Makefile->GetPolicies()
+                ->GetPolicyWarning(cmPolicies::CMP0022)) << "\n"
+            << "Target \"" << this->GetName() << "\" has a "
+              "INTERFACE_LINK_LIBRARIES property which differs from its "
+            << linkIfaceProp << " properties.";
+          this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+          }
+          // Fall through
+        case cmPolicies::OLD:
+          break;
+        case cmPolicies::REQUIRED_IF_USED:
+        case cmPolicies::REQUIRED_ALWAYS:
+        case cmPolicies::NEW:
+          explicitLibraries = newExplicitLibraries;
+          linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
+          break;
+        }
+      }
+    }
+  else if(this->GetType() == cmTarget::STATIC_LIBRARY)
+    {
+    if (newExplicitLibraries)
+      {
+      cmListFileBacktrace lfbt;
+      cmGeneratorExpression ge(lfbt);
+      cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
+                                            "INTERFACE_LINK_LIBRARIES", 0, 0);
+      std::vector<std::string> ifaceLibs;
+      cmSystemTools::ExpandListArgument(
+          ge.Parse(newExplicitLibraries)->Evaluate(
+                                          this->Makefile,
+                                          config,
+                                          false,
+                                          headTarget,
+                                          this, &dagChecker), ifaceLibs);
+      LinkImplementation const* impl = this->GetLinkImplementation(config,
+                                                                headTarget);
+      if (ifaceLibs != impl->Libraries)
+        {
+        switch(this->GetPolicyStatusCMP0022())
+          {
+          case cmPolicies::WARN:
+            {
+            cmOStringStream w;
+            w << (this->Makefile->GetPolicies()
+                  ->GetPolicyWarning(cmPolicies::CMP0022)) << "\n"
+              << "Static library target \"" << this->GetName() << "\" has a "
+                "INTERFACE_LINK_LIBRARIES property.  This should be preferred "
+                "as the source of the link interface for this library.  "
+                "Ignoring the property and using the link implementation "
+                "as the link interface instead.";
+            this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+            }
+            // Fall through
+          case cmPolicies::OLD:
+            break;
+          case cmPolicies::REQUIRED_IF_USED:
+          case cmPolicies::REQUIRED_ALWAYS:
+          case cmPolicies::NEW:
+            explicitLibraries = newExplicitLibraries;
+            linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
+            break;
+          }
+        }
+      }
     }
 
   // There is no implicit link interface for executables or modules
@@ -6097,7 +6287,11 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
         }
       }
     }
-  else
+  else if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN
+        || this->GetPolicyStatusCMP0022() == cmPolicies::OLD)
+    // The implementation shouldn't be the interface if CMP0022 is NEW. That
+    // way, the LINK_LIBRARIES property can be set directly without having to
+    // empty the INTERFACE_LINK_LIBRARIES
     {
     // The link implementation is the default link interface.
     LinkImplementation const* impl = this->GetLinkImplementation(config,

+ 8 - 0
Source/cmTarget.h

@@ -111,6 +111,10 @@ public:
   cmPolicies::PolicyStatus GetPolicyStatusCMP0021() const
     { return this->PolicyStatusCMP0021; }
 
+  /** Get the status of policy CMP0022 when the target was created.  */
+  cmPolicies::PolicyStatus GetPolicyStatusCMP0022() const
+    { return this->PolicyStatusCMP0022; }
+
   /**
    * Get the list of the custom commands for this target
    */
@@ -276,6 +280,9 @@ public:
       if the target cannot be linked.  */
   LinkInterface const* GetLinkInterface(const char* config,
                                         cmTarget *headTarget);
+  void GetTransitivePropertyLinkLibraries(const char* config,
+                                        cmTarget *headTarget,
+                                        std::vector<std::string> &libs);
 
   /** The link implementation specifies the direct library
       dependencies needed by the object files of the target.  */
@@ -692,6 +699,7 @@ private:
   cmPolicies::PolicyStatus PolicyStatusCMP0008;
   cmPolicies::PolicyStatus PolicyStatusCMP0020;
   cmPolicies::PolicyStatus PolicyStatusCMP0021;
+  cmPolicies::PolicyStatus PolicyStatusCMP0022;
 
   // Internal representation details.
   friend class cmTargetInternals;

+ 25 - 1
Source/cmTargetLinkLibrariesCommand.cxx

@@ -224,12 +224,17 @@ bool cmTargetLinkLibrariesCommand
     cmSystemTools::SetFatalErrorOccured();
     }
 
+  const cmPolicies::PolicyStatus policy22Status
+                      = this->Target->GetPolicyStatusCMP0022();
+
   // If any of the LINK_ options were given, make sure the
   // LINK_INTERFACE_LIBRARIES target property exists.
   // Use of any of the new keywords implies awareness of
   // this property. And if no libraries are named, it should
   // result in an empty link interface.
-  if(this->CurrentProcessingState != ProcessingLinkLibraries &&
+  if((policy22Status == cmPolicies::OLD ||
+      policy22Status == cmPolicies::WARN) &&
+      this->CurrentProcessingState != ProcessingLinkLibraries &&
      !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES"))
     {
     this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
@@ -263,11 +268,30 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
       ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
     if (this->CurrentProcessingState != ProcessingPublicInterface)
       {
+      if (this->Target->GetType() == cmTarget::STATIC_LIBRARY)
+        {
+        this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
+                  ("$<LINK_ONLY:" +
+                  this->Target->GetDebugGeneratorExpressions(lib, llt) +
+                  ">").c_str());
+        }
       // Not LINK_INTERFACE_LIBRARIES or LINK_PUBLIC, do not add to interface.
       return;
       }
     }
 
+  this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
+              this->Target->GetDebugGeneratorExpressions(lib, llt).c_str());
+
+  const cmPolicies::PolicyStatus policy22Status
+                      = this->Target->GetPolicyStatusCMP0022();
+
+  if (policy22Status != cmPolicies::OLD
+      && policy22Status != cmPolicies::WARN)
+    {
+    return;
+    }
+
   // Get the list of configurations considered to be DEBUG.
   std::vector<std::string> const& debugConfigs =
     this->Makefile->GetCMakeInstance()->GetDebugConfigs();

+ 15 - 8
Source/cmTargetLinkLibrariesCommand.h

@@ -92,7 +92,7 @@ public:
       "When this target is linked into another target then the libraries "
       "linked to this target will appear on the link line for the other "
       "target too.  "
-      "See the LINK_INTERFACE_LIBRARIES target property to override the "
+      "See the INTERFACE_LINK_LIBRARIES target property to override the "
       "set of transitive link dependencies for a target.  "
       "Calls to other signatures of this command may set the property "
       "making any libraries linked exclusively by this signature private."
@@ -112,14 +112,19 @@ public:
       "  target_link_libraries(<target> LINK_INTERFACE_LIBRARIES\n"
       "                        [[debug|optimized|general] <lib>] ...)\n"
       "The LINK_INTERFACE_LIBRARIES mode appends the libraries "
-      "to the LINK_INTERFACE_LIBRARIES and its per-configuration equivalent "
-      "target properties instead of using them for linking.  "
-      "Libraries specified as \"debug\" are appended to the "
+      "to the INTERFACE_LINK_LIBRARIES target property instead of using them "
+      "for linking.  If policy CMP0022 is not NEW, then this mode also "
+      "appends libraries to the LINK_INTERFACE_LIBRARIES and its "
+      "per-configuration equivalent.  "
+      "Libraries specified as \"debug\" are wrapped in a generator "
+      "expression to correspond to debug builds.  If policy CMP0022 is not "
+      "NEW, the libraries are also appended to the "
       "LINK_INTERFACE_LIBRARIES_DEBUG property (or to the properties "
       "corresponding to configurations listed in the DEBUG_CONFIGURATIONS "
       "global property if it is set).  "
       "Libraries specified as \"optimized\" are appended to the "
-      "LINK_INTERFACE_LIBRARIES property.  "
+      "INTERFACE_LINK_LIBRARIES property.  If policy CMP0022 is not NEW, "
+      "they are also appended to the LINK_INTERFACE_LIBRARIES property.  "
       "Libraries specified as \"general\" (or without any keyword) are "
       "treated as if specified for both \"debug\" and \"optimized\"."
       "\n"
@@ -131,9 +136,11 @@ public:
       "The LINK_PUBLIC and LINK_PRIVATE modes can be used to specify both "
       "the link dependencies and the link interface in one command.  "
       "Libraries and targets following LINK_PUBLIC are linked to, and are "
-      "made part of the LINK_INTERFACE_LIBRARIES. Libraries and targets "
-      "following LINK_PRIVATE are linked to, but are not made part of the "
-      "LINK_INTERFACE_LIBRARIES.  "
+      "made part of the INTERFACE_LINK_LIBRARIES.  If policy CMP0022 is not "
+      "NEW, they are also made part of the LINK_INTERFACE_LIBRARIES.  "
+      "Libraries and targets following LINK_PRIVATE are linked to, but are "
+      "not made part of the INTERFACE_LINK_LIBRARIES (or "
+      "LINK_INTERFACE_LIBRARIES)."
       "\n"
       "The library dependency graph is normally acyclic (a DAG), but in the "
       "case of mutually-dependent STATIC libraries CMake allows the graph "

+ 2 - 0
Tests/CMakeCommands/target_link_libraries/CMakeLists.txt

@@ -122,3 +122,5 @@ add_library(libConsumer empty.cpp)
 # evaluates to the empty string in non-Debug cases, ensure that that causes
 # no problems.
 target_link_libraries(libConsumer debug depA)
+
+add_subdirectory(cmp0022)

+ 18 - 0
Tests/CMakeCommands/target_link_libraries/cmp0022/CMakeLists.txt

@@ -0,0 +1,18 @@
+
+include(GenerateExportHeader)
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+cmake_policy(SET CMP0022 NEW)
+add_library(cmp0022lib SHARED cmp0022lib.cpp)
+generate_export_header(cmp0022lib)
+add_library(cmp0022ifacelib SHARED cmp0022ifacelib.cpp)
+generate_export_header(cmp0022ifacelib)
+target_link_libraries(cmp0022lib LINK_PUBLIC cmp0022ifacelib)
+
+assert_property(cmp0022lib LINK_INTERFACE_LIBRARIES "")
+assert_property(cmp0022ifacelib LINK_INTERFACE_LIBRARIES "")
+assert_property(cmp0022lib INTERFACE_LINK_LIBRARIES "cmp0022ifacelib")
+assert_property(cmp0022ifacelib INTERFACE_LINK_LIBRARIES "")
+
+add_executable(cmp0022exe cmp0022exe.cpp)
+target_link_libraries(cmp0022exe cmp0022lib)

+ 7 - 0
Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022exe.cpp

@@ -0,0 +1,7 @@
+
+#include "cmp0022lib.h"
+
+int main(void)
+{
+  return cmp0022().Value;
+}

+ 9 - 0
Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022ifacelib.cpp

@@ -0,0 +1,9 @@
+
+#include "cmp0022ifacelib.h"
+
+CMP0022Iface cmp0022iface()
+{
+  CMP0022Iface iface;
+  iface.Value = 0;
+  return iface;
+}

+ 9 - 0
Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022ifacelib.h

@@ -0,0 +1,9 @@
+
+#include "cmp0022ifacelib_export.h"
+
+struct CMP0022Iface
+{
+  int Value;
+};
+
+CMP0022Iface CMP0022IFACELIB_EXPORT cmp0022iface();

+ 7 - 0
Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022lib.cpp

@@ -0,0 +1,7 @@
+
+#include "cmp0022lib.h"
+
+CMP0022Iface cmp0022()
+{
+  return cmp0022iface();
+}

+ 6 - 0
Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022lib.h

@@ -0,0 +1,6 @@
+
+#include "cmp0022lib_export.h"
+
+#include "cmp0022ifacelib.h"
+
+CMP0022Iface CMP0022LIB_EXPORT cmp0022();

+ 10 - 0
Tests/CMakeLists.txt

@@ -2528,6 +2528,16 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
     --test-command IncludeDirectories)
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/IncludeDirectories")
 
+  add_test(InterfaceLinkLibraries ${CMAKE_CTEST_COMMAND}
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/InterfaceLinkLibraries"
+    "${CMake_BINARY_DIR}/Tests/InterfaceLinkLibraries"
+    --build-two-config
+    ${build_generator_args}
+    --build-project InterfaceLinkLibraries
+    --test-command InterfaceLinkLibraries)
+  list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/InterfaceLinkLibraries")
+
   if(CMAKE_USE_KWSTYLE AND KWSTYLE_EXECUTABLE)
     # The "make StyleCheck" command line as a test. If the test fails, look
     # for lines like "Error #0 (624) Line length exceed 88 (max=79)" in the

+ 29 - 0
Tests/ExportImport/Export/CMakeLists.txt

@@ -235,6 +235,33 @@ target_link_libraries(testSharedLibDepends LINK_PUBLIC renamed_on_export)
 target_link_libraries(testSharedLibDepends LINK_INTERFACE_LIBRARIES
   $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:$<TARGET_NAME:testSharedLibRequired>>)
 
+add_library(cmp0022OLD SHARED cmp0022_vs6_1.cpp)
+generate_export_header(cmp0022OLD BASE_NAME cmp0022)
+target_include_directories(cmp0022OLD PUBLIC
+  "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>"
+  "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/cmp0022>"
+)
+cmake_policy(SET CMP0022 NEW)
+add_library(cmp0022NEW SHARED cmp0022_vs6_1.cpp)
+target_include_directories(cmp0022NEW PUBLIC
+  "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>"
+  "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/cmp0022>"
+)
+cmake_policy(SET CMP0022 OLD)
+install(FILES
+  "${CMAKE_CURRENT_SOURCE_DIR}/cmp0022.h"
+  "${CMAKE_CURRENT_BINARY_DIR}/cmp0022_export.h"
+    DESTINATION include/cmp0022
+)
+
+set_property(TARGET testLib2 APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS USING_TESTLIB2)
+set_property(TARGET testLib3 APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS USING_TESTLIB3)
+
+set_property(TARGET cmp0022NEW APPEND PROPERTY INTERFACE_LINK_LIBRARIES testLib2)
+# set_property(TARGET cmp0022NEW APPEND PROPERTY LINK_INTERFACE_LIBRARIES testLibIncludeRequired2) # TODO: Test for error
+set_property(TARGET cmp0022OLD APPEND PROPERTY INTERFACE_LINK_LIBRARIES testLib2)
+set_property(TARGET cmp0022OLD APPEND PROPERTY LINK_INTERFACE_LIBRARIES testLib3)
+
 install(TARGETS testLibRequired
                 testLibIncludeRequired1
                 testLibIncludeRequired2
@@ -276,6 +303,7 @@ install(
   testExe2lib testLib4lib testLib4libdbg testLib4libopt
   testLib6
   testLibCycleA testLibCycleB
+  cmp0022NEW cmp0022OLD
   EXPORT exp
   RUNTIME DESTINATION bin
   LIBRARY DESTINATION lib NAMELINK_SKIP
@@ -319,6 +347,7 @@ add_subdirectory(sublib) # For CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE test.
 export(TARGETS testExe1 testLib1 testLib2 testLib3
   testExe2libImp testLib3Imp testLib3ImpDep subdirlib
   testSharedLibRequired testSharedLibDepends renamed_on_export
+  cmp0022NEW cmp0022OLD
   NAMESPACE bld_
   FILE ExportBuildTree.cmake
   )

+ 7 - 0
Tests/ExportImport/Export/cmp0022.cpp

@@ -0,0 +1,7 @@
+
+#include "cmp0022.h"
+
+int cmp0022()
+{
+  return 0;
+}

+ 4 - 0
Tests/ExportImport/Export/cmp0022.h

@@ -0,0 +1,4 @@
+
+#include "cmp0022_export.h"
+
+int CMP0022_EXPORT cmp0022();

+ 1 - 0
Tests/ExportImport/Export/cmp0022_vs6_1.cpp

@@ -0,0 +1 @@
+#include "cmp0022.cpp"

+ 1 - 0
Tests/ExportImport/Export/cmp0022_vs6_2.cpp

@@ -0,0 +1 @@
+#include "cmp0022.cpp"

+ 10 - 0
Tests/ExportImport/Import/A/CMakeLists.txt

@@ -68,6 +68,16 @@ target_link_libraries(imp_testExe1b
   bld_testLibCycleA
   )
 
+add_executable(cmp0022OLD_test cmp0022OLD_test_vs6_1.cpp)
+target_link_libraries(cmp0022OLD_test bld_cmp0022OLD)
+add_executable(cmp0022NEW_test cmp0022NEW_test_vs6_1.cpp)
+target_link_libraries(cmp0022NEW_test bld_cmp0022NEW)
+
+add_executable(cmp0022OLD_exp_test cmp0022OLD_test_vs6_2.cpp)
+target_link_libraries(cmp0022OLD_exp_test exp_cmp0022OLD)
+add_executable(cmp0022NEW_exp_test cmp0022NEW_test_vs6_2.cpp)
+target_link_libraries(cmp0022NEW_exp_test exp_cmp0022NEW)
+
 # Try building a plugin to an executable imported from the build tree.
 add_library(imp_mod1b MODULE imp_mod1.c)
 target_link_libraries(imp_mod1b bld_testExe2)

+ 12 - 0
Tests/ExportImport/Import/A/cmp0022NEW_test.cpp

@@ -0,0 +1,12 @@
+
+#ifndef USING_TESTLIB2
+#error Expected USING_TESTLIB2
+#endif
+#ifdef USING_TESTLIB3
+#error Unexpected USING_TESTLIB3
+#endif
+
+int main(void)
+{
+  return 0;
+}

+ 1 - 0
Tests/ExportImport/Import/A/cmp0022NEW_test_vs6_1.cpp

@@ -0,0 +1 @@
+#include "cmp0022NEW_test.cpp"

+ 1 - 0
Tests/ExportImport/Import/A/cmp0022NEW_test_vs6_2.cpp

@@ -0,0 +1 @@
+#include "cmp0022NEW_test.cpp"

+ 12 - 0
Tests/ExportImport/Import/A/cmp0022OLD_test.cpp

@@ -0,0 +1,12 @@
+
+#ifdef USING_TESTLIB2
+#error Unexpected USING_TESTLIB2
+#endif
+#ifndef USING_TESTLIB3
+#error Expected USING_TESTLIB3
+#endif
+
+int main(void)
+{
+  return 0;
+}

+ 1 - 0
Tests/ExportImport/Import/A/cmp0022OLD_test_vs6_1.cpp

@@ -0,0 +1 @@
+#include "cmp0022OLD_test.cpp"

+ 1 - 0
Tests/ExportImport/Import/A/cmp0022OLD_test_vs6_2.cpp

@@ -0,0 +1 @@
+#include "cmp0022OLD_test.cpp"

+ 49 - 0
Tests/InterfaceLinkLibraries/CMakeLists.txt

@@ -0,0 +1,49 @@
+cmake_minimum_required (VERSION 2.8)
+
+cmake_policy(SET CMP0022 NEW)
+
+project(InterfaceLinkLibraries)
+
+add_library(foo_shared SHARED foo_vs6_1.cpp)
+target_compile_definitions(foo_shared INTERFACE FOO_LIBRARY)
+add_library(bar_shared SHARED bar_vs6_1.cpp)
+target_compile_definitions(bar_shared INTERFACE BAR_LIBRARY)
+set_property(TARGET bar_shared APPEND PROPERTY INTERFACE_LINK_LIBRARIES foo_shared)
+
+add_executable(shared_test main_vs6_1.cpp)
+set_property(TARGET shared_test APPEND PROPERTY LINK_LIBRARIES bar_shared)
+
+add_library(foo_static STATIC foo_vs6_2.cpp)
+target_compile_definitions(foo_static INTERFACE FOO_LIBRARY)
+add_library(bar_static STATIC bar_vs6_2.cpp)
+target_compile_definitions(bar_static INTERFACE BAR_LIBRARY)
+set_property(TARGET bar_static APPEND PROPERTY INTERFACE_LINK_LIBRARIES foo_static)
+
+add_executable(static_test main_vs6_2.cpp)
+set_property(TARGET static_test APPEND PROPERTY LINK_LIBRARIES bar_static)
+
+add_library(foo_shared_private SHARED foo_vs6_3.cpp)
+target_compile_definitions(foo_shared_private INTERFACE FOO_LIBRARY)
+add_library(bang_shared_private SHARED bang_vs6_1.cpp)
+target_compile_definitions(bang_shared_private INTERFACE BANG_LIBRARY)
+add_library(bar_shared_private SHARED bar_vs6_3.cpp)
+target_compile_definitions(bar_shared_private INTERFACE BAR_LIBRARY)
+target_compile_definitions(bar_shared_private PRIVATE BAR_USE_BANG)
+set_property(TARGET bar_shared_private APPEND PROPERTY LINK_LIBRARIES bang_shared_private)
+set_property(TARGET bar_shared_private APPEND PROPERTY INTERFACE_LINK_LIBRARIES foo_shared_private)
+
+add_executable(shared_private_test main_vs6_3.cpp)
+set_property(TARGET shared_private_test APPEND PROPERTY LINK_LIBRARIES bar_shared_private)
+
+add_library(foo_static_private STATIC foo_vs6_4.cpp)
+target_compile_definitions(foo_static_private INTERFACE FOO_LIBRARY)
+add_library(bang_static_private STATIC bang_vs6_2.cpp)
+target_compile_definitions(bang_static_private INTERFACE BANG_LIBRARY)
+add_library(bar_static_private STATIC bar_vs6_4.cpp)
+target_compile_definitions(bar_static_private INTERFACE BAR_LIBRARY)
+target_compile_definitions(bar_static_private PRIVATE BAR_USE_BANG)
+set_property(TARGET bar_static_private APPEND PROPERTY LINK_LIBRARIES bang_static_private)
+set_property(TARGET bar_static_private APPEND PROPERTY INTERFACE_LINK_LIBRARIES $<LINK_ONLY:bang_static_private> foo_static_private)
+
+add_executable(InterfaceLinkLibraries main_vs6_4.cpp)
+set_property(TARGET InterfaceLinkLibraries APPEND PROPERTY LINK_LIBRARIES bar_static_private)

+ 15 - 0
Tests/InterfaceLinkLibraries/bang.cpp

@@ -0,0 +1,15 @@
+
+#ifdef FOO_LIBRARY
+#error Unexpected FOO_LIBRARY
+#endif
+
+#ifdef BAR_LIBRARY
+#error Unexpected BAR_LIBRARY
+#endif
+
+#include "bang.h"
+
+int bang()
+{
+  return 0;
+}

+ 4 - 0
Tests/InterfaceLinkLibraries/bang.h

@@ -0,0 +1,4 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int bang();

+ 1 - 0
Tests/InterfaceLinkLibraries/bang_vs6_1.cpp

@@ -0,0 +1 @@
+#include "bang.cpp"

+ 1 - 0
Tests/InterfaceLinkLibraries/bang_vs6_2.cpp

@@ -0,0 +1 @@
+#include "bang.cpp"

+ 26 - 0
Tests/InterfaceLinkLibraries/bar.cpp

@@ -0,0 +1,26 @@
+
+#ifdef FOO_LIBRARY
+#error Unexpected FOO_LIBRARY
+#endif
+
+#ifdef BAR_USE_BANG
+#  ifndef BANG_LIBRARY
+#    error Expected BANG_LIBRARY
+#  endif
+#  include "bang.h"
+#else
+#  ifdef BANG_LIBRARY
+#    error Unexpected BANG_LIBRARY
+#  endif
+#endif
+
+#include "bar.h"
+
+int bar()
+{
+#ifdef BAR_USE_BANG
+  return bang();
+#else
+  return 0;
+#endif
+}

+ 7 - 0
Tests/InterfaceLinkLibraries/bar.h

@@ -0,0 +1,7 @@
+
+#include "foo.h"
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int bar();

+ 1 - 0
Tests/InterfaceLinkLibraries/bar_vs6_1.cpp

@@ -0,0 +1 @@
+#include "bar.cpp"

+ 1 - 0
Tests/InterfaceLinkLibraries/bar_vs6_2.cpp

@@ -0,0 +1 @@
+#include "bar.cpp"

+ 1 - 0
Tests/InterfaceLinkLibraries/bar_vs6_3.cpp

@@ -0,0 +1 @@
+#include "bar.cpp"

+ 1 - 0
Tests/InterfaceLinkLibraries/bar_vs6_4.cpp

@@ -0,0 +1 @@
+#include "bar.cpp"

+ 15 - 0
Tests/InterfaceLinkLibraries/foo.cpp

@@ -0,0 +1,15 @@
+
+#ifdef BAR_LIBRARY
+#error Unexpected BAR_LIBRARY
+#endif
+
+#ifdef BANG_LIBRARY
+#error Unexpected BANG_LIBRARY
+#endif
+
+#include "foo.h"
+
+int foo()
+{
+  return 0;
+}

+ 4 - 0
Tests/InterfaceLinkLibraries/foo.h

@@ -0,0 +1,4 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int foo();

+ 1 - 0
Tests/InterfaceLinkLibraries/foo_vs6_1.cpp

@@ -0,0 +1 @@
+#include "foo.cpp"

+ 1 - 0
Tests/InterfaceLinkLibraries/foo_vs6_2.cpp

@@ -0,0 +1 @@
+#include "foo.cpp"

+ 1 - 0
Tests/InterfaceLinkLibraries/foo_vs6_3.cpp

@@ -0,0 +1 @@
+#include "foo.cpp"

+ 1 - 0
Tests/InterfaceLinkLibraries/foo_vs6_4.cpp

@@ -0,0 +1 @@
+#include "foo.cpp"

+ 19 - 0
Tests/InterfaceLinkLibraries/main.cpp

@@ -0,0 +1,19 @@
+
+#ifndef FOO_LIBRARY
+#error Expected FOO_LIBRARY
+#endif
+
+#ifndef BAR_LIBRARY
+#error Expected BAR_LIBRARY
+#endif
+
+#ifdef BANG_LIBRARY
+#error Unexpected BANG_LIBRARY
+#endif
+
+#include "bar.h"
+
+int main(void)
+{
+  return foo() + bar();
+}

+ 1 - 0
Tests/InterfaceLinkLibraries/main_vs6_1.cpp

@@ -0,0 +1 @@
+#include "main.cpp"

+ 1 - 0
Tests/InterfaceLinkLibraries/main_vs6_2.cpp

@@ -0,0 +1 @@
+#include "main.cpp"

+ 1 - 0
Tests/InterfaceLinkLibraries/main_vs6_3.cpp

@@ -0,0 +1 @@
+#include "main.cpp"

+ 1 - 0
Tests/InterfaceLinkLibraries/main_vs6_4.cpp

@@ -0,0 +1 @@
+#include "main.cpp"

+ 1 - 0
Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-link_libraries-stderr.txt

@@ -0,0 +1 @@
+^$

+ 9 - 0
Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-link_libraries.cmake

@@ -0,0 +1,9 @@
+
+enable_language(CXX)
+
+add_subdirectory(dep1)
+add_subdirectory(dep2)
+add_subdirectory(dep3)
+
+add_library(somelib empty.cpp)
+target_link_libraries(somelib dep3)

+ 1 - 0
Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-stderr.txt

@@ -0,0 +1 @@
+^$

+ 8 - 0
Tests/RunCMake/CMP0022/CMP0022-NOWARN-static.cmake

@@ -0,0 +1,8 @@
+
+project(CMP0022-NOWARN-static)
+
+add_library(foo STATIC empty_vs6_1.cpp)
+add_library(bar STATIC empty_vs6_2.cpp)
+add_library(bat STATIC empty_vs6_3.cpp)
+target_link_libraries(foo bar)
+target_link_libraries(bar bat)

+ 1 - 0
Tests/RunCMake/CMP0022/CMP0022-WARN-static-result.txt

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

+ 10 - 0
Tests/RunCMake/CMP0022/CMP0022-WARN-static-stderr.txt

@@ -0,0 +1,10 @@
+CMake Warning \(dev\) in CMakeLists.txt:
+  Policy CMP0022 is not set: INTERFACE_LINK_LIBRARIES defines the link
+  interface.  Run "cmake --help-policy CMP0022" for policy details.  Use the
+  cmake_policy command to set the policy and suppress this warning.
+
+  Static library target "bar" has a INTERFACE_LINK_LIBRARIES property.  This
+  should be preferred as the source of the link interface for this library.
+  Ignoring the property and using the link implementation as the link
+  interface instead.
+This warning is for project developers.  Use -Wno-dev to suppress it.$

+ 11 - 0
Tests/RunCMake/CMP0022/CMP0022-WARN-static.cmake

@@ -0,0 +1,11 @@
+
+project(CMP0022-WARN)
+
+add_library(foo STATIC empty_vs6_1.cpp)
+add_library(bar STATIC empty_vs6_2.cpp)
+add_library(bat STATIC empty_vs6_3.cpp)
+set_property(TARGET bar PROPERTY INTERFACE_LINK_LIBRARIES foo)
+set_property(TARGET bar PROPERTY LINK_LIBRARIES bat)
+
+add_library(user empty.cpp)
+target_link_libraries(user bar)

+ 8 - 0
Tests/RunCMake/CMP0022/CMP0022-WARN-stderr.txt

@@ -0,0 +1,8 @@
+CMake Warning \(dev\) in CMakeLists.txt:
+  Policy CMP0022 is not set: INTERFACE_LINK_LIBRARIES defines the link
+  interface.  Run "cmake --help-policy CMP0022" for policy details.  Use the
+  cmake_policy command to set the policy and suppress this warning.
+
+  Target "bar" has a INTERFACE_LINK_LIBRARIES property which differs from its
+  LINK_INTERFACE_LIBRARIES properties.
+This warning is for project developers.  Use -Wno-dev to suppress it.$

+ 1 - 0
Tests/RunCMake/CMP0022/CMP0022-WARN-tll-result.txt

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

+ 8 - 0
Tests/RunCMake/CMP0022/CMP0022-WARN-tll-stderr.txt

@@ -0,0 +1,8 @@
+CMake Warning \(dev\) in CMakeLists.txt:
+  Policy CMP0022 is not set: INTERFACE_LINK_LIBRARIES defines the link
+  interface.  Run "cmake --help-policy CMP0022" for policy details.  Use the
+  cmake_policy command to set the policy and suppress this warning.
+
+  Target "bar" has a INTERFACE_LINK_LIBRARIES property which differs from its
+  LINK_INTERFACE_LIBRARIES properties.
+This warning is for project developers.  Use -Wno-dev to suppress it.

+ 11 - 0
Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake

@@ -0,0 +1,11 @@
+
+project(CMP0022-WARN-tll)
+
+add_library(foo SHARED empty_vs6_1.cpp)
+add_library(bar SHARED empty_vs6_2.cpp)
+add_library(bat SHARED empty_vs6_3.cpp)
+target_link_libraries(bar LINK_PUBLIC foo)
+set_property(TARGET bar PROPERTY LINK_INTERFACE_LIBRARIES bat)
+
+add_library(user SHARED empty.cpp)
+target_link_libraries(user bar)

+ 11 - 0
Tests/RunCMake/CMP0022/CMP0022-WARN.cmake

@@ -0,0 +1,11 @@
+
+project(CMP0022-WARN)
+
+add_library(foo SHARED empty_vs6_1.cpp)
+add_library(bar SHARED empty_vs6_2.cpp)
+add_library(bat SHARED empty_vs6_3.cpp)
+set_property(TARGET bar PROPERTY INTERFACE_LINK_LIBRARIES foo)
+set_property(TARGET bar PROPERTY LINK_INTERFACE_LIBRARIES bat)
+
+add_library(user empty.cpp)
+target_link_libraries(user bar)

+ 1 - 0
Tests/RunCMake/CMP0022/CMP0022-export-result.txt

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

+ 4 - 0
Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt

@@ -0,0 +1,4 @@
+CMake Error at CMP0022-export.cmake:11 \(export\):
+  Target "cmp0022NEW" has policy CMP0022 enabled, but also has old-style
+  INTERFACE_LINK_LIBRARIES properties populated, but it was exported without
+  the EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties

+ 11 - 0
Tests/RunCMake/CMP0022/CMP0022-export.cmake

@@ -0,0 +1,11 @@
+
+project(cmp0022NEW)
+
+cmake_policy(SET CMP0022 NEW)
+
+add_library(cmp0022NEW SHARED empty_vs6_1.cpp)
+add_library(testLib SHARED empty_vs6_2.cpp)
+
+set_property(TARGET cmp0022NEW APPEND PROPERTY LINK_INTERFACE_LIBRARIES testLib)
+
+export(TARGETS cmp0022NEW testLib FILE "${CMAKE_CURRENT_BINARY_DIR}/cmp0022NEW.cmake")

+ 1 - 0
Tests/RunCMake/CMP0022/CMP0022-install-export-result.txt

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

+ 4 - 0
Tests/RunCMake/CMP0022/CMP0022-install-export-stderr.txt

@@ -0,0 +1,4 @@
+CMake Error in CMakeLists.txt:
+  Target "cmp0022NEW" has policy CMP0022 enabled, but also has old-style
+  INTERFACE_LINK_LIBRARIES properties populated, but it was exported without
+  the EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties

+ 12 - 0
Tests/RunCMake/CMP0022/CMP0022-install-export.cmake

@@ -0,0 +1,12 @@
+
+project(cmp0022NEW)
+
+cmake_policy(SET CMP0022 NEW)
+
+add_library(cmp0022NEW SHARED empty_vs6_1.cpp)
+add_library(testLib SHARED empty_vs6_2.cpp)
+
+set_property(TARGET cmp0022NEW APPEND PROPERTY LINK_INTERFACE_LIBRARIES testLib)
+
+install(TARGETS cmp0022NEW testLib EXPORT exp DESTINATION lib)
+install(EXPORT exp FILE expTargets.cmake DESTINATION lib/cmake/exp)

+ 3 - 0
Tests/RunCMake/CMP0022/CMakeLists.txt

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.11)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)

+ 9 - 0
Tests/RunCMake/CMP0022/RunCMakeTest.cmake

@@ -0,0 +1,9 @@
+include(RunCMake)
+
+run_cmake(CMP0022-WARN)
+run_cmake(CMP0022-WARN-tll)
+run_cmake(CMP0022-WARN-static)
+run_cmake(CMP0022-NOWARN-static)
+run_cmake(CMP0022-NOWARN-static-link_libraries)
+run_cmake(CMP0022-export)
+run_cmake(CMP0022-install-export)

+ 2 - 0
Tests/RunCMake/CMP0022/dep1/CMakeLists.txt

@@ -0,0 +1,2 @@
+
+add_library(dep1 ../empty_vs6_1.cpp)

+ 2 - 0
Tests/RunCMake/CMP0022/dep2/CMakeLists.txt

@@ -0,0 +1,2 @@
+
+add_library(dep2 ../empty_vs6_2.cpp)

+ 5 - 0
Tests/RunCMake/CMP0022/dep3/CMakeLists.txt

@@ -0,0 +1,5 @@
+
+link_libraries(dep1)
+
+add_library(dep3 ../empty_vs6_3.cpp)
+target_link_libraries(dep3 dep2)

+ 7 - 0
Tests/RunCMake/CMP0022/empty.cpp

@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int empty()
+{
+  return 0;
+}

+ 1 - 0
Tests/RunCMake/CMP0022/empty_vs6_1.cpp

@@ -0,0 +1 @@
+#include "empty.cpp"

+ 1 - 0
Tests/RunCMake/CMP0022/empty_vs6_2.cpp

@@ -0,0 +1 @@
+#include "empty.cpp"

+ 1 - 0
Tests/RunCMake/CMP0022/empty_vs6_3.cpp

@@ -0,0 +1 @@
+#include "empty.cpp"

+ 1 - 0
Tests/RunCMake/CMakeLists.txt

@@ -52,6 +52,7 @@ if(XCODE_VERSION AND "${XCODE_VERSION}" VERSION_LESS 3)
 endif()
 
 add_RunCMake_test(CMP0019)
+add_RunCMake_test(CMP0022)
 add_RunCMake_test(CTest)
 if(UNIX AND "${CMAKE_TEST_GENERATOR}" MATCHES "Unix Makefiles")
   add_RunCMake_test(CompilerChange)