Browse Source

Merge topic 'tll-new-signatures'

b655865 target_link_libraries: Add PUBLIC/PRIVATE/INTERFACE keyword signature
Brad King 12 years ago
parent
commit
2f8dace125
30 changed files with 407 additions and 19 deletions
  1. 26 0
      Source/cmPolicies.cxx
  2. 1 0
      Source/cmPolicies.h
  3. 51 0
      Source/cmTarget.cxx
  4. 8 0
      Source/cmTarget.h
  5. 124 13
      Source/cmTargetLinkLibrariesCommand.cxx
  6. 22 6
      Source/cmTargetLinkLibrariesCommand.h
  7. 6 0
      Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
  8. 19 0
      Tests/CMakeCommands/target_link_libraries/newsignature1.cpp
  9. 1 0
      Tests/RunCMake/CMakeLists.txt
  10. 1 0
      Tests/RunCMake/target_link_libraries/CMP0023-NEW-2-result.txt
  11. 16 0
      Tests/RunCMake/target_link_libraries/CMP0023-NEW-2-stderr.txt
  12. 11 0
      Tests/RunCMake/target_link_libraries/CMP0023-NEW-2.cmake
  13. 1 0
      Tests/RunCMake/target_link_libraries/CMP0023-NEW-result.txt
  14. 16 0
      Tests/RunCMake/target_link_libraries/CMP0023-NEW-stderr.txt
  15. 11 0
      Tests/RunCMake/target_link_libraries/CMP0023-NEW.cmake
  16. 16 0
      Tests/RunCMake/target_link_libraries/CMP0023-WARN-2-stderr.txt
  17. 9 0
      Tests/RunCMake/target_link_libraries/CMP0023-WARN-2.cmake
  18. 16 0
      Tests/RunCMake/target_link_libraries/CMP0023-WARN-stderr.txt
  19. 9 0
      Tests/RunCMake/target_link_libraries/CMP0023-WARN.cmake
  20. 3 0
      Tests/RunCMake/target_link_libraries/CMakeLists.txt
  21. 1 0
      Tests/RunCMake/target_link_libraries/MixedSignature-result.txt
  22. 5 0
      Tests/RunCMake/target_link_libraries/MixedSignature-stderr.txt
  23. 6 0
      Tests/RunCMake/target_link_libraries/MixedSignature.cmake
  24. 8 0
      Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake
  25. 1 0
      Tests/RunCMake/target_link_libraries/Separate-PRIVATE-LINK_PRIVATE-uses-result.txt
  26. 9 0
      Tests/RunCMake/target_link_libraries/Separate-PRIVATE-LINK_PRIVATE-uses.cmake
  27. 7 0
      Tests/RunCMake/target_link_libraries/empty.cpp
  28. 1 0
      Tests/RunCMake/target_link_libraries/empty_vs6_1.cpp
  29. 1 0
      Tests/RunCMake/target_link_libraries/empty_vs6_2.cpp
  30. 1 0
      Tests/RunCMake/target_link_libraries/empty_vs6_3.cpp

+ 26 - 0
Source/cmPolicies.cxx

@@ -575,6 +575,32 @@ cmPolicies::cmPolicies()
     "property for in-build targets, and ignore the old properties matching "
     "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?.",
     2,8,11,20130516, cmPolicies::WARN);
+
+  this->DefinePolicy(
+    CMP0023, "CMP0023",
+    "Plain and keyword target_link_libraries signatures cannot be mixed.",
+    "CMake 2.8.12 introduced the target_link_libraries signature using "
+    "the PUBLIC, PRIVATE, and INTERFACE keywords to generalize the "
+    "LINK_PUBLIC and LINK_PRIVATE keywords introduced in CMake 2.8.7.  "
+    "Use of signatures with any of these keywords sets the link interface "
+    "of a target explicitly, even if empty.  "
+    "This produces confusing behavior when used in combination with the "
+    "historical behavior of the plain target_link_libraries signature.  "
+    "For example, consider the code:\n"
+    " target_link_libraries(mylib A)\n"
+    " target_link_libraries(mylib PRIVATE B)\n"
+    "After the first line the link interface has not been set explicitly "
+    "so CMake would use the link implementation, A, as the link interface.  "
+    "However, the second line sets the link interface to empty.  "
+    "In order to avoid this subtle behavior CMake now prefers to disallow "
+    "mixing the plain and keyword signatures of target_link_libraries for "
+    "a single target."
+    "\n"
+    "The OLD behavior for this policy is to allow keyword and plain "
+    "target_link_libraries signatures to be mixed.  "
+    "The NEW behavior for this policy is to not to allow mixing of the "
+    "keyword and plain signatures.",
+    2,8,11,20130724, cmPolicies::WARN);
 }
 
 cmPolicies::~cmPolicies()

+ 1 - 0
Source/cmPolicies.h

@@ -73,6 +73,7 @@ public:
     CMP0021, ///< Fatal error on relative paths in INCLUDE_DIRECTORIES
     /// target property
     CMP0022, ///< INTERFACE_LINK_LIBRARIES defines the link interface
+    CMP0023, ///< Disallow mixing keyword and plain tll signatures
 
     /** \brief Always the last entry.
      *

+ 51 - 0
Source/cmTarget.cxx

@@ -2493,6 +2493,57 @@ static std::string targetNameGenex(const char *lib)
   return std::string("$<TARGET_NAME:") + lib + ">";
 }
 
+//----------------------------------------------------------------------------
+bool cmTarget::PushTLLCommandTrace(TLLSignature signature)
+{
+  bool ret = true;
+  if (!this->TLLCommands.empty())
+    {
+    if (this->TLLCommands.back().first != signature)
+      {
+      ret = false;
+      }
+    }
+  cmListFileBacktrace lfbt;
+  this->Makefile->GetBacktrace(lfbt);
+  this->TLLCommands.push_back(std::make_pair(signature, lfbt));
+  return ret;
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::GetTllSignatureTraces(cmOStringStream &s,
+                                     TLLSignature sig) const
+{
+  std::vector<cmListFileBacktrace> sigs;
+  typedef std::vector<std::pair<TLLSignature, cmListFileBacktrace> > Container;
+  for(Container::const_iterator it = this->TLLCommands.begin();
+      it != this->TLLCommands.end(); ++it)
+    {
+    if (it->first == sig)
+      {
+      sigs.push_back(it->second);
+      }
+    }
+  if (!sigs.empty())
+    {
+    const char *sigString
+                        = (sig == cmTarget::KeywordTLLSignature ? "keyword"
+                                                                : "plain");
+    s << "The uses of the " << sigString << " signature are here:\n";
+    for(std::vector<cmListFileBacktrace>::const_iterator it = sigs.begin();
+        it != sigs.end(); ++it)
+      {
+      cmListFileBacktrace::const_iterator i = it->begin();
+      if(i != it->end())
+        {
+        cmListFileContext const& lfc = *i;
+        s << " * " << (lfc.Line? "": " in ") << lfc << std::endl;
+        ++i;
+        }
+      }
+    }
+}
+
 //----------------------------------------------------------------------------
 void cmTarget::AddLinkLibrary(cmMakefile& mf,
                               const char *target, const char* lib,

+ 8 - 0
Source/cmTarget.h

@@ -190,6 +190,12 @@ public:
   void AddLinkLibrary(cmMakefile& mf,
                       const char *target, const char* lib,
                       LinkLibraryType llt);
+  enum TLLSignature {
+    KeywordTLLSignature,
+    PlainTLLSignature
+  };
+  bool PushTLLCommandTrace(TLLSignature signature);
+  void GetTllSignatureTraces(cmOStringStream &s, TLLSignature sig) const;
 
   void MergeLinkLibraries( cmMakefile& mf, const char* selfname,
                            const LinkLibraryVectorType& libs );
@@ -548,6 +554,8 @@ private:
   // directories.
   std::set<cmStdString> SystemIncludeDirectories;
 
+  std::vector<std::pair<TLLSignature, cmListFileBacktrace> > TLLCommands;
+
   /**
    * A list of direct dependencies. Use in conjunction with DependencyMap.
    */

+ 124 - 13
Source/cmTargetLinkLibrariesCommand.cxx

@@ -116,7 +116,7 @@ bool cmTargetLinkLibrariesCommand
     {
     if(args[i] == "LINK_INTERFACE_LIBRARIES")
       {
-      this->CurrentProcessingState = ProcessingLinkInterface;
+      this->CurrentProcessingState = ProcessingPlainLinkInterface;
       if(i != 1)
         {
         this->Makefile->IssueMessage(
@@ -127,9 +127,26 @@ bool cmTargetLinkLibrariesCommand
         return true;
         }
       }
+    else if(args[i] == "INTERFACE")
+      {
+      if(i != 1
+          && this->CurrentProcessingState != ProcessingKeywordPrivateInterface
+          && this->CurrentProcessingState != ProcessingKeywordPublicInterface
+          && this->CurrentProcessingState != ProcessingKeywordLinkInterface)
+        {
+        this->Makefile->IssueMessage(
+          cmake::FATAL_ERROR,
+          "The INTERFACE option must appear as the second "
+          "argument, just after the target name."
+          );
+        return true;
+        }
+      this->CurrentProcessingState = ProcessingKeywordLinkInterface;
+      }
     else if(args[i] == "LINK_PUBLIC")
       {
-      if(i != 1 && this->CurrentProcessingState != ProcessingPrivateInterface)
+      if(i != 1
+          && this->CurrentProcessingState != ProcessingPlainPrivateInterface)
         {
         this->Makefile->IssueMessage(
           cmake::FATAL_ERROR,
@@ -138,11 +155,28 @@ bool cmTargetLinkLibrariesCommand
           );
         return true;
         }
-      this->CurrentProcessingState = ProcessingPublicInterface;
+      this->CurrentProcessingState = ProcessingPlainPublicInterface;
+      }
+    else if(args[i] == "PUBLIC")
+      {
+      if(i != 1
+          && this->CurrentProcessingState != ProcessingKeywordPrivateInterface
+          && this->CurrentProcessingState != ProcessingKeywordPublicInterface
+          && this->CurrentProcessingState != ProcessingKeywordLinkInterface)
+        {
+        this->Makefile->IssueMessage(
+          cmake::FATAL_ERROR,
+          "The PUBLIC or PRIVATE option must appear as the second "
+          "argument, just after the target name."
+          );
+        return true;
+        }
+      this->CurrentProcessingState = ProcessingKeywordPublicInterface;
       }
     else if(args[i] == "LINK_PRIVATE")
       {
-      if(i != 1 && this->CurrentProcessingState != ProcessingPublicInterface)
+      if(i != 1
+          && this->CurrentProcessingState != ProcessingPlainPublicInterface)
         {
         this->Makefile->IssueMessage(
           cmake::FATAL_ERROR,
@@ -151,7 +185,23 @@ bool cmTargetLinkLibrariesCommand
           );
         return true;
         }
-      this->CurrentProcessingState = ProcessingPrivateInterface;
+      this->CurrentProcessingState = ProcessingPlainPrivateInterface;
+      }
+    else if(args[i] == "PRIVATE")
+      {
+      if(i != 1
+          && this->CurrentProcessingState != ProcessingKeywordPrivateInterface
+          && this->CurrentProcessingState != ProcessingKeywordPublicInterface
+          && this->CurrentProcessingState != ProcessingKeywordLinkInterface)
+        {
+        this->Makefile->IssueMessage(
+          cmake::FATAL_ERROR,
+          "The PUBLIC or PRIVATE option must appear as the second "
+          "argument, just after the target name."
+          );
+        return true;
+        }
+      this->CurrentProcessingState = ProcessingKeywordPrivateInterface;
       }
     else if(args[i] == "debug")
       {
@@ -184,7 +234,10 @@ bool cmTargetLinkLibrariesCommand
       {
       // The link type was specified by the previous argument.
       haveLLT = false;
-      this->HandleLibrary(args[i].c_str(), llt);
+      if (!this->HandleLibrary(args[i].c_str(), llt))
+        {
+        return false;
+        }
       }
     else
       {
@@ -210,7 +263,10 @@ bool cmTargetLinkLibrariesCommand
           llt = cmTarget::OPTIMIZED;
           }
         }
-      this->HandleLibrary(args[i].c_str(), llt);
+      if (!this->HandleLibrary(args[i].c_str(), llt))
+        {
+        return false;
+        }
       }
     }
 
@@ -257,16 +313,69 @@ cmTargetLinkLibrariesCommand
 }
 
 //----------------------------------------------------------------------------
-void
+bool
 cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
                                             cmTarget::LinkLibraryType llt)
 {
+  cmTarget::TLLSignature sig =
+        (this->CurrentProcessingState == ProcessingPlainPrivateInterface
+      || this->CurrentProcessingState == ProcessingPlainPublicInterface
+      || this->CurrentProcessingState == ProcessingKeywordPrivateInterface
+      || this->CurrentProcessingState == ProcessingKeywordPublicInterface
+      || this->CurrentProcessingState == ProcessingKeywordLinkInterface)
+        ? cmTarget::KeywordTLLSignature : cmTarget::PlainTLLSignature;
+  if (!this->Target->PushTLLCommandTrace(sig))
+    {
+    const char *modal = 0;
+    cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+    switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0023))
+      {
+      case cmPolicies::WARN:
+        modal = "should";
+      case cmPolicies::OLD:
+        break;
+      case cmPolicies::REQUIRED_ALWAYS:
+      case cmPolicies::REQUIRED_IF_USED:
+      case cmPolicies::NEW:
+        modal = "must";
+        messageType = cmake::FATAL_ERROR;
+      }
+
+      if(modal)
+        {
+        cmOStringStream e;
+        // If the sig is a keyword form and there is a conflict, the existing
+        // form must be the plain form.
+        const char *existingSig
+                    = (sig == cmTarget::KeywordTLLSignature ? "plain"
+                                                            : "keyword");
+        e << this->Makefile->GetPolicies()
+                              ->GetPolicyWarning(cmPolicies::CMP0023) << "\n"
+            "The " << existingSig << " signature for target_link_libraries "
+            "has already been used with the target \""
+          << this->Target->GetName() << "\".  All uses of "
+             "target_link_libraries with a target " << modal << " be either "
+             "all-keyword or all-plain.\n";
+        this->Target->GetTllSignatureTraces(e,
+                                          sig == cmTarget::KeywordTLLSignature
+                                            ? cmTarget::PlainTLLSignature
+                                            : cmTarget::KeywordTLLSignature);
+        this->Makefile->IssueMessage(messageType, e.str().c_str());
+        if(messageType == cmake::FATAL_ERROR)
+          {
+          return false;
+          }
+        }
+    }
+
   // Handle normal case first.
-  if(this->CurrentProcessingState != ProcessingLinkInterface)
+  if(this->CurrentProcessingState != ProcessingKeywordLinkInterface
+      && this->CurrentProcessingState != ProcessingPlainLinkInterface)
     {
     this->Makefile
       ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
-    if (this->CurrentProcessingState != ProcessingPublicInterface)
+    if (this->CurrentProcessingState != ProcessingKeywordPublicInterface
+        && this->CurrentProcessingState != ProcessingPlainPublicInterface)
       {
       if (this->Target->GetType() == cmTarget::STATIC_LIBRARY)
         {
@@ -275,8 +384,9 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
                   this->Target->GetDebugGeneratorExpressions(lib, llt) +
                   ">").c_str());
         }
-      // Not LINK_INTERFACE_LIBRARIES or LINK_PUBLIC, do not add to interface.
-      return;
+      // Not a 'public' or 'interface' library. Do not add to interface
+      // property.
+      return true;
       }
     }
 
@@ -289,7 +399,7 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
   if (policy22Status != cmPolicies::OLD
       && policy22Status != cmPolicies::WARN)
     {
-    return;
+    return true;
     }
 
   // Get the list of configurations considered to be DEBUG.
@@ -327,4 +437,5 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
         }
       }
     }
+  return true;
 }

+ 22 - 6
Source/cmTargetLinkLibrariesCommand.h

@@ -113,6 +113,16 @@ public:
       "directory of the framework will also be processed as a \"usage "
       "requirement\".  This has the same effect as passing the framework "
       "directory as an include directory."
+      "  target_link_libraries(<target>\n"
+      "                      <PRIVATE|PUBLIC|INTERFACE> <lib> ...\n"
+      "                      [<PRIVATE|PUBLIC|INTERFACE> <lib> ... ] ...])\n"
+      "The PUBLIC, PRIVATE and INTERFACE keywords can be used to specify "
+      "both the link dependencies and the link interface in one command.  "
+      "Libraries and targets following PUBLIC are linked to, and are "
+      "made part of the link interface.  Libraries and targets "
+      "following PRIVATE are linked to, but are not made part of the "
+      "link interface.  Libraries following INTERFACE are appended "
+      "to the link interface and are not used for linking <target>."
       "\n"
       "  target_link_libraries(<target> LINK_INTERFACE_LIBRARIES\n"
       "                        [[debug|optimized|general] <lib>] ...)\n"
@@ -120,7 +130,8 @@ public:
       "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.  "
+      "per-configuration equivalent.  This signature "
+      "is for compatibility only. Prefer the INTERFACE mode instead.  "
       "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 "
@@ -139,7 +150,9 @@ public:
       "                        [<LINK_PRIVATE|LINK_PUBLIC>\n"
       "                          [[debug|optimized|general] <lib>] ...])\n"
       "The LINK_PUBLIC and LINK_PRIVATE modes can be used to specify both "
-      "the link dependencies and the link interface in one command.  "
+      "the link dependencies and the link interface in one command.  This "
+      "signature is for compatibility only. Prefer the PUBLIC or PRIVATE "
+      "keywords instead.  "
       "Libraries and targets following LINK_PUBLIC are linked to, and are "
       "made part of the INTERFACE_LINK_LIBRARIES.  If policy CMP0022 is not "
       "NEW, they are also made part of the LINK_INTERFACE_LIBRARIES.  "
@@ -185,14 +198,17 @@ private:
   cmTarget* Target;
   enum ProcessingState {
     ProcessingLinkLibraries,
-    ProcessingLinkInterface,
-    ProcessingPublicInterface,
-    ProcessingPrivateInterface
+    ProcessingPlainLinkInterface,
+    ProcessingKeywordLinkInterface,
+    ProcessingPlainPublicInterface,
+    ProcessingKeywordPublicInterface,
+    ProcessingPlainPrivateInterface,
+    ProcessingKeywordPrivateInterface
   };
 
   ProcessingState CurrentProcessingState;
 
-  void HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt);
+  bool HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt);
 };
 
 

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

@@ -124,3 +124,9 @@ add_library(libConsumer empty.cpp)
 target_link_libraries(libConsumer debug depA)
 
 add_subdirectory(cmp0022)
+
+add_executable(newsignature1 newsignature1.cpp)
+target_link_libraries(newsignature1 PRIVATE depC INTERFACE depD PUBLIC depB PRIVATE subdirlib INTERFACE INTERFACE PUBLIC)
+
+assert_property(newsignature1 INTERFACE_LINK_LIBRARIES "depD;depB")
+assert_property(newsignature1 LINK_LIBRARIES "depC;depB;subdirlib")

+ 19 - 0
Tests/CMakeCommands/target_link_libraries/newsignature1.cpp

@@ -0,0 +1,19 @@
+
+#include "depB.h"
+#include "depC.h"
+#include "depIfaceOnly.h"
+
+#include "subdirlib.h"
+
+int main(int, char **)
+{
+  DepA a;
+  DepB b;
+  DepC c;
+
+  DepIfaceOnly iface_only;
+
+  SubDirLibObject sd;
+
+  return a.foo() + b.foo() + c.foo() + iface_only.foo() + sd.foo();
+}

+ 1 - 0
Tests/RunCMake/CMakeLists.txt

@@ -115,3 +115,4 @@ if("${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [^6]")
 endif()
 
 add_RunCMake_test(File_Generate)
+add_RunCMake_test(target_link_libraries)

+ 1 - 0
Tests/RunCMake/target_link_libraries/CMP0023-NEW-2-result.txt

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

+ 16 - 0
Tests/RunCMake/target_link_libraries/CMP0023-NEW-2-stderr.txt

@@ -0,0 +1,16 @@
+CMake Error at CMP0023-NEW-2.cmake:11 \(target_link_libraries\):
+  Policy CMP0023 is not set: Plain and keyword target_link_libraries
+  signatures cannot be mixed.  Run "cmake --help-policy CMP0023" for policy
+  details.  Use the cmake_policy command to set the policy and suppress this
+  warning.
+
+  The plain signature for target_link_libraries has already been used with
+  the target "foo".  All uses of target_link_libraries with a target must be
+  either all-keyword or all-plain.
+
+  The uses of the plain signature are here:
+
+   \* CMP0023-NEW-2.cmake:10 \(target_link_libraries\)
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 11 - 0
Tests/RunCMake/target_link_libraries/CMP0023-NEW-2.cmake

@@ -0,0 +1,11 @@
+
+project(CMP0022-WARN)
+
+cmake_policy(SET CMP0023 NEW)
+
+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(foo bar)
+target_link_libraries(foo LINK_PRIVATE bat)

+ 1 - 0
Tests/RunCMake/target_link_libraries/CMP0023-NEW-result.txt

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

+ 16 - 0
Tests/RunCMake/target_link_libraries/CMP0023-NEW-stderr.txt

@@ -0,0 +1,16 @@
+CMake Error at CMP0023-NEW.cmake:11 \(target_link_libraries\):
+  Policy CMP0023 is not set: Plain and keyword target_link_libraries
+  signatures cannot be mixed.  Run "cmake --help-policy CMP0023" for policy
+  details.  Use the cmake_policy command to set the policy and suppress this
+  warning.
+
+  The plain signature for target_link_libraries has already been used with
+  the target "foo".  All uses of target_link_libraries with a target must be
+  either all-keyword or all-plain.
+
+  The uses of the plain signature are here:
+
+   \* CMP0023-NEW.cmake:10 \(target_link_libraries\)
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 11 - 0
Tests/RunCMake/target_link_libraries/CMP0023-NEW.cmake

@@ -0,0 +1,11 @@
+
+project(CMP0022-WARN)
+
+cmake_policy(SET CMP0023 NEW)
+
+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(foo bar)
+target_link_libraries(foo PRIVATE bat)

+ 16 - 0
Tests/RunCMake/target_link_libraries/CMP0023-WARN-2-stderr.txt

@@ -0,0 +1,16 @@
+CMake Warning \(dev\) at CMP0023-WARN-2.cmake:9 \(target_link_libraries\):
+  Policy CMP0023 is not set: Plain and keyword target_link_libraries
+  signatures cannot be mixed.  Run "cmake --help-policy CMP0023" for policy
+  details.  Use the cmake_policy command to set the policy and suppress this
+  warning.
+
+  The plain signature for target_link_libraries has already been used with
+  the target "foo".  All uses of target_link_libraries with a target should
+  be either all-keyword or all-plain.
+
+  The uses of the plain signature are here:
+
+   \* CMP0023-WARN-2.cmake:8 \(target_link_libraries\)
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 9 - 0
Tests/RunCMake/target_link_libraries/CMP0023-WARN-2.cmake

@@ -0,0 +1,9 @@
+
+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)
+
+target_link_libraries(foo bar)
+target_link_libraries(foo LINK_PRIVATE bat)

+ 16 - 0
Tests/RunCMake/target_link_libraries/CMP0023-WARN-stderr.txt

@@ -0,0 +1,16 @@
+CMake Warning \(dev\) at CMP0023-WARN.cmake:9 \(target_link_libraries\):
+  Policy CMP0023 is not set: Plain and keyword target_link_libraries
+  signatures cannot be mixed.  Run "cmake --help-policy CMP0023" for policy
+  details.  Use the cmake_policy command to set the policy and suppress this
+  warning.
+
+  The plain signature for target_link_libraries has already been used with
+  the target "foo".  All uses of target_link_libraries with a target should
+  be either all-keyword or all-plain.
+
+  The uses of the plain signature are here:
+
+   \* CMP0023-WARN.cmake:8 \(target_link_libraries\)
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 9 - 0
Tests/RunCMake/target_link_libraries/CMP0023-WARN.cmake

@@ -0,0 +1,9 @@
+
+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)
+
+target_link_libraries(foo bar)
+target_link_libraries(foo PRIVATE bat)

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

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

+ 1 - 0
Tests/RunCMake/target_link_libraries/MixedSignature-result.txt

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

+ 5 - 0
Tests/RunCMake/target_link_libraries/MixedSignature-stderr.txt

@@ -0,0 +1,5 @@
+CMake Error at MixedSignature.cmake:6 \(target_link_libraries\):
+  The PUBLIC or PRIVATE option must appear as the second argument, just after
+  the target name.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 6 - 0
Tests/RunCMake/target_link_libraries/MixedSignature.cmake

@@ -0,0 +1,6 @@
+
+add_library(foo empty_vs6_1.cpp)
+add_library(bar empty_vs6_2.cpp)
+add_library(bat empty_vs6_3.cpp)
+
+target_link_libraries(foo LINK_PUBLIC bar PRIVATE bat)

+ 8 - 0
Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake

@@ -0,0 +1,8 @@
+include(RunCMake)
+
+run_cmake(CMP0023-WARN)
+run_cmake(CMP0023-NEW)
+run_cmake(CMP0023-WARN-2)
+run_cmake(CMP0023-NEW-2)
+run_cmake(MixedSignature)
+run_cmake(Separate-PRIVATE-LINK_PRIVATE-uses)

+ 1 - 0
Tests/RunCMake/target_link_libraries/Separate-PRIVATE-LINK_PRIVATE-uses-result.txt

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

+ 9 - 0
Tests/RunCMake/target_link_libraries/Separate-PRIVATE-LINK_PRIVATE-uses.cmake

@@ -0,0 +1,9 @@
+
+enable_language(CXX)
+
+add_library(foo empty_vs6_1.cpp)
+add_library(bar empty_vs6_2.cpp)
+add_library(bat empty_vs6_3.cpp)
+
+target_link_libraries(foo LINK_PRIVATE bar)
+target_link_libraries(foo PRIVATE bat)

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

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

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

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

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

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

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

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