Disallow link-to-self (#13947).

This commit is contained in:
Stephen Kelly 2013-11-05 18:01:09 +01:00
parent 05f5fde0eb
commit 301bb5cdda
18 changed files with 105 additions and 7 deletions

View File

@ -71,3 +71,4 @@ All Policies
/policy/CMP0035 /policy/CMP0035
/policy/CMP0036 /policy/CMP0036
/policy/CMP0037 /policy/CMP0037
/policy/CMP0038

16
Help/policy/CMP0038.rst Normal file
View File

@ -0,0 +1,16 @@
CMP0038
-------
Targets may not link directly to themselves
CMake 2.8.12 and lower allowed a build target to link to itself directly with
a :command:`target_link_libraries` call. This is an indicator of a bug in
user code.
The OLD behavior for this policy is to ignore targets which list themselves
in their own link implementation. The NEW behavior for this policy is to
report an error if a target attempts to link to itself.
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

@ -291,6 +291,11 @@ cmPolicies::cmPolicies()
CMP0037, "CMP0037", CMP0037, "CMP0037",
"Target names should match a validity pattern.", "Target names should match a validity pattern.",
3,0,0,0, cmPolicies::WARN); 3,0,0,0, cmPolicies::WARN);
this->DefinePolicy(
CMP0038, "CMP0038",
"Targets may not link directly to themselves.",
3,0,0,0, cmPolicies::WARN);
} }
cmPolicies::~cmPolicies() cmPolicies::~cmPolicies()

View File

@ -89,6 +89,7 @@ public:
CMP0035, ///< Disallow command: variable_requires CMP0035, ///< Disallow command: variable_requires
CMP0036, ///< Disallow command: build_name CMP0036, ///< Disallow command: build_name
CMP0037, ///< Target names should match a validity pattern. CMP0037, ///< Target names should match a validity pattern.
CMP0038, ///< Targets may not link directly to themselves
/** \brief Always the last entry. /** \brief Always the last entry.
* *

View File

@ -932,12 +932,6 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf,
const char *target, const char* lib, const char *target, const char* lib,
LinkLibraryType llt) LinkLibraryType llt)
{ {
// Never add a self dependency, even if the user asks for it.
if(strcmp( target, lib ) == 0)
{
return;
}
cmTarget *tgt = this->Makefile->FindTargetToUse(lib); cmTarget *tgt = this->Makefile->FindTargetToUse(lib);
{ {
const bool isNonImportedTarget = tgt && !tgt->IsImported(); const bool isNonImportedTarget = tgt && !tgt->IsImported();
@ -951,7 +945,8 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf,
} }
if (cmGeneratorExpression::Find(lib) != std::string::npos if (cmGeneratorExpression::Find(lib) != std::string::npos
|| (tgt && tgt->GetType() == INTERFACE_LIBRARY)) || (tgt && tgt->GetType() == INTERFACE_LIBRARY)
|| (strcmp( target, lib ) == 0))
{ {
return; return;
} }
@ -5293,6 +5288,41 @@ void cmTarget::ComputeLinkImplementation(const char* config,
std::string item = this->CheckCMP0004(*li); std::string item = this->CheckCMP0004(*li);
if(item == this->GetName() || item.empty()) if(item == this->GetName() || item.empty())
{ {
if(item == this->GetName())
{
bool noMessage = false;
cmake::MessageType messageType = cmake::FATAL_ERROR;
cmOStringStream e;
switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0038))
{
case cmPolicies::WARN:
{
e << (this->Makefile->GetPolicies()
->GetPolicyWarning(cmPolicies::CMP0038)) << "\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 itself.";
this->Makefile->GetCMakeInstance()->IssueMessage(messageType,
e.str(),
this->GetBacktrace());
if (messageType == cmake::FATAL_ERROR)
{
return;
}
}
}
continue; continue;
} }
cmTarget *tgt = this->Makefile->FindTargetToUse(li->c_str()); cmTarget *tgt = this->Makefile->FindTargetToUse(li->c_str());
@ -5335,6 +5365,7 @@ void cmTarget::ComputeLinkImplementation(const char* config,
} }
} }
} }
// The entry is meant for this configuration. // The entry is meant for this configuration.
impl.Libraries.push_back(item); impl.Libraries.push_back(item);
} }

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,4 @@
CMake Error at CMP0038-NEW.cmake:3 \(add_library\):
Target "self_link" links to itself.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1,4 @@
cmake_policy(SET CMP0038 NEW)
add_library(self_link empty.cpp)
target_link_libraries(self_link self_link)

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1 @@
^$

View File

@ -0,0 +1,4 @@
cmake_policy(SET CMP0038 OLD)
add_library(self_link empty.cpp)
target_link_libraries(self_link self_link)

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1,9 @@
CMake Warning \(dev\) at CMP0038-WARN.cmake:2 \(add_library\):
Policy CMP0038 is not set: Targets may not link directly to themselves.
Run "cmake --help-policy CMP0038" for policy details. Use the cmake_policy
command to set the policy and suppress this warning.
Target "self_link" links to itself.
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(self_link empty.cpp)
target_link_libraries(self_link self_link)

View File

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

View File

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

View File

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

View File

@ -59,6 +59,7 @@ add_RunCMake_test(CMP0028)
if (NOT "${CMAKE_TEST_GENERATOR}" MATCHES "(MSYS|MinGW|NMake|Borland) Makefiles") if (NOT "${CMAKE_TEST_GENERATOR}" MATCHES "(MSYS|MinGW|NMake|Borland) Makefiles")
add_RunCMake_test(CMP0037) add_RunCMake_test(CMP0037)
endif() endif()
add_RunCMake_test(CMP0038)
add_RunCMake_test(CTest) add_RunCMake_test(CTest)
if(UNIX AND "${CMAKE_TEST_GENERATOR}" MATCHES "Unix Makefiles") if(UNIX AND "${CMAKE_TEST_GENERATOR}" MATCHES "Unix Makefiles")
add_RunCMake_test(CompilerChange) add_RunCMake_test(CompilerChange)