diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 1f575744d4..057dfb5d88 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -1449,6 +1449,19 @@ Configuration Expressions in ``...`` are evaluated using the custom command's "command config". With other generators, the content of ``...`` is evaluated normally. +Global Expressions +------------------ + +Global Properties +^^^^^^^^^^^^^^^^^ + +.. genex:: $ + + .. versionadded:: 4.5 + + Value of the global property ``prop``, or empty if + the property is not set. + Rule-Dependent Expressions -------------------------- diff --git a/Help/release/dev/GenEx-GLOBAL_PROPERTY.rst b/Help/release/dev/GenEx-GLOBAL_PROPERTY.rst new file mode 100644 index 0000000000..41c75c0651 --- /dev/null +++ b/Help/release/dev/GenEx-GLOBAL_PROPERTY.rst @@ -0,0 +1,5 @@ +GenEx-GLOBAL_PROPERTY +--------------------- + +* CMake gains the :genex:`GLOBAL_PROPERTY` generator expression to query + global properties. diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 51ebc560e7..5f8fe93788 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -4080,6 +4080,31 @@ static const struct DeviceLinkNode : public cmGeneratorExpressionNode } } deviceLinkNode; +static const struct GlobalPropertyNode : public cmGeneratorExpressionNode +{ + GlobalPropertyNode() {} // NOLINT(modernize-use-equals-default) + + // This node handles errors on parameter count itself. + int NumExpectedParameters() const override { return 1; } + + std::string Evaluate( + std::vector const& parameters, cm::GenEx::Evaluation* eval, + GeneratorExpressionContent const* content, + cmGeneratorExpressionDAGChecker* /*dagCheckerParent*/) const override + { + auto const& propertyName = parameters[0]; + + if (propertyName.empty()) { + reportError(eval, content->GetOriginalExpression(), + "$ expression requires a " + "non-empty property name."); + return std::string{}; + } + cmake* cm = eval->Context.LG->GetCMakeInstance(); + return cm->GetState()->GetGlobalProperty(propertyName); + } +} globalPropertyNode; + namespace { bool GetFileSet(std::vector const& parameters, cm::GenEx::Evaluation* eval, @@ -6538,6 +6563,7 @@ cmGeneratorExpressionNode const* cmGeneratorExpressionNode::GetNode( { "COMMA", &commaNode }, { "SEMICOLON", &semicolonNode }, { "QUOTE", "eNode }, + { "GLOBAL_PROPERTY", &globalPropertyNode }, { "RULE_PROPERTY", &rulePropertyNode }, { "SOURCE_EXISTS", &sourceExistsNode }, { "SOURCE_PROPERTY", &sourcePropertyNode }, diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 75f5fa8252..65fdcc3199 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -573,6 +573,7 @@ add_RunCMake_test(GenEx-LINK_GROUP) add_RunCMake_test(GenEx-TARGET_FILE -DLINKER_SUPPORTS_PDB=${LINKER_SUPPORTS_PDB}) add_RunCMake_test(GenEx-TARGET_IMPORT_FILE) add_RunCMake_test(GenEx-GENEX_EVAL) +add_RunCMake_test(GenEx-GLOBAL_PROPERTY) add_RunCMake_test(GenEx-RULE_PROPERTY) add_RunCMake_test(GenEx-SOURCE_EXISTS) add_RunCMake_test(GenEx-SOURCE_PROPERTY) diff --git a/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/CMakeLists.txt b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/CMakeLists.txt new file mode 100644 index 0000000000..7a948f9be7 --- /dev/null +++ b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 4.0...4.4) + +project(${RunCMake_TEST} NONE) + +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/GLOBAL_PROPERTY-check.cmake b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/GLOBAL_PROPERTY-check.cmake new file mode 100644 index 0000000000..89447da1f9 --- /dev/null +++ b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/GLOBAL_PROPERTY-check.cmake @@ -0,0 +1,5 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/GLOBAL_PROPERTY-generated.txt" content) + +if(NOT content MATCHES "ENABLED_LANGUAGES=C;CXX" OR NOT content MATCHES "DEBUG_CONFIGURATIONS=Debug;Foo") + set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected:\n [[ENABLED_LANGUAGES=C;CXX\nDEBUG_CONFIGURATIONS=Debug;Foo]]") +endif() diff --git a/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/GLOBAL_PROPERTY.cmake b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/GLOBAL_PROPERTY.cmake new file mode 100644 index 0000000000..b13f1e1a12 --- /dev/null +++ b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/GLOBAL_PROPERTY.cmake @@ -0,0 +1,7 @@ + +enable_language(C) +enable_language(CXX) + +set_property(GLOBAL PROPERTY DEBUG_CONFIGURATIONS Debug Foo) + +file(GENERATE OUTPUT GLOBAL_PROPERTY-generated.txt CONTENT "ENABLED_LANGUAGES=$\nDEBUG_CONFIGURATIONS=$\n") diff --git a/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/RunCMakeTest.cmake new file mode 100644 index 0000000000..f49d71bf54 --- /dev/null +++ b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/RunCMakeTest.cmake @@ -0,0 +1,6 @@ + +include(RunCMake) + +run_cmake(no-arguments) +run_cmake(no-property) +run_cmake(GLOBAL_PROPERTY) diff --git a/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-arguments-result.txt b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-arguments-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-arguments-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-arguments-stderr.txt b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-arguments-stderr.txt new file mode 100644 index 0000000000..574ccb5ac2 --- /dev/null +++ b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-arguments-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at no-arguments\.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$ + + \$ expression requires exactly one parameter\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-arguments.cmake b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-arguments.cmake new file mode 100644 index 0000000000..ab9793288e --- /dev/null +++ b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-arguments.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$") diff --git a/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-property-result.txt b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-property-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-property-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-property-stderr.txt b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-property-stderr.txt new file mode 100644 index 0000000000..38e429c85f --- /dev/null +++ b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-property-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at no-property\.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$ + + \$ expression requires a non-empty property name\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-property.cmake b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-property.cmake new file mode 100644 index 0000000000..5f29ca898a --- /dev/null +++ b/Tests/RunCMake/GenEx-GLOBAL_PROPERTY/no-property.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$")