From 301bb5cdda081f0bef0702e41ae4b47102b235df Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 5 Nov 2013 18:01:09 +0100 Subject: Disallow link-to-self (#13947). --- Help/manual/cmake-policies.7.rst | 1 + Help/policy/CMP0038.rst | 16 +++++++++ Source/cmPolicies.cxx | 5 +++ Source/cmPolicies.h | 1 + Source/cmTarget.cxx | 45 ++++++++++++++++++++++---- Tests/RunCMake/CMP0038/CMP0038-NEW-result.txt | 1 + Tests/RunCMake/CMP0038/CMP0038-NEW-stderr.txt | 4 +++ Tests/RunCMake/CMP0038/CMP0038-NEW.cmake | 4 +++ Tests/RunCMake/CMP0038/CMP0038-OLD-result.txt | 1 + Tests/RunCMake/CMP0038/CMP0038-OLD-stderr.txt | 1 + Tests/RunCMake/CMP0038/CMP0038-OLD.cmake | 4 +++ Tests/RunCMake/CMP0038/CMP0038-WARN-result.txt | 1 + Tests/RunCMake/CMP0038/CMP0038-WARN-stderr.txt | 9 ++++++ Tests/RunCMake/CMP0038/CMP0038-WARN.cmake | 3 ++ Tests/RunCMake/CMP0038/CMakeLists.txt | 3 ++ Tests/RunCMake/CMP0038/RunCMakeTest.cmake | 5 +++ Tests/RunCMake/CMP0038/empty.cpp | 7 ++++ Tests/RunCMake/CMakeLists.txt | 1 + 18 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 Help/policy/CMP0038.rst create mode 100644 Tests/RunCMake/CMP0038/CMP0038-NEW-result.txt create mode 100644 Tests/RunCMake/CMP0038/CMP0038-NEW-stderr.txt create mode 100644 Tests/RunCMake/CMP0038/CMP0038-NEW.cmake create mode 100644 Tests/RunCMake/CMP0038/CMP0038-OLD-result.txt create mode 100644 Tests/RunCMake/CMP0038/CMP0038-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0038/CMP0038-OLD.cmake create mode 100644 Tests/RunCMake/CMP0038/CMP0038-WARN-result.txt create mode 100644 Tests/RunCMake/CMP0038/CMP0038-WARN-stderr.txt create mode 100644 Tests/RunCMake/CMP0038/CMP0038-WARN.cmake create mode 100644 Tests/RunCMake/CMP0038/CMakeLists.txt create mode 100644 Tests/RunCMake/CMP0038/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/CMP0038/empty.cpp diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index addd2a7..f77a21c 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -71,3 +71,4 @@ All Policies /policy/CMP0035 /policy/CMP0036 /policy/CMP0037 + /policy/CMP0038 diff --git a/Help/policy/CMP0038.rst b/Help/policy/CMP0038.rst new file mode 100644 index 0000000..c448ed6 --- /dev/null +++ b/Help/policy/CMP0038.rst @@ -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. diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index db23f1e..af33d0b 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -291,6 +291,11 @@ cmPolicies::cmPolicies() CMP0037, "CMP0037", "Target names should match a validity pattern.", 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() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 821c58d..2ea9973 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -89,6 +89,7 @@ public: CMP0035, ///< Disallow command: variable_requires CMP0036, ///< Disallow command: build_name CMP0037, ///< Target names should match a validity pattern. + CMP0038, ///< Targets may not link directly to themselves /** \brief Always the last entry. * diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index d0390f7..d5e8420 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -932,12 +932,6 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, const char *target, const char* lib, 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); { const bool isNonImportedTarget = tgt && !tgt->IsImported(); @@ -951,7 +945,8 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, } if (cmGeneratorExpression::Find(lib) != std::string::npos - || (tgt && tgt->GetType() == INTERFACE_LIBRARY)) + || (tgt && tgt->GetType() == INTERFACE_LIBRARY) + || (strcmp( target, lib ) == 0)) { return; } @@ -5293,6 +5288,41 @@ void cmTarget::ComputeLinkImplementation(const char* config, std::string item = this->CheckCMP0004(*li); 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; } 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. impl.Libraries.push_back(item); } diff --git a/Tests/RunCMake/CMP0038/CMP0038-NEW-result.txt b/Tests/RunCMake/CMP0038/CMP0038-NEW-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMP0038/CMP0038-NEW-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0038/CMP0038-NEW-stderr.txt b/Tests/RunCMake/CMP0038/CMP0038-NEW-stderr.txt new file mode 100644 index 0000000..3d0a428 --- /dev/null +++ b/Tests/RunCMake/CMP0038/CMP0038-NEW-stderr.txt @@ -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\) diff --git a/Tests/RunCMake/CMP0038/CMP0038-NEW.cmake b/Tests/RunCMake/CMP0038/CMP0038-NEW.cmake new file mode 100644 index 0000000..6296b83 --- /dev/null +++ b/Tests/RunCMake/CMP0038/CMP0038-NEW.cmake @@ -0,0 +1,4 @@ + +cmake_policy(SET CMP0038 NEW) +add_library(self_link empty.cpp) +target_link_libraries(self_link self_link) diff --git a/Tests/RunCMake/CMP0038/CMP0038-OLD-result.txt b/Tests/RunCMake/CMP0038/CMP0038-OLD-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CMP0038/CMP0038-OLD-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0038/CMP0038-OLD-stderr.txt b/Tests/RunCMake/CMP0038/CMP0038-OLD-stderr.txt new file mode 100644 index 0000000..10f3293 --- /dev/null +++ b/Tests/RunCMake/CMP0038/CMP0038-OLD-stderr.txt @@ -0,0 +1 @@ +^$ diff --git a/Tests/RunCMake/CMP0038/CMP0038-OLD.cmake b/Tests/RunCMake/CMP0038/CMP0038-OLD.cmake new file mode 100644 index 0000000..3752821 --- /dev/null +++ b/Tests/RunCMake/CMP0038/CMP0038-OLD.cmake @@ -0,0 +1,4 @@ + +cmake_policy(SET CMP0038 OLD) +add_library(self_link empty.cpp) +target_link_libraries(self_link self_link) diff --git a/Tests/RunCMake/CMP0038/CMP0038-WARN-result.txt b/Tests/RunCMake/CMP0038/CMP0038-WARN-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CMP0038/CMP0038-WARN-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0038/CMP0038-WARN-stderr.txt b/Tests/RunCMake/CMP0038/CMP0038-WARN-stderr.txt new file mode 100644 index 0000000..64631e7 --- /dev/null +++ b/Tests/RunCMake/CMP0038/CMP0038-WARN-stderr.txt @@ -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. diff --git a/Tests/RunCMake/CMP0038/CMP0038-WARN.cmake b/Tests/RunCMake/CMP0038/CMP0038-WARN.cmake new file mode 100644 index 0000000..5b92d09 --- /dev/null +++ b/Tests/RunCMake/CMP0038/CMP0038-WARN.cmake @@ -0,0 +1,3 @@ + +add_library(self_link empty.cpp) +target_link_libraries(self_link self_link) diff --git a/Tests/RunCMake/CMP0038/CMakeLists.txt b/Tests/RunCMake/CMP0038/CMakeLists.txt new file mode 100644 index 0000000..2f10cb0 --- /dev/null +++ b/Tests/RunCMake/CMP0038/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12) +project(${RunCMake_TEST} CXX) +include(${RunCMake_TEST}.cmake NO_POLICY_SCOPE) diff --git a/Tests/RunCMake/CMP0038/RunCMakeTest.cmake b/Tests/RunCMake/CMP0038/RunCMakeTest.cmake new file mode 100644 index 0000000..fc3500a --- /dev/null +++ b/Tests/RunCMake/CMP0038/RunCMakeTest.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +run_cmake(CMP0038-WARN) +run_cmake(CMP0038-NEW) +run_cmake(CMP0038-OLD) diff --git a/Tests/RunCMake/CMP0038/empty.cpp b/Tests/RunCMake/CMP0038/empty.cpp new file mode 100644 index 0000000..bfbbdde --- /dev/null +++ b/Tests/RunCMake/CMP0038/empty.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty() +{ + return 0; +} diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index a1467d0..5c4ac7d 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -59,6 +59,7 @@ add_RunCMake_test(CMP0028) if (NOT "${CMAKE_TEST_GENERATOR}" MATCHES "(MSYS|MinGW|NMake|Borland) Makefiles") add_RunCMake_test(CMP0037) endif() +add_RunCMake_test(CMP0038) add_RunCMake_test(CTest) if(UNIX AND "${CMAKE_TEST_GENERATOR}" MATCHES "Unix Makefiles") add_RunCMake_test(CompilerChange) -- cgit v0.12