summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Kelly <steveire@gmail.com>2013-06-04 14:25:47 (GMT)
committerStephen Kelly <steveire@gmail.com>2013-07-08 20:39:09 (GMT)
commitd0a76ea07cfc2a73900a9539e940e1e60dbba120 (patch)
tree8afdc5cb57a2ee3c88db5a677a2e642b40415326
parentddde61c0b2b46a452366acae690aca0095c0a49c (diff)
downloadCMake-d0a76ea07cfc2a73900a9539e940e1e60dbba120.zip
CMake-d0a76ea07cfc2a73900a9539e940e1e60dbba120.tar.gz
CMake-d0a76ea07cfc2a73900a9539e940e1e60dbba120.tar.bz2
Introduce the INTERFACE_LINK_LIBRARIES property.
This property replaces the properties which match (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?, and is enabled for IMPORTED targets, and for non-IMPORTED targets only with a policy. For static libraries, the INTERFACE_LINK_LIBRARIES property is also used as the source of transitive usage requirements content. Static libraries still require users to link to all entries in their LINK_LIBRARIES, but usage requirements such as INCLUDE_DIRECTORIES COMPILE_DEFINITIONS and COMPILE_OPTIONS can be restricted to only certain interface libraries. Because the INTERFACE_LINK_LIBRARIES property is populated unconditionally, we need to compare the evaluated result of it with the link implementation to determine whether to issue the policy warning for static libraries. For shared libraries, the policy warning is issued if the contents of the INTERFACE_LINK_LIBRARIES property differs from the contents of the relevant config-specific old LINK_INTERFACE_LIBRARIES property.
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx3
-rw-r--r--Source/cmPolicies.cxx22
-rw-r--r--Source/cmPolicies.h1
-rw-r--r--Source/cmTarget.cxx179
-rw-r--r--Source/cmTarget.h5
-rw-r--r--Tests/CMakeLists.txt10
-rw-r--r--Tests/InterfaceLinkLibraries/CMakeLists.txt49
-rw-r--r--Tests/InterfaceLinkLibraries/bang.cpp15
-rw-r--r--Tests/InterfaceLinkLibraries/bang.h4
-rw-r--r--Tests/InterfaceLinkLibraries/bang_vs6_1.cpp1
-rw-r--r--Tests/InterfaceLinkLibraries/bang_vs6_2.cpp1
-rw-r--r--Tests/InterfaceLinkLibraries/bar.cpp26
-rw-r--r--Tests/InterfaceLinkLibraries/bar.h7
-rw-r--r--Tests/InterfaceLinkLibraries/bar_vs6_1.cpp1
-rw-r--r--Tests/InterfaceLinkLibraries/bar_vs6_2.cpp1
-rw-r--r--Tests/InterfaceLinkLibraries/bar_vs6_3.cpp1
-rw-r--r--Tests/InterfaceLinkLibraries/bar_vs6_4.cpp1
-rw-r--r--Tests/InterfaceLinkLibraries/foo.cpp15
-rw-r--r--Tests/InterfaceLinkLibraries/foo.h4
-rw-r--r--Tests/InterfaceLinkLibraries/foo_vs6_1.cpp1
-rw-r--r--Tests/InterfaceLinkLibraries/foo_vs6_2.cpp1
-rw-r--r--Tests/InterfaceLinkLibraries/foo_vs6_3.cpp1
-rw-r--r--Tests/InterfaceLinkLibraries/foo_vs6_4.cpp1
-rw-r--r--Tests/InterfaceLinkLibraries/main.cpp19
-rw-r--r--Tests/InterfaceLinkLibraries/main_vs6_1.cpp1
-rw-r--r--Tests/InterfaceLinkLibraries/main_vs6_2.cpp1
-rw-r--r--Tests/InterfaceLinkLibraries/main_vs6_3.cpp1
-rw-r--r--Tests/InterfaceLinkLibraries/main_vs6_4.cpp1
-rw-r--r--Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-stderr.txt1
-rw-r--r--Tests/RunCMake/CMP0022/CMP0022-NOWARN-static.cmake8
-rw-r--r--Tests/RunCMake/CMP0022/CMP0022-WARN-static-result.txt1
-rw-r--r--Tests/RunCMake/CMP0022/CMP0022-WARN-static-stderr.txt10
-rw-r--r--Tests/RunCMake/CMP0022/CMP0022-WARN-static.cmake11
-rw-r--r--Tests/RunCMake/CMP0022/CMP0022-WARN-stderr.txt8
-rw-r--r--Tests/RunCMake/CMP0022/CMP0022-WARN.cmake11
-rw-r--r--Tests/RunCMake/CMP0022/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CMP0022/RunCMakeTest.cmake5
-rw-r--r--Tests/RunCMake/CMP0022/empty.cpp7
-rw-r--r--Tests/RunCMake/CMP0022/empty_vs6_1.cpp1
-rw-r--r--Tests/RunCMake/CMP0022/empty_vs6_2.cpp1
-rw-r--r--Tests/RunCMake/CMP0022/empty_vs6_3.cpp1
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
42 files changed, 434 insertions, 8 deletions
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index a4d5453..8b17c37 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -174,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;
}
//----------------------------------------------------------------------------
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 32829a6..20c3058 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -544,6 +544,28 @@ 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. "
+ "\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()
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index a033e87..20c953f 100644
--- a/Source/cmPolicies.h
+++ b/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.
*
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index f7424a7..3bad407 100644
--- a/Source/cmTarget.cxx
+++ b/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);
}
//----------------------------------------------------------------------------
@@ -3528,6 +3556,29 @@ static void cmTargetCheckLINK_INTERFACE_LIBRARIES(
}
//----------------------------------------------------------------------------
+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)
{
// Certain properties need checking.
@@ -3545,6 +3596,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);
+ }
+ }
}
//----------------------------------------------------------------------------
@@ -6013,8 +6071,34 @@ void cmTarget::GetTransitivePropertyLinkLibraries(
{
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);
- libs = iface->Libraries;
+ 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);
}
//----------------------------------------------------------------------------
@@ -6035,6 +6119,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())
@@ -6050,6 +6136,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
@@ -6113,7 +6274,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,
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index dd28405..d7ee332 100644
--- a/Source/cmTarget.h
+++ b/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
*/
@@ -695,6 +699,7 @@ private:
cmPolicies::PolicyStatus PolicyStatusCMP0008;
cmPolicies::PolicyStatus PolicyStatusCMP0020;
cmPolicies::PolicyStatus PolicyStatusCMP0021;
+ cmPolicies::PolicyStatus PolicyStatusCMP0022;
// Internal representation details.
friend class cmTargetInternals;
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 36cd7fd..fcefaf9 100644
--- a/Tests/CMakeLists.txt
+++ b/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
diff --git a/Tests/InterfaceLinkLibraries/CMakeLists.txt b/Tests/InterfaceLinkLibraries/CMakeLists.txt
new file mode 100644
index 0000000..bd0cf74
--- /dev/null
+++ b/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)
diff --git a/Tests/InterfaceLinkLibraries/bang.cpp b/Tests/InterfaceLinkLibraries/bang.cpp
new file mode 100644
index 0000000..2e95098
--- /dev/null
+++ b/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;
+}
diff --git a/Tests/InterfaceLinkLibraries/bang.h b/Tests/InterfaceLinkLibraries/bang.h
new file mode 100644
index 0000000..acffb39
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/bang.h
@@ -0,0 +1,4 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int bang();
diff --git a/Tests/InterfaceLinkLibraries/bang_vs6_1.cpp b/Tests/InterfaceLinkLibraries/bang_vs6_1.cpp
new file mode 100644
index 0000000..4886861
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/bang_vs6_1.cpp
@@ -0,0 +1 @@
+#include "bang.cpp"
diff --git a/Tests/InterfaceLinkLibraries/bang_vs6_2.cpp b/Tests/InterfaceLinkLibraries/bang_vs6_2.cpp
new file mode 100644
index 0000000..4886861
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/bang_vs6_2.cpp
@@ -0,0 +1 @@
+#include "bang.cpp"
diff --git a/Tests/InterfaceLinkLibraries/bar.cpp b/Tests/InterfaceLinkLibraries/bar.cpp
new file mode 100644
index 0000000..f39bfa5
--- /dev/null
+++ b/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
+}
diff --git a/Tests/InterfaceLinkLibraries/bar.h b/Tests/InterfaceLinkLibraries/bar.h
new file mode 100644
index 0000000..f83b37e
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/bar.h
@@ -0,0 +1,7 @@
+
+#include "foo.h"
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int bar();
diff --git a/Tests/InterfaceLinkLibraries/bar_vs6_1.cpp b/Tests/InterfaceLinkLibraries/bar_vs6_1.cpp
new file mode 100644
index 0000000..58a04c4
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/bar_vs6_1.cpp
@@ -0,0 +1 @@
+#include "bar.cpp"
diff --git a/Tests/InterfaceLinkLibraries/bar_vs6_2.cpp b/Tests/InterfaceLinkLibraries/bar_vs6_2.cpp
new file mode 100644
index 0000000..58a04c4
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/bar_vs6_2.cpp
@@ -0,0 +1 @@
+#include "bar.cpp"
diff --git a/Tests/InterfaceLinkLibraries/bar_vs6_3.cpp b/Tests/InterfaceLinkLibraries/bar_vs6_3.cpp
new file mode 100644
index 0000000..58a04c4
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/bar_vs6_3.cpp
@@ -0,0 +1 @@
+#include "bar.cpp"
diff --git a/Tests/InterfaceLinkLibraries/bar_vs6_4.cpp b/Tests/InterfaceLinkLibraries/bar_vs6_4.cpp
new file mode 100644
index 0000000..58a04c4
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/bar_vs6_4.cpp
@@ -0,0 +1 @@
+#include "bar.cpp"
diff --git a/Tests/InterfaceLinkLibraries/foo.cpp b/Tests/InterfaceLinkLibraries/foo.cpp
new file mode 100644
index 0000000..5295707
--- /dev/null
+++ b/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;
+}
diff --git a/Tests/InterfaceLinkLibraries/foo.h b/Tests/InterfaceLinkLibraries/foo.h
new file mode 100644
index 0000000..e12e23c
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/foo.h
@@ -0,0 +1,4 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int foo();
diff --git a/Tests/InterfaceLinkLibraries/foo_vs6_1.cpp b/Tests/InterfaceLinkLibraries/foo_vs6_1.cpp
new file mode 100644
index 0000000..d2e5e52
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/foo_vs6_1.cpp
@@ -0,0 +1 @@
+#include "foo.cpp"
diff --git a/Tests/InterfaceLinkLibraries/foo_vs6_2.cpp b/Tests/InterfaceLinkLibraries/foo_vs6_2.cpp
new file mode 100644
index 0000000..d2e5e52
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/foo_vs6_2.cpp
@@ -0,0 +1 @@
+#include "foo.cpp"
diff --git a/Tests/InterfaceLinkLibraries/foo_vs6_3.cpp b/Tests/InterfaceLinkLibraries/foo_vs6_3.cpp
new file mode 100644
index 0000000..d2e5e52
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/foo_vs6_3.cpp
@@ -0,0 +1 @@
+#include "foo.cpp"
diff --git a/Tests/InterfaceLinkLibraries/foo_vs6_4.cpp b/Tests/InterfaceLinkLibraries/foo_vs6_4.cpp
new file mode 100644
index 0000000..d2e5e52
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/foo_vs6_4.cpp
@@ -0,0 +1 @@
+#include "foo.cpp"
diff --git a/Tests/InterfaceLinkLibraries/main.cpp b/Tests/InterfaceLinkLibraries/main.cpp
new file mode 100644
index 0000000..a54076a
--- /dev/null
+++ b/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();
+}
diff --git a/Tests/InterfaceLinkLibraries/main_vs6_1.cpp b/Tests/InterfaceLinkLibraries/main_vs6_1.cpp
new file mode 100644
index 0000000..9b10ef2
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/main_vs6_1.cpp
@@ -0,0 +1 @@
+#include "main.cpp"
diff --git a/Tests/InterfaceLinkLibraries/main_vs6_2.cpp b/Tests/InterfaceLinkLibraries/main_vs6_2.cpp
new file mode 100644
index 0000000..9b10ef2
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/main_vs6_2.cpp
@@ -0,0 +1 @@
+#include "main.cpp"
diff --git a/Tests/InterfaceLinkLibraries/main_vs6_3.cpp b/Tests/InterfaceLinkLibraries/main_vs6_3.cpp
new file mode 100644
index 0000000..9b10ef2
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/main_vs6_3.cpp
@@ -0,0 +1 @@
+#include "main.cpp"
diff --git a/Tests/InterfaceLinkLibraries/main_vs6_4.cpp b/Tests/InterfaceLinkLibraries/main_vs6_4.cpp
new file mode 100644
index 0000000..9b10ef2
--- /dev/null
+++ b/Tests/InterfaceLinkLibraries/main_vs6_4.cpp
@@ -0,0 +1 @@
+#include "main.cpp"
diff --git a/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-stderr.txt
new file mode 100644
index 0000000..10f3293
--- /dev/null
+++ b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-stderr.txt
@@ -0,0 +1 @@
+^$
diff --git a/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static.cmake b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static.cmake
new file mode 100644
index 0000000..3e4144f
--- /dev/null
+++ b/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)
diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-static-result.txt b/Tests/RunCMake/CMP0022/CMP0022-WARN-static-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-static-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-static-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-WARN-static-stderr.txt
new file mode 100644
index 0000000..41d132c
--- /dev/null
+++ b/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.$
diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-static.cmake b/Tests/RunCMake/CMP0022/CMP0022-WARN-static.cmake
new file mode 100644
index 0000000..b3cb131
--- /dev/null
+++ b/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)
diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-WARN-stderr.txt
new file mode 100644
index 0000000..29103c9
--- /dev/null
+++ b/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.$
diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN.cmake b/Tests/RunCMake/CMP0022/CMP0022-WARN.cmake
new file mode 100644
index 0000000..24b7f45
--- /dev/null
+++ b/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)
diff --git a/Tests/RunCMake/CMP0022/CMakeLists.txt b/Tests/RunCMake/CMP0022/CMakeLists.txt
new file mode 100644
index 0000000..72abfc8
--- /dev/null
+++ b/Tests/RunCMake/CMP0022/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.11)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0022/RunCMakeTest.cmake b/Tests/RunCMake/CMP0022/RunCMakeTest.cmake
new file mode 100644
index 0000000..2e74f17
--- /dev/null
+++ b/Tests/RunCMake/CMP0022/RunCMakeTest.cmake
@@ -0,0 +1,5 @@
+include(RunCMake)
+
+run_cmake(CMP0022-WARN)
+run_cmake(CMP0022-WARN-static)
+run_cmake(CMP0022-NOWARN-static)
diff --git a/Tests/RunCMake/CMP0022/empty.cpp b/Tests/RunCMake/CMP0022/empty.cpp
new file mode 100644
index 0000000..bfbbdde
--- /dev/null
+++ b/Tests/RunCMake/CMP0022/empty.cpp
@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int empty()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CMP0022/empty_vs6_1.cpp b/Tests/RunCMake/CMP0022/empty_vs6_1.cpp
new file mode 100644
index 0000000..7efedab
--- /dev/null
+++ b/Tests/RunCMake/CMP0022/empty_vs6_1.cpp
@@ -0,0 +1 @@
+#include "empty.cpp"
diff --git a/Tests/RunCMake/CMP0022/empty_vs6_2.cpp b/Tests/RunCMake/CMP0022/empty_vs6_2.cpp
new file mode 100644
index 0000000..7efedab
--- /dev/null
+++ b/Tests/RunCMake/CMP0022/empty_vs6_2.cpp
@@ -0,0 +1 @@
+#include "empty.cpp"
diff --git a/Tests/RunCMake/CMP0022/empty_vs6_3.cpp b/Tests/RunCMake/CMP0022/empty_vs6_3.cpp
new file mode 100644
index 0000000..7efedab
--- /dev/null
+++ b/Tests/RunCMake/CMP0022/empty_vs6_3.cpp
@@ -0,0 +1 @@
+#include "empty.cpp"
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index c1a08d2..e07c42f 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/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)