Consider targets with double colons to be IMPORTED or ALIAS targets.

Introduce a policy to control the behavior.

The AliasTargets unit test already tests that using a
double-semicolon in the name is not an error. Change the ExportImport
test to use a namespace with a double-semicolon too.
This commit is contained in:
Stephen Kelly 2013-07-30 09:51:56 +02:00
parent 919e1e8453
commit f063c45589
20 changed files with 124 additions and 11 deletions

View File

@ -37,3 +37,4 @@ All Policies
/policy/CMP0025
/policy/CMP0026
/policy/CMP0027
/policy/CMP0028

23
Help/policy/CMP0028.rst Normal file
View File

@ -0,0 +1,23 @@
CMP0028
-------
Double colon in target name means ALIAS or IMPORTED target.
CMake 2.8.12 and lower allowed the use of targets and files with double
colons in target_link_libraries, with some buildsystem generators.
The use of double-colons is a common pattern used to namespace IMPORTED
targets and ALIAS targets. When computing the link dependencies of a target,
the name of each dependency could either be a target, or a file on disk.
Previously, if a target was not found with a matching name, the name was
considered to refer to a file on disk. This can lead to confusing error
messages if there is a typo in what should be a target name.
The OLD behavior for this policy is to search for targets, then files on disk,
even if the search term contains double-colons. The NEW behavior for this
policy is to issue a FATAL_ERROR if a link dependency contains
double-colons but is not an IMPORTED target or an ALIAS target.
This policy was introduced in CMake version 3.0.0. CMake version
|release| warns when the policy is not set and uses OLD behavior. Use
the cmake_policy command to set it to OLD or NEW explicitly.

View File

@ -241,6 +241,11 @@ cmPolicies::cmPolicies()
CMP0027, "CMP0027",
"Conditionally linked imported targets with missing include directories.",
3,0,0,0, cmPolicies::WARN);
this->DefinePolicy(
CMP0028, "CMP0028",
"Double colon in target name means ALIAS or IMPORTED target.",
3,0,0,0, cmPolicies::WARN);
}
cmPolicies::~cmPolicies()

View File

@ -79,6 +79,7 @@ public:
CMP0026, ///< Disallow use of the LOCATION target property.
CMP0027, ///< Conditionally linked imported targets with missing include
/// directories.
CMP0028, ///< Double colon in target name means ALIAS or IMPORTED target.
/** \brief Always the last entry.
*

View File

@ -5483,6 +5483,46 @@ void cmTarget::ComputeLinkImplementation(const char* config,
{
continue;
}
cmTarget *tgt = this->Makefile->FindTargetToUse(li->c_str());
if(!tgt && std::string(item).find("::") != std::string::npos)
{
bool noMessage = false;
cmake::MessageType messageType = cmake::FATAL_ERROR;
cmOStringStream e;
switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0028))
{
case cmPolicies::WARN:
{
e << (this->Makefile->GetPolicies()
->GetPolicyWarning(cmPolicies::CMP0028)) << "\n";
messageType = cmake::AUTHOR_WARNING;
}
break;
case cmPolicies::OLD:
noMessage = true;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
// Issue the fatal message.
break;
}
if(!noMessage)
{
e << "Target \"" << this->GetName() << "\" links to target \"" << item
<< "\" but the target was not found. Perhaps a find_package() "
"call is missing for an IMPORTED target, or a ALIAS target is "
"missing?";
this->Makefile->GetCMakeInstance()->IssueMessage(messageType,
e.str(),
this->GetBacktrace());
if (messageType == cmake::FATAL_ERROR)
{
return;
}
}
}
// The entry is meant for this configuration.
impl.Libraries.push_back(item);
}

View File

@ -24,7 +24,7 @@ add_library(sharediface INTERFACE)
target_link_libraries(sharediface INTERFACE sharedlib)
export(TARGETS sharediface sharedlib headeronly
NAMESPACE bld_
NAMESPACE bld::
FILE ../ExportInterfaceBuildTree.cmake
)
@ -46,4 +46,4 @@ install(FILES
DESTINATION include/sharedlib
)
install(EXPORT expInterface NAMESPACE exp_ DESTINATION lib/exp)
install(EXPORT expInterface NAMESPACE exp:: DESTINATION lib/exp)

View File

@ -10,18 +10,18 @@ set_property(TARGET define_iface PROPERTY
INTERFACE_COMPILE_DEFINITIONS DEFINE_IFACE_DEFINE)
add_executable(headeronlytest_bld headeronlytest.cpp)
target_link_libraries(headeronlytest_bld bld_headeronly)
target_link_libraries(headeronlytest_bld bld::headeronly)
set_property(TARGET bld_sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface)
set_property(TARGET bld::sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface)
add_executable(interfacetest_bld interfacetest.cpp)
target_link_libraries(interfacetest_bld bld_sharediface)
target_link_libraries(interfacetest_bld bld::sharediface)
include(CheckCXXSourceCompiles)
macro(do_try_compile prefix)
set(CMAKE_REQUIRED_LIBRARIES ${prefix}headeronly)
set(CMAKE_REQUIRED_LIBRARIES ${prefix}::headeronly)
check_cxx_source_compiles(
"
#include \"headeronly.h\"
@ -42,14 +42,14 @@ macro(do_try_compile prefix)
endif()
endmacro()
do_try_compile(bld_)
do_try_compile(bld)
add_executable(headeronlytest_exp headeronlytest.cpp)
target_link_libraries(headeronlytest_exp exp_headeronly)
target_link_libraries(headeronlytest_exp exp::headeronly)
set_property(TARGET exp_sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface)
set_property(TARGET exp::sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface)
add_executable(interfacetest_exp interfacetest.cpp)
target_link_libraries(interfacetest_exp exp_sharediface)
target_link_libraries(interfacetest_exp exp::sharediface)
do_try_compile(exp_)
do_try_compile(exp)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,6 @@
CMake Error at CMP0028-NEW.cmake:4 \(add_library\):
Target "foo" links to target "External::Library" but the target was not
found. Perhaps a find_package\(\) call is missing for an IMPORTED target, or
a ALIAS target is missing\?
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1,5 @@
cmake_policy(SET CMP0028 NEW)
add_library(foo empty.cpp)
target_link_libraries(foo PRIVATE External::Library)

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1 @@
^$

View File

@ -0,0 +1,5 @@
cmake_policy(SET CMP0028 OLD)
add_library(foo empty.cpp)
target_link_libraries(foo PRIVATE External::Library)

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1,11 @@
CMake Warning \(dev\) at CMP0028-WARN.cmake:2 \(add_library\):
Policy CMP0028 is not set: Double colon in target name means ALIAS or
IMPORTED target. Run "cmake --help-policy CMP0028" for policy details.
Use the cmake_policy command to set the policy and suppress this warning.
Target "foo" links to target "External::Library" but the target was not
found. Perhaps a find_package\(\) call is missing for an IMPORTED target, or
a ALIAS target is missing\?
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.

View File

@ -0,0 +1,3 @@
add_library(foo empty.cpp)
target_link_libraries(foo PRIVATE External::Library)

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} CXX)
include(${RunCMake_TEST}.cmake NO_POLICY_SCOPE)

View File

@ -0,0 +1,5 @@
include(RunCMake)
run_cmake(CMP0028-NEW)
run_cmake(CMP0028-OLD)
run_cmake(CMP0028-WARN)

View File

View File

@ -55,6 +55,7 @@ add_RunCMake_test(CMP0019)
add_RunCMake_test(CMP0022)
add_RunCMake_test(CMP0026)
add_RunCMake_test(CMP0027)
add_RunCMake_test(CMP0028)
add_RunCMake_test(CTest)
if(UNIX AND "${CMAKE_TEST_GENERATOR}" MATCHES "Unix Makefiles")
add_RunCMake_test(CompilerChange)