summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2015-04-07 14:43:47 (GMT)
committerBrad King <brad.king@kitware.com>2015-04-09 15:29:18 (GMT)
commit882f48e5ba335a1dbc1750c23e6dea5fa92a3adc (patch)
tree7783686bed3456d95538a4770dff27f0e24963bc
parent318cd37097c724fac13a364fe3beb21055575ae7 (diff)
downloadCMake-882f48e5ba335a1dbc1750c23e6dea5fa92a3adc.zip
CMake-882f48e5ba335a1dbc1750c23e6dea5fa92a3adc.tar.gz
CMake-882f48e5ba335a1dbc1750c23e6dea5fa92a3adc.tar.bz2
Link libraries by full path even in implicit directories
When CMP0003 was first introduced we wanted to link all libraries by full path. However, some projects had problems on platforms where find_library would find /usr/lib/libfoo.so when the project really wanted to link to /usr/lib/<arch>/libfoo.so and had been working by accident because pre-CMP0003 behavior used -lfoo to link. We first tried to address that in commit v2.6.0~440 (Teach find_library to avoid returning library paths in system directories, 2008-01-23) by returning just "foo" for libraries in implicit link directories. This caused problems for projects expecting find_library to always return a full path. We ended up using the solution in commit v2.6.0~366 (... switch library paths found in implicit link directories to use -l, 2008-01-31). However, the special case for libraries in implicit link directories has also proven problematic and confusing. Introduce policy CMP0060 to switch to linking all libraries by full path even if they are in implicit link directories. Explain in the policy documentation the factors that led to the original approach and now to this approach.
-rw-r--r--Help/command/target_link_libraries.rst16
-rw-r--r--Help/manual/cmake-policies.7.rst1
-rw-r--r--Help/policy/CMP0060.rst63
-rw-r--r--Help/release/dev/link-implicit-libs-full-path.rst6
-rw-r--r--Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst2
-rw-r--r--Source/cmComputeLinkInformation.cxx42
-rw-r--r--Source/cmComputeLinkInformation.h4
-rw-r--r--Source/cmPolicies.cxx5
-rw-r--r--Source/cmPolicies.h1
-rw-r--r--Source/cmTarget.h3
-rw-r--r--Tests/RunCMake/CMP0060/CMP0060-Common.cmake35
-rw-r--r--Tests/RunCMake/CMP0060/CMP0060-NEW.cmake2
-rw-r--r--Tests/RunCMake/CMP0060/CMP0060-OLD-Build-result.txt1
-rw-r--r--Tests/RunCMake/CMP0060/CMP0060-OLD-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/CMP0060/CMP0060-OLD.cmake2
-rw-r--r--Tests/RunCMake/CMP0060/CMP0060-WARN-OFF-Build-result.txt1
-rw-r--r--Tests/RunCMake/CMP0060/CMP0060-WARN-OFF-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/CMP0060/CMP0060-WARN-OFF.cmake1
-rw-r--r--Tests/RunCMake/CMP0060/CMP0060-WARN-ON-Build-result.txt1
-rw-r--r--Tests/RunCMake/CMP0060/CMP0060-WARN-ON-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/CMP0060/CMP0060-WARN-ON-stderr.txt16
-rw-r--r--Tests/RunCMake/CMP0060/CMP0060-WARN-ON.cmake2
-rw-r--r--Tests/RunCMake/CMP0060/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CMP0060/RunCMakeTest.cmake19
-rw-r--r--Tests/RunCMake/CMP0060/cmp0060.c4
-rw-r--r--Tests/RunCMake/CMP0060/main.c5
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt1
28 files changed, 234 insertions, 6 deletions
diff --git a/Help/command/target_link_libraries.rst b/Help/command/target_link_libraries.rst
index 393c8b4..d903d05 100644
--- a/Help/command/target_link_libraries.rst
+++ b/Help/command/target_link_libraries.rst
@@ -34,14 +34,20 @@ Each ``<item>`` may be:
automatically be added in the build system to make sure the named
library target is up-to-date before the ``<target>`` links.
+ If an imported library has the :prop_tgt:`IMPORTED_NO_SONAME`
+ target property set, CMake may ask the linker to search for
+ the library instead of using the full path
+ (e.g. ``/usr/lib/libfoo.so`` becomes ``-lfoo``).
+
* **A full path to a library file**: The generated link line will
- normally preserve the full path to the file. However, there are
- some cases where CMake must ask the linker to search for the library
- (e.g. ``/usr/lib/libfoo.so`` becomes ``-lfoo``), such as when it
- appears in a system library directory that the compiler front-end
- may replace with an alternative. Either way, the buildsystem will
+ normally preserve the full path to the file. The buildsystem will
have a dependency to re-link ``<target>`` if the library file changes.
+ There are some cases where CMake may ask the linker to search for
+ the library (e.g. ``/usr/lib/libfoo.so`` becomes ``-lfoo``), such
+ as when a shared library is detected to have no ``SONAME`` field.
+ See policy :policy:`CMP0060` for discussion of another case.
+
If the library file is in a Mac OSX framework, the ``Headers`` directory
of the framework will also be processed as a
:ref:`usage requirement <Target Usage Requirements>`. This has the same
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index d2960de..aff696d 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -117,3 +117,4 @@ All Policies
/policy/CMP0057
/policy/CMP0058
/policy/CMP0059
+ /policy/CMP0060
diff --git a/Help/policy/CMP0060.rst b/Help/policy/CMP0060.rst
new file mode 100644
index 0000000..cc37b1b
--- /dev/null
+++ b/Help/policy/CMP0060.rst
@@ -0,0 +1,63 @@
+CMP0060
+-------
+
+Link libraries by full path even in implicit directories.
+
+Policy :policy:`CMP0003` was introduced with the intention of always
+linking library files by full path when a full path is given to the
+:command:`target_link_libraries` command. However, on some platforms
+(e.g. HP-UX) the compiler front-end adds alternative library search paths
+for the current architecture (e.g. ``/usr/lib/<arch>`` has alternatives
+to libraries in ``/usr/lib`` for the current architecture).
+On such platforms the :command:`find_library` may find a library such as
+``/usr/lib/libfoo.so`` that does not belong to the current architecture.
+
+Prior to policy :policy:`CMP0003` projects would still build in such
+cases because the incorrect library path would be converted to ``-lfoo``
+on the link line and the linker would find the proper library in the
+arch-specific search path provided by the compiler front-end implicitly.
+At the time we chose to remain compatible with such projects by always
+converting library files found in implicit link directories to ``-lfoo``
+flags to ask the linker to search for them. This approach allowed existing
+projects to continue to build while still linking to libraries outside
+implicit link directories via full path (such as those in the build tree).
+
+CMake does allow projects to override this behavior by using an
+:ref:`IMPORTED library target <Imported Targets>` with its
+:prop_tgt:`IMPORTED_LOCATION` property set to the desired full path to
+a library file. In fact, many :ref:`Find Modules` are learning to provide
+:ref:`Imported Targets` instead of just the traditional ``Foo_LIBRARIES``
+variable listing library files. However, this makes the link line
+generated for a library found by a Find Module depend on whether it
+is linked through an imported target or not, which is inconsistent.
+Furthermore, this behavior has been a source of confusion because the
+generated link line for a library file depends on its location. It is
+also problematic for projects trying to link statically because flags
+like ``-Wl,-Bstatic -lfoo -Wl,-Bdynamic`` may be used to help the linker
+select ``libfoo.a`` instead of ``libfoo.so`` but then leak dynamic linking
+to following libraries. (See the :prop_tgt:`LINK_SEARCH_END_STATIC`
+target property for a solution typically used for that problem.)
+
+When the special case for libraries in implicit link directories was first
+introduced the list of implicit link directories was simply hard-coded
+(e.g. ``/lib``, ``/usr/lib``, and a few others). Since that time, CMake
+has learned to detect the implicit link directories used by the compiler
+front-end. If necessary, the :command:`find_library` command could be
+taught to use this information to help find libraries of the proper
+architecture.
+
+For these reasons, CMake 3.3 and above prefer to drop the special case
+and link libraries by full path even when they are in implicit link
+directories. Policy ``CMP0060`` provides compatibility for existing
+projects.
+
+The OLD behavior for this policy is to ask the linker to search for
+libraries whose full paths are known to be in implicit link directories.
+The NEW behavior for this policy is to link libraries by full path even
+if they are in implicit link directories.
+
+This policy was introduced in CMake version 3.3. Unlike most policies,
+CMake version |release| does *not* warn by default when this policy
+is not set and simply uses OLD behavior. See documentation of the
+:variable:`CMAKE_POLICY_WARNING_CMP0060 <CMAKE_POLICY_WARNING_CMP<NNNN>>`
+variable to control the warning.
diff --git a/Help/release/dev/link-implicit-libs-full-path.rst b/Help/release/dev/link-implicit-libs-full-path.rst
new file mode 100644
index 0000000..7ed7245
--- /dev/null
+++ b/Help/release/dev/link-implicit-libs-full-path.rst
@@ -0,0 +1,6 @@
+link-implicit-libs-full-path
+----------------------------
+
+* Linking to library files by a full path in an implicit linker search
+ directory (e.g. ``/usr/lib/libfoo.a``) no longer asks the linker to
+ search for the library (e.g. ``-lfoo``). See policy :policy:`CMP0060`.
diff --git a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
index a83c807..092fe3e 100644
--- a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
+++ b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
@@ -11,6 +11,8 @@ warn by default:
policy :policy:`CMP0047`.
* ``CMAKE_POLICY_WARNING_CMP0056`` controls the warning for
policy :policy:`CMP0056`.
+* ``CMAKE_POLICY_WARNING_CMP0060`` controls the warning for
+ policy :policy:`CMP0060`.
This variable should not be set by a project in CMake code. Project
developers running CMake may set this variable in their cache to
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index b0e0f36..8880667 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -411,6 +411,10 @@ cmComputeLinkInformation
std::vector<std::string> const& dirs = this->Target->GetLinkDirectories();
this->OldLinkDirMask.insert(dirs.begin(), dirs.end());
}
+
+ this->CMP0060Warn =
+ this->Makefile->PolicyOptionalWarningEnabled(
+ "CMAKE_POLICY_WARNING_CMP0060");
}
//----------------------------------------------------------------------------
@@ -548,6 +552,22 @@ bool cmComputeLinkInformation::Compute()
// Add implicit language runtime libraries and directories.
this->AddImplicitLinkInfo();
+ if (!this->CMP0060WarnItems.empty())
+ {
+ std::ostringstream w;
+ w << (this->Makefile->GetCMakeInstance()->GetPolicies()
+ ->GetPolicyWarning(cmPolicies::CMP0060)) << "\n"
+ "Some library files are in directories implicitly searched by "
+ "the linker when invoked for " << this->LinkLanguage << ":\n"
+ " " << cmJoin(this->CMP0060WarnItems, "\n ") << "\n"
+ "For compatibility with older versions of CMake, the generated "
+ "link line will ask the linker to search for these by library "
+ "name."
+ ;
+ this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(),
+ this->Target->GetBacktrace());
+ }
+
return true;
}
@@ -1190,6 +1210,28 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item)
return false;
}
+ // Check the policy for whether we should use the approach below.
+ switch (this->Target->GetPolicyStatusCMP0060())
+ {
+ case cmPolicies::WARN:
+ if (this->CMP0060Warn)
+ {
+ // Print the warning at most once for this item.
+ std::string const& wid = "CMP0060-WARNING-GIVEN-" + item;
+ if (!this->CMakeInstance->GetPropertyAsBool(wid))
+ {
+ this->CMakeInstance->SetProperty(wid, "1");
+ this->CMP0060WarnItems.insert(item);
+ }
+ }
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ return false;
+ }
+
// Many system linkers support multiple architectures by
// automatically selecting the implicit linker search path for the
// current architecture. If the library appears in an implicit link
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index e5d674a..8847141 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -175,6 +175,10 @@ private:
std::vector<std::string> OldUserFlagItems;
bool OldLinkDirMode;
+ // CMP0060 warnings.
+ bool CMP0060Warn;
+ std::set<std::string> CMP0060WarnItems;
+
// Runtime path computation.
cmOrderDirectories* OrderRuntimeSearchPath;
void AddLibraryRuntimeInfo(std::string const& fullPath,
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 0a61bca..e7678cb 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -390,6 +390,11 @@ cmPolicies::cmPolicies()
CMP0059, "CMP0059",
"Do no treat DEFINITIONS as a built-in directory property.",
3,3,0, cmPolicies::WARN);
+
+ this->DefinePolicy(
+ CMP0060, "CMP0060",
+ "Link libraries by full path even in implicit directories.",
+ 3,3,0, cmPolicies::WARN);
}
cmPolicies::~cmPolicies()
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index ced9d8c..1d108c1 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -118,6 +118,7 @@ public:
CMP0058, ///< Ninja requires custom command byproducts to be explicit
CMP0059, ///< Do not treat ``DEFINITIONS`` as a built-in directory
/// property.
+ CMP0060, ///< Link libraries by full path even in implicit directories.
/** \brief Always the last entry.
*
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index a4ef977..55bf234 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -34,7 +34,8 @@
F(CMP0041) \
F(CMP0042) \
F(CMP0046) \
- F(CMP0052)
+ F(CMP0052) \
+ F(CMP0060)
class cmake;
class cmMakefile;
diff --git a/Tests/RunCMake/CMP0060/CMP0060-Common.cmake b/Tests/RunCMake/CMP0060/CMP0060-Common.cmake
new file mode 100644
index 0000000..e0a56e6
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/CMP0060-Common.cmake
@@ -0,0 +1,35 @@
+# Always build in a predictable configuration. For multi-config
+# generators we depend on RunCMakeTest.cmake to do this for us.
+if(NOT CMAKE_CONFIGURATION_TYPES)
+ set(CMAKE_BUILD_TYPE Debug)
+endif()
+
+# Convince CMake that it can instruct the linker to search for the
+# library of the proper linkage type, but do not really pass flags.
+set(CMAKE_EXE_LINK_STATIC_C_FLAGS " ")
+set(CMAKE_EXE_LINK_DYNAMIC_C_FLAGS " ")
+
+# Make a link line asking for the linker to search for the library
+# look like a missing object file so we will get predictable content
+# in the error message. This also ensures that cases expected to use
+# the full path can be verified by confirming that they link.
+set(CMAKE_LINK_LIBRARY_FLAG LINKFLAG_)
+set(CMAKE_LINK_LIBRARY_SUFFIX _LINKSUFFIX${CMAKE_C_OUTPUT_EXTENSION})
+
+# Convince CMake that our library is in an implicit linker search directory.
+list(APPEND CMAKE_C_IMPLICIT_LINK_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}/lib)
+
+# Create a simple library file. Place it in our library directory.
+add_library(CMP0060 STATIC cmp0060.c)
+set_property(TARGET CMP0060 PROPERTY
+ ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/lib)
+
+# Add a target to link the library file by full path.
+add_executable(main1 main.c)
+target_link_libraries(main1 $<TARGET_FILE:CMP0060>)
+add_dependencies(main1 CMP0060)
+
+# Add a second target to verify the warning only appears once.
+add_executable(main2 main.c)
+target_link_libraries(main2 $<TARGET_FILE:CMP0060>)
+add_dependencies(main2 CMP0060)
diff --git a/Tests/RunCMake/CMP0060/CMP0060-NEW.cmake b/Tests/RunCMake/CMP0060/CMP0060-NEW.cmake
new file mode 100644
index 0000000..0414e4b
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/CMP0060-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0060 NEW)
+include(CMP0060-Common.cmake)
diff --git a/Tests/RunCMake/CMP0060/CMP0060-OLD-Build-result.txt b/Tests/RunCMake/CMP0060/CMP0060-OLD-Build-result.txt
new file mode 100644
index 0000000..d197c91
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/CMP0060-OLD-Build-result.txt
@@ -0,0 +1 @@
+[^0]
diff --git a/Tests/RunCMake/CMP0060/CMP0060-OLD-Build-stdout.txt b/Tests/RunCMake/CMP0060/CMP0060-OLD-Build-stdout.txt
new file mode 100644
index 0000000..240764c
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/CMP0060-OLD-Build-stdout.txt
@@ -0,0 +1 @@
+LINKFLAG_CMP0060_LINKSUFFIX
diff --git a/Tests/RunCMake/CMP0060/CMP0060-OLD.cmake b/Tests/RunCMake/CMP0060/CMP0060-OLD.cmake
new file mode 100644
index 0000000..a9cffef
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/CMP0060-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0060 OLD)
+include(CMP0060-Common.cmake)
diff --git a/Tests/RunCMake/CMP0060/CMP0060-WARN-OFF-Build-result.txt b/Tests/RunCMake/CMP0060/CMP0060-WARN-OFF-Build-result.txt
new file mode 100644
index 0000000..d197c91
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/CMP0060-WARN-OFF-Build-result.txt
@@ -0,0 +1 @@
+[^0]
diff --git a/Tests/RunCMake/CMP0060/CMP0060-WARN-OFF-Build-stdout.txt b/Tests/RunCMake/CMP0060/CMP0060-WARN-OFF-Build-stdout.txt
new file mode 100644
index 0000000..240764c
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/CMP0060-WARN-OFF-Build-stdout.txt
@@ -0,0 +1 @@
+LINKFLAG_CMP0060_LINKSUFFIX
diff --git a/Tests/RunCMake/CMP0060/CMP0060-WARN-OFF.cmake b/Tests/RunCMake/CMP0060/CMP0060-WARN-OFF.cmake
new file mode 100644
index 0000000..6b84565
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/CMP0060-WARN-OFF.cmake
@@ -0,0 +1 @@
+include(CMP0060-Common.cmake)
diff --git a/Tests/RunCMake/CMP0060/CMP0060-WARN-ON-Build-result.txt b/Tests/RunCMake/CMP0060/CMP0060-WARN-ON-Build-result.txt
new file mode 100644
index 0000000..d197c91
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/CMP0060-WARN-ON-Build-result.txt
@@ -0,0 +1 @@
+[^0]
diff --git a/Tests/RunCMake/CMP0060/CMP0060-WARN-ON-Build-stdout.txt b/Tests/RunCMake/CMP0060/CMP0060-WARN-ON-Build-stdout.txt
new file mode 100644
index 0000000..240764c
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/CMP0060-WARN-ON-Build-stdout.txt
@@ -0,0 +1 @@
+LINKFLAG_CMP0060_LINKSUFFIX
diff --git a/Tests/RunCMake/CMP0060/CMP0060-WARN-ON-stderr.txt b/Tests/RunCMake/CMP0060/CMP0060-WARN-ON-stderr.txt
new file mode 100644
index 0000000..f6cc978
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/CMP0060-WARN-ON-stderr.txt
@@ -0,0 +1,16 @@
+^CMake Warning \(dev\) at CMP0060-Common.cmake:[0-9]+ \(add_executable\):
+ Policy CMP0060 is not set: Link libraries by full path even in implicit
+ directories. Run "cmake --help-policy CMP0060" for policy details. Use
+ the cmake_policy command to set the policy and suppress this warning.
+
+ Some library files are in directories implicitly searched by the linker
+ when invoked for C:
+
+ .*/Tests/RunCMake/CMP0060/CMP0060-WARN-ON-build/lib/(lib)?CMP0060.(a|lib)
+
+ For compatibility with older versions of CMake, the generated link line
+ will ask the linker to search for these by library name.
+Call Stack \(most recent call first\):
+ CMP0060-WARN-ON.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/CMP0060/CMP0060-WARN-ON.cmake b/Tests/RunCMake/CMP0060/CMP0060-WARN-ON.cmake
new file mode 100644
index 0000000..a0a7950
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/CMP0060-WARN-ON.cmake
@@ -0,0 +1,2 @@
+set(CMAKE_POLICY_WARNING_CMP0060 1)
+include(CMP0060-Common.cmake)
diff --git a/Tests/RunCMake/CMP0060/CMakeLists.txt b/Tests/RunCMake/CMP0060/CMakeLists.txt
new file mode 100644
index 0000000..db6b701
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.2)
+project(${RunCMake_TEST} C)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0060/RunCMakeTest.cmake b/Tests/RunCMake/CMP0060/RunCMakeTest.cmake
new file mode 100644
index 0000000..445156f
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/RunCMakeTest.cmake
@@ -0,0 +1,19 @@
+include(RunCMake)
+
+function(run_cmake_CMP0060 CASE)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0060-${CASE}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+ run_cmake(CMP0060-${CASE})
+ set(RunCMake_TEST_OUTPUT_MERGE 1)
+ run_cmake_command(CMP0060-${CASE}-Build
+ ${CMAKE_COMMAND} --build . --config Debug
+ )
+endfunction()
+
+run_cmake_CMP0060(OLD)
+run_cmake_CMP0060(WARN-OFF)
+run_cmake_CMP0060(WARN-ON)
+run_cmake_CMP0060(NEW)
diff --git a/Tests/RunCMake/CMP0060/cmp0060.c b/Tests/RunCMake/CMP0060/cmp0060.c
new file mode 100644
index 0000000..a2da227
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/cmp0060.c
@@ -0,0 +1,4 @@
+int libCMP0060(void)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CMP0060/main.c b/Tests/RunCMake/CMP0060/main.c
new file mode 100644
index 0000000..91848c2
--- /dev/null
+++ b/Tests/RunCMake/CMP0060/main.c
@@ -0,0 +1,5 @@
+extern int libCMP0060(void);
+int main(void)
+{
+ return libCMP0060();
+}
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 60a8a82..e53612f 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -65,6 +65,7 @@ add_RunCMake_test(CMP0054)
add_RunCMake_test(CMP0055)
add_RunCMake_test(CMP0057)
add_RunCMake_test(CMP0059)
+add_RunCMake_test(CMP0060)
if(CMAKE_GENERATOR STREQUAL "Ninja")
add_RunCMake_test(Ninja)
endif()
diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
index f4b744b..1da1623 100644
--- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
+++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
@@ -17,6 +17,7 @@
\* CMP0042
\* CMP0046
\* CMP0052
+ \* CMP0060
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)