diff --git a/Help/command/if.rst b/Help/command/if.rst index 0956a1c11e..9dd7358ba9 100644 --- a/Help/command/if.rst +++ b/Help/command/if.rst @@ -44,8 +44,8 @@ Compound conditions are evaluated in the following order of precedence: 2. Unary tests such as: * The `Existence Checks`_ :cref:`COMMAND`, :cref:`DEFINED`, - :cref:`DIAGNOSTIC`, :cref:`EXISTS`, :cref:`POLICY`, :cref:`TARGET`, and - :cref:`TEST`. + :cref:`DIAGNOSTIC`, :cref:`EXISTS`, :cref:`POLICY`, :cref:`RULE`, + :cref:`TARGET`, and :cref:`TEST`. * The `File Operations`_ :cref:`IS_READABLE`, :cref:`IS_WRITABLE`, :cref:`IS_EXECUTABLE`, :cref:`IS_DIRECTORY`, :cref:`IS_SYMLINK`, and :cref:`IS_ABSOLUTE`. @@ -142,6 +142,13 @@ Existence Checks True if the given name is an existing policy (of the form ``CMP``). +.. signature:: if(RULE ) + + .. versionadded:: 4.5 + + True if the given name is an existing rule created by a call to the + :command:`add_custom_rule` command and is visible in the current directory. + .. signature:: if(TARGET ) True if the given name is an existing logical target name created diff --git a/Help/release/dev/if-RULE-operator.rst b/Help/release/dev/if-RULE-operator.rst new file mode 100644 index 0000000000..296ac5d93c --- /dev/null +++ b/Help/release/dev/if-RULE-operator.rst @@ -0,0 +1,5 @@ +if-RULE-operator +---------------- + +* The :command:`if` command gained a ``RULE`` operator to check if a rule + exists. diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 325e3796de..122e4c0aca 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -53,6 +53,7 @@ auto const keyOR = "OR"_s; auto const keyParenL = "("_s; auto const keyParenR = ")"_s; auto const keyPOLICY = "POLICY"_s; +auto const keyRULE = "RULE"_s; auto const keySTREQUAL = "STREQUAL"_s; auto const keySTRGREATER = "STRGREATER"_s; auto const keySTRGREATER_EQUAL = "STRGREATER_EQUAL"_s; @@ -515,6 +516,12 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, newArgs.ReduceOneArg( cmPolicies::GetPolicyID(args.next->GetValue().c_str(), pid), args); } + // does a rule exist + else if (this->IsKeyword(keyRULE, *args.current)) { + newArgs.ReduceOneArg( + static_cast(this->Makefile.FindRuleToUse(args.next->GetValue())), + args); + } // does a target exist else if (this->IsKeyword(keyTARGET, *args.current)) { newArgs.ReduceOneArg(static_cast(this->Makefile.FindTargetToUse( diff --git a/Tests/RunCMake/CustomRule/ExistenceCheck.cmake b/Tests/RunCMake/CustomRule/ExistenceCheck.cmake new file mode 100644 index 0000000000..a436a44549 --- /dev/null +++ b/Tests/RunCMake/CustomRule/ExistenceCheck.cmake @@ -0,0 +1,22 @@ + +enable_language(C) + +if(RULE foo) + message(SEND_ERROR "RULE 'foo' unexpectedly found") +endif() + +add_custom_rule(foo OUTPUT out COMMAND cmd) +if(NOT RULE foo) + message(SEND_ERROR "RULE 'foo' unexpectedly not found") +endif() + +add_library(foo) +add_subdirectory(subdir2) +if(RULE simple) + message(SEND_ERROR "RULE 'simple' from 'subdir2' unexpectedly found") +endif() + +add_subdirectory(subdir1) +if(NOT RULE simple) + message(SEND_ERROR "RULE 'simple' from 'subdir1' unexpectedly not found") +endif() diff --git a/Tests/RunCMake/CustomRule/RunCMakeTest.cmake b/Tests/RunCMake/CustomRule/RunCMakeTest.cmake index d6359a6008..42e2a6ca09 100644 --- a/Tests/RunCMake/CustomRule/RunCMakeTest.cmake +++ b/Tests/RunCMake/CustomRule/RunCMakeTest.cmake @@ -24,3 +24,5 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|MSVC|SunPro|XL|HP") run_configure_and_build(Configurators) run_configure_and_build(DerivedRule) endif() + +run_cmake(ExistenceCheck)