diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 4bee05e90..891333ceb 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -97,3 +97,4 @@ All Policies /policy/CMP0043 /policy/CMP0044 /policy/CMP0045 + /policy/CMP0046 diff --git a/Help/policy/CMP0046.rst b/Help/policy/CMP0046.rst new file mode 100644 index 000000000..5192dc7b8 --- /dev/null +++ b/Help/policy/CMP0046.rst @@ -0,0 +1,17 @@ +CMP0046 +------- + +Error on non-existent dependency in add_dependencies. + +CMake 2.8.12 and lower silently ignored non-existent dependencies +listed in the :command:`add_dependencies` command. + +The OLD behavior for this policy is to silently ignore non-existent +dependencies. The NEW behavior for this policy is to report an error +if non-existent dependencies are listed in the :command:`add_dependencies` +command. + +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/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx index 87bfb3cc1..a7ffded2b 100644 --- a/Source/cmAddDependenciesCommand.cxx +++ b/Source/cmAddDependenciesCommand.cxx @@ -46,7 +46,7 @@ bool cmAddDependenciesCommand ++s; // skip over target_name for (; s != args.end(); ++s) { - target->AddUtility(s->c_str()); + target->AddUtility(s->c_str(), this->Makefile); } } else diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 73a8e2787..a848e4faf 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -343,6 +343,45 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, cmTarget const* dependee = depender->GetMakefile()->FindTargetToUse(dependee_name); + if(!dependee && !linking && + (depender->GetType() != cmTarget::GLOBAL_TARGET)) + { + cmMakefile *makefile = depender->GetMakefile(); + cmake::MessageType messageType = cmake::AUTHOR_WARNING; + bool issueMessage = false; + switch(makefile->GetPolicyStatus(cmPolicies::CMP0046)) + { + case cmPolicies::WARN: + issueMessage = true; + case cmPolicies::OLD: + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + issueMessage = true; + messageType = cmake::FATAL_ERROR; + } + if(issueMessage) + { + cmake* cm = this->GlobalGenerator->GetCMakeInstance(); + cmOStringStream e; + e << (makefile->GetPolicies() + ->GetPolicyWarning(cmPolicies::CMP0046)) << "\n"; + e << "The dependency target \"" << dependee_name + << "\" of target \"" << depender->GetName() << "\" does not exist."; + + cmListFileBacktrace nullBacktrace; + cmListFileBacktrace const* backtrace = + depender->GetUtilityBacktrace(dependee_name); + if(!backtrace) + { + backtrace = &nullBacktrace; + } + + cm->IssueMessage(messageType, e.str(), *backtrace); + } + } + // Skip targets that will not really be linked. This is probably a // name conflict between an external library and an executable // within the project. diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 5a189f8c1..020a782a1 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -331,6 +331,11 @@ cmPolicies::cmPolicies() CMP0045, "CMP0045", "Error on non-existent target in get_target_property.", 3,0,0,0, cmPolicies::WARN); + + this->DefinePolicy( + CMP0046, "CMP0046", + "Error on non-existent dependency in add_dependencies.", + 3,0,0,0, cmPolicies::WARN); } cmPolicies::~cmPolicies() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index b1342bfbb..38f47f1c5 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -99,6 +99,7 @@ public: CMP0043, ///< Ignore COMPILE_DEFINITIONS_ properties CMP0044, ///< Case sensitive _COMPILER_ID generator expressions CMP0045, ///< Error on non-existent target in get_target_property + CMP0046, ///< Error on non-existent dependency in add_dependencies /** \brief Always the last entry. * diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 4828d201d..24fa0c519 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -401,6 +401,26 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->SetPropertyDefault("JOB_POOL_LINK", 0); } +//---------------------------------------------------------------------------- +void cmTarget::AddUtility(const char *u, cmMakefile *makefile) +{ + this->Utilities.insert(u); + if(makefile) + { + makefile->GetBacktrace(UtilityBacktraces[u]); + } +} + +//---------------------------------------------------------------------------- +cmListFileBacktrace const* cmTarget::GetUtilityBacktrace(const char *u) const +{ + std::map::const_iterator i = + this->UtilityBacktraces.find(u); + if(i == this->UtilityBacktraces.end()) return 0; + + return &i->second; +} + //---------------------------------------------------------------------------- void cmTarget::FinishConfigure() { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 26d391f8c..ce0d81223 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -242,9 +242,10 @@ public: * name as would be specified to the ADD_EXECUTABLE or UTILITY_SOURCE * commands. It is not a full path nor does it have an extension. */ - void AddUtility(const char* u) { this->Utilities.insert(u);} + void AddUtility(const char* u, cmMakefile *makefile = 0); ///! Get the utilities used by this target std::setconst& GetUtilities() const { return this->Utilities; } + cmListFileBacktrace const* GetUtilityBacktrace(const char* u) const; /** Finalize the target at the end of the Configure step. */ void FinishConfigure(); @@ -691,6 +692,7 @@ private: std::string RuntimeInstallPath; mutable std::string ExportMacro; std::set Utilities; + std::map UtilityBacktraces; bool RecordDependencies; mutable cmPropertyMap Properties; LinkLibraryVectorType OriginalLinkLibraries; diff --git a/Tests/RunCMake/CMP0046/CMP0046-NEW-existing-dependency-stderr.txt b/Tests/RunCMake/CMP0046/CMP0046-NEW-existing-dependency-stderr.txt new file mode 100644 index 000000000..10f32932e --- /dev/null +++ b/Tests/RunCMake/CMP0046/CMP0046-NEW-existing-dependency-stderr.txt @@ -0,0 +1 @@ +^$ diff --git a/Tests/RunCMake/CMP0046/CMP0046-NEW-existing-dependency.cmake b/Tests/RunCMake/CMP0046/CMP0046-NEW-existing-dependency.cmake new file mode 100644 index 000000000..0be290a8d --- /dev/null +++ b/Tests/RunCMake/CMP0046/CMP0046-NEW-existing-dependency.cmake @@ -0,0 +1,5 @@ +cmake_policy(SET CMP0046 NEW) + +add_custom_target(foo) +add_custom_target(bar) +add_dependencies(foo bar) diff --git a/Tests/RunCMake/CMP0046/CMP0046-NEW-missing-dependency-result.txt b/Tests/RunCMake/CMP0046/CMP0046-NEW-missing-dependency-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/CMP0046/CMP0046-NEW-missing-dependency-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0046/CMP0046-NEW-missing-dependency-stderr.txt b/Tests/RunCMake/CMP0046/CMP0046-NEW-missing-dependency-stderr.txt new file mode 100644 index 000000000..0c23c43e0 --- /dev/null +++ b/Tests/RunCMake/CMP0046/CMP0046-NEW-missing-dependency-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at CMP0046-NEW-missing-dependency.cmake:4 \(add_dependencies\): + Policy CMP0046 is not set: Error on non-existent dependency in + add_dependencies. Run "cmake --help-policy CMP0046" for policy details. + Use the cmake_policy command to set the policy and suppress this warning. ++ + The dependency target "bar" of target "foo" does not exist. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/CMP0046/CMP0046-NEW-missing-dependency.cmake b/Tests/RunCMake/CMP0046/CMP0046-NEW-missing-dependency.cmake new file mode 100644 index 000000000..9bb6b90c8 --- /dev/null +++ b/Tests/RunCMake/CMP0046/CMP0046-NEW-missing-dependency.cmake @@ -0,0 +1,4 @@ +cmake_policy(SET CMP0046 NEW) + +add_custom_target(foo) +add_dependencies(foo bar) diff --git a/Tests/RunCMake/CMP0046/CMP0046-OLD-existing-dependency-stderr.txt b/Tests/RunCMake/CMP0046/CMP0046-OLD-existing-dependency-stderr.txt new file mode 100644 index 000000000..10f32932e --- /dev/null +++ b/Tests/RunCMake/CMP0046/CMP0046-OLD-existing-dependency-stderr.txt @@ -0,0 +1 @@ +^$ diff --git a/Tests/RunCMake/CMP0046/CMP0046-OLD-existing-dependency.cmake b/Tests/RunCMake/CMP0046/CMP0046-OLD-existing-dependency.cmake new file mode 100644 index 000000000..b22ab4fb9 --- /dev/null +++ b/Tests/RunCMake/CMP0046/CMP0046-OLD-existing-dependency.cmake @@ -0,0 +1,5 @@ +cmake_policy(SET CMP0046 OLD) + +add_custom_target(foo) +add_custom_target(bar) +add_dependencies(foo bar) diff --git a/Tests/RunCMake/CMP0046/CMP0046-OLD-missing-dependency-stderr.txt b/Tests/RunCMake/CMP0046/CMP0046-OLD-missing-dependency-stderr.txt new file mode 100644 index 000000000..10f32932e --- /dev/null +++ b/Tests/RunCMake/CMP0046/CMP0046-OLD-missing-dependency-stderr.txt @@ -0,0 +1 @@ +^$ diff --git a/Tests/RunCMake/CMP0046/CMP0046-OLD-missing-dependency.cmake b/Tests/RunCMake/CMP0046/CMP0046-OLD-missing-dependency.cmake new file mode 100644 index 000000000..5ee3cb75e --- /dev/null +++ b/Tests/RunCMake/CMP0046/CMP0046-OLD-missing-dependency.cmake @@ -0,0 +1,4 @@ +cmake_policy(SET CMP0046 OLD) + +add_custom_target(foo) +add_dependencies(foo bar) diff --git a/Tests/RunCMake/CMP0046/CMP0046-WARN-missing-dependency-stderr.txt b/Tests/RunCMake/CMP0046/CMP0046-WARN-missing-dependency-stderr.txt new file mode 100644 index 000000000..fed36f16e --- /dev/null +++ b/Tests/RunCMake/CMP0046/CMP0046-WARN-missing-dependency-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMP0046-WARN-missing-dependency.cmake:2 \(add_dependencies\): + Policy CMP0046 is not set: Error on non-existent dependency in + add_dependencies. Run "cmake --help-policy CMP0046" for policy details. + Use the cmake_policy command to set the policy and suppress this warning. ++ + The dependency target "bar" of target "foo" does not exist. +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/CMP0046/CMP0046-WARN-missing-dependency.cmake b/Tests/RunCMake/CMP0046/CMP0046-WARN-missing-dependency.cmake new file mode 100644 index 000000000..896fa40f6 --- /dev/null +++ b/Tests/RunCMake/CMP0046/CMP0046-WARN-missing-dependency.cmake @@ -0,0 +1,2 @@ +add_custom_target(foo) +add_dependencies(foo bar) diff --git a/Tests/RunCMake/CMP0046/CMakeLists.txt b/Tests/RunCMake/CMP0046/CMakeLists.txt new file mode 100644 index 000000000..2f10cb092 --- /dev/null +++ b/Tests/RunCMake/CMP0046/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/CMP0046/RunCMakeTest.cmake b/Tests/RunCMake/CMP0046/RunCMakeTest.cmake new file mode 100644 index 000000000..5131e5b23 --- /dev/null +++ b/Tests/RunCMake/CMP0046/RunCMakeTest.cmake @@ -0,0 +1,8 @@ +include(RunCMake) + +run_cmake(CMP0046-OLD-missing-dependency) +run_cmake(CMP0046-NEW-missing-dependency) +run_cmake(CMP0046-WARN-missing-dependency) + +run_cmake(CMP0046-OLD-existing-dependency) +run_cmake(CMP0046-NEW-existing-dependency) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 77700d786..1c23bcd60 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -66,6 +66,7 @@ if(CMAKE_SYSTEM_NAME MATCHES Darwin AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG) endif() add_RunCMake_test(CMP0043) add_RunCMake_test(CMP0045) +add_RunCMake_test(CMP0046) add_RunCMake_test(CTest) if(UNIX AND "${CMAKE_TEST_GENERATOR}" MATCHES "Unix Makefiles") add_RunCMake_test(CompilerChange)