mirror of
https://github.com/reactos/CMake.git
synced 2024-11-28 05:50:42 +00:00
Genex: Add $<TARGET_GENEX_EVAL:...> and $<GENEX_EVAL:...>
Fixes: #17884
This commit is contained in:
parent
1f372ac4e5
commit
4d15046edd
@ -305,3 +305,42 @@ Available output expressions are:
|
||||
Content of ``...`` converted to shell path style. For example, slashes are
|
||||
converted to backslashes in Windows shells and drive letters are converted
|
||||
to posix paths in MSYS shells. The ``...`` must be an absolute path.
|
||||
``$<GENEX_EVAL:...>``
|
||||
Content of ``...`` evaluated as a generator expression in the current
|
||||
context. This enables consumption of generator expressions
|
||||
whose evaluation results itself in generator expressions.
|
||||
``$<TARGET_GENEX_EVAL:tgt,...>``
|
||||
Content of ``...`` evaluated as a generator expression in the context of
|
||||
``tgt`` target. This enables consumption of custom target properties that
|
||||
themselves contain generator expressions.
|
||||
|
||||
Having the capability to evaluate generator expressions is very useful when
|
||||
you want to manage custom properties supporting generator expressions.
|
||||
For example:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
add_library(foo ...)
|
||||
|
||||
set_property(TARGET foo PROPERTY
|
||||
CUSTOM_KEYS $<$<CONFIG:DEBUG>:FOO_EXTRA_THINGS>
|
||||
)
|
||||
|
||||
add_custom_target(printFooKeys
|
||||
COMMAND ${CMAKE_COMMAND} -E echo $<TARGET_PROPERTY:foo,CUSTOM_KEYS>
|
||||
)
|
||||
|
||||
This naive implementation of the ``printFooKeys`` custom command is wrong
|
||||
because ``CUSTOM_KEYS`` target property is not evaluated and the content
|
||||
is passed as is (i.e. ``$<$<CONFIG:DEBUG>:FOO_EXTRA_THINGS>``).
|
||||
|
||||
To have the expected result (i.e. ``FOO_EXTRA_THINGS`` if config is
|
||||
``Debug``), it is required to evaluate the output of
|
||||
``$<TARGET_PROPERTY:foo,CUSTOM_KEYS>``:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
add_custom_target(printFooKeys
|
||||
COMMAND ${CMAKE_COMMAND} -E
|
||||
echo $<TARGET_GENEX_EVAL:foo,$<TARGET_PROPERTY:foo,CUSTOM_KEYS>>
|
||||
)
|
||||
|
7
Help/release/dev/genex-GENEX_EVAL.rst
Normal file
7
Help/release/dev/genex-GENEX_EVAL.rst
Normal file
@ -0,0 +1,7 @@
|
||||
genex-GENEX_EVAL
|
||||
----------------
|
||||
|
||||
* New ``$<GENEX_EVAL:...>`` and ``$<TARGET_GENEX_EVAL:target,...>``
|
||||
:manual:`generator expression <cmake-generator-expressions(7)>`
|
||||
had been added to enable consumption of generator expressions whose
|
||||
evaluation results itself in generator expressions.
|
@ -154,6 +154,18 @@ bool cmGeneratorExpressionDAGChecker::GetTransitivePropertiesOnly()
|
||||
return top->TransitivePropertiesOnly;
|
||||
}
|
||||
|
||||
bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression()
|
||||
{
|
||||
const cmGeneratorExpressionDAGChecker* top = this;
|
||||
const cmGeneratorExpressionDAGChecker* parent = this->Parent;
|
||||
while (parent) {
|
||||
top = parent;
|
||||
parent = parent->Parent;
|
||||
}
|
||||
|
||||
return top->Property == "TARGET_GENEX_EVAL" || top->Property == "GENEX_EVAL";
|
||||
}
|
||||
|
||||
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char* tgt)
|
||||
{
|
||||
const cmGeneratorExpressionDAGChecker* top = this;
|
||||
|
@ -61,6 +61,7 @@ struct cmGeneratorExpressionDAGChecker
|
||||
void ReportError(cmGeneratorExpressionContext* context,
|
||||
const std::string& expr);
|
||||
|
||||
bool EvaluatingGenexExpression();
|
||||
bool EvaluatingLinkLibraries(const char* tgt = nullptr);
|
||||
|
||||
#define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const;
|
||||
|
@ -365,6 +365,113 @@ static const struct TargetNameIfExistsNode : public cmGeneratorExpressionNode
|
||||
}
|
||||
} targetNameIfExistsNode;
|
||||
|
||||
struct GenexEvaluator : public cmGeneratorExpressionNode
|
||||
{
|
||||
GenexEvaluator() {}
|
||||
|
||||
protected:
|
||||
std::string EvaluateExpression(
|
||||
const std::string& genexOperator, const std::string& expression,
|
||||
cmGeneratorExpressionContext* context,
|
||||
const GeneratorExpressionContent* content,
|
||||
cmGeneratorExpressionDAGChecker* dagCheckerParent) const
|
||||
{
|
||||
if (context->HeadTarget) {
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
context->Backtrace, context->HeadTarget->GetName(), genexOperator,
|
||||
content, dagCheckerParent);
|
||||
switch (dagChecker.Check()) {
|
||||
case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
|
||||
case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: {
|
||||
dagChecker.ReportError(context, content->GetOriginalExpression());
|
||||
return std::string();
|
||||
}
|
||||
case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
|
||||
case cmGeneratorExpressionDAGChecker::DAG:
|
||||
break;
|
||||
}
|
||||
|
||||
return this->EvaluateDependentExpression(
|
||||
expression, context->LG, context, context->HeadTarget,
|
||||
context->CurrentTarget, &dagChecker);
|
||||
}
|
||||
|
||||
return this->EvaluateDependentExpression(
|
||||
expression, context->LG, context, context->HeadTarget,
|
||||
context->CurrentTarget, dagCheckerParent);
|
||||
}
|
||||
};
|
||||
|
||||
static const struct TargetGenexEvalNode : public GenexEvaluator
|
||||
{
|
||||
TargetGenexEvalNode() {}
|
||||
|
||||
int NumExpectedParameters() const override { return 2; }
|
||||
|
||||
bool AcceptsArbitraryContentParameter() const override { return true; }
|
||||
|
||||
std::string Evaluate(
|
||||
const std::vector<std::string>& parameters,
|
||||
cmGeneratorExpressionContext* context,
|
||||
const GeneratorExpressionContent* content,
|
||||
cmGeneratorExpressionDAGChecker* dagCheckerParent) const override
|
||||
{
|
||||
const std::string& targetName = parameters.front();
|
||||
if (targetName.empty() ||
|
||||
!cmGeneratorExpression::IsValidTargetName(targetName)) {
|
||||
reportError(context, content->GetOriginalExpression(),
|
||||
"$<TARGET_GENEX_EVAL:tgt, ...> expression requires a "
|
||||
"non-empty valid target name.");
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const auto* target = context->LG->FindGeneratorTargetToUse(targetName);
|
||||
if (!target) {
|
||||
std::ostringstream e;
|
||||
e << "$<TARGET_GENEX_EVAL:tgt, ...> target \"" << targetName
|
||||
<< "\" not found.";
|
||||
reportError(context, content->GetOriginalExpression(), e.str());
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::string& expression = parameters[1];
|
||||
if (expression.empty()) {
|
||||
return expression;
|
||||
}
|
||||
|
||||
cmGeneratorExpressionContext targetContext(
|
||||
context->LG, context->Config, context->Quiet, target, target,
|
||||
context->EvaluateForBuildsystem, context->Backtrace, context->Language);
|
||||
|
||||
return this->EvaluateExpression("TARGET_GENEX_EVAL", expression,
|
||||
&targetContext, content, dagCheckerParent);
|
||||
}
|
||||
} targetGenexEvalNode;
|
||||
|
||||
static const struct GenexEvalNode : public GenexEvaluator
|
||||
{
|
||||
GenexEvalNode() {}
|
||||
|
||||
int NumExpectedParameters() const override { return 1; }
|
||||
|
||||
bool AcceptsArbitraryContentParameter() const override { return true; }
|
||||
|
||||
std::string Evaluate(
|
||||
const std::vector<std::string>& parameters,
|
||||
cmGeneratorExpressionContext* context,
|
||||
const GeneratorExpressionContent* content,
|
||||
cmGeneratorExpressionDAGChecker* dagCheckerParent) const override
|
||||
{
|
||||
const std::string& expression = parameters[0];
|
||||
if (expression.empty()) {
|
||||
return expression;
|
||||
}
|
||||
|
||||
return this->EvaluateExpression("GENEX_EVAL", expression, context, content,
|
||||
dagCheckerParent);
|
||||
}
|
||||
} genexEvalNode;
|
||||
|
||||
static const struct LowerCaseNode : public cmGeneratorExpressionNode
|
||||
{
|
||||
LowerCaseNode() {}
|
||||
@ -1124,7 +1231,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||
const char* prop = target->GetProperty(propertyName);
|
||||
|
||||
if (dagCheckerParent) {
|
||||
if (dagCheckerParent->EvaluatingLinkLibraries()) {
|
||||
if (dagCheckerParent->EvaluatingGenexExpression()) {
|
||||
// No check required.
|
||||
} else if (dagCheckerParent->EvaluatingLinkLibraries()) {
|
||||
#define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \
|
||||
(#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) ||
|
||||
if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(
|
||||
@ -1933,6 +2042,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
|
||||
nodeMap["TARGET_POLICY"] = &targetPolicyNode;
|
||||
nodeMap["TARGET_EXISTS"] = &targetExistsNode;
|
||||
nodeMap["TARGET_NAME_IF_EXISTS"] = &targetNameIfExistsNode;
|
||||
nodeMap["TARGET_GENEX_EVAL"] = &targetGenexEvalNode;
|
||||
nodeMap["GENEX_EVAL"] = &genexEvalNode;
|
||||
nodeMap["BUILD_INTERFACE"] = &buildInterfaceNode;
|
||||
nodeMap["INSTALL_INTERFACE"] = &installInterfaceNode;
|
||||
nodeMap["INSTALL_PREFIX"] = &installPrefixNode;
|
||||
|
@ -0,0 +1,6 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/GENEX_EVAL-generated.txt" content)
|
||||
|
||||
set(expected "BEFORE_PROPERTY1_AFTER")
|
||||
if(NOT content STREQUAL expected)
|
||||
set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
|
||||
endif()
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,26 @@
|
||||
^CMake Error at GENEX_EVAL-recursion1.cmake:7 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<GENEX_EVAL:\$<TARGET_PROPERTY:CUSTOM_PROPERTY>>
|
||||
|
||||
Dependency loop found.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
|
||||
|
||||
CMake Error at GENEX_EVAL-recursion1.cmake:7 \(add_custom_target\):
|
||||
Loop step 1
|
||||
|
||||
\$<GENEX_EVAL:\$<TARGET_PROPERTY:CUSTOM_PROPERTY>>
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
|
||||
|
||||
CMake Error at GENEX_EVAL-recursion1.cmake:7 \(add_custom_target\):
|
||||
Loop step 2
|
||||
|
||||
\$<TARGET_GENEX_EVAL:recursion,\$<TARGET_PROPERTY:recursion,CUSTOM_PROPERTY>>
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,9 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
add_library (recursion SHARED empty.c)
|
||||
set_property (TARGET recursion PROPERTY CUSTOM_PROPERTY "$<GENEX_EVAL:$<TARGET_PROPERTY:CUSTOM_PROPERTY>>")
|
||||
|
||||
add_custom_target (drive
|
||||
COMMAND echo "$<TARGET_GENEX_EVAL:recursion,$<TARGET_PROPERTY:recursion,CUSTOM_PROPERTY>>"
|
||||
DEPENDS recursion)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,26 @@
|
||||
^CMake Error at GENEX_EVAL-recursion2.cmake:8 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<GENEX_EVAL:\$<TARGET_PROPERTY:CUSTOM_PROPERTY1>>
|
||||
|
||||
Dependency loop found.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
|
||||
|
||||
CMake Error at GENEX_EVAL-recursion2.cmake:8 \(add_custom_target\):
|
||||
Loop step 1
|
||||
|
||||
\$<GENEX_EVAL:\$<TARGET_PROPERTY:CUSTOM_PROPERTY2>>
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
|
||||
|
||||
CMake Error at GENEX_EVAL-recursion2.cmake:8 \(add_custom_target\):
|
||||
Loop step 2
|
||||
|
||||
\$<TARGET_GENEX_EVAL:recursion,\$<TARGET_PROPERTY:recursion,CUSTOM_PROPERTY1>>
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,10 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
add_library(recursion SHARED empty.c)
|
||||
set_property (TARGET recursion PROPERTY CUSTOM_PROPERTY1 "$<GENEX_EVAL:$<TARGET_PROPERTY:CUSTOM_PROPERTY2>>")
|
||||
set_property (TARGET recursion PROPERTY CUSTOM_PROPERTY2 "$<GENEX_EVAL:$<TARGET_PROPERTY:CUSTOM_PROPERTY1>>")
|
||||
|
||||
add_custom_target (drive
|
||||
COMMAND echo "$<TARGET_GENEX_EVAL:recursion,$<TARGET_PROPERTY:recursion,CUSTOM_PROPERTY1>>"
|
||||
DEPENDS recursion)
|
11
Tests/RunCMake/GeneratorExpression/GENEX_EVAL.cmake
Normal file
11
Tests/RunCMake/GeneratorExpression/GENEX_EVAL.cmake
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
cmake_policy(VERSION 3.11)
|
||||
|
||||
enable_language(C)
|
||||
|
||||
add_library (example SHARED empty.c)
|
||||
set_property (TARGET example PROPERTY CUSTOM_PROPERTY1 "PROPERTY1")
|
||||
set_property (TARGET example PROPERTY CUSTOM_PROPERTY2 "$<TARGET_PROPERTY:CUSTOM_PROPERTY1>")
|
||||
set_property (TARGET example PROPERTY CUSTOM_PROPERTY3 "$<GENEX_EVAL:BEFORE_$<TARGET_PROPERTY:CUSTOM_PROPERTY2>_AFTER>")
|
||||
|
||||
file(GENERATE OUTPUT "GENEX_EVAL-generated.txt" CONTENT "$<TARGET_GENEX_EVAL:example,$<TARGET_PROPERTY:example,CUSTOM_PROPERTY3>>")
|
@ -42,6 +42,15 @@ run_cmake(TARGET_NAME_IF_EXISTS-no-arg)
|
||||
run_cmake(TARGET_NAME_IF_EXISTS-empty-arg)
|
||||
run_cmake(TARGET_NAME_IF_EXISTS)
|
||||
run_cmake(TARGET_NAME_IF_EXISTS-not-a-target)
|
||||
run_cmake(TARGET_GENEX_EVAL-no-arg)
|
||||
run_cmake(TARGET_GENEX_EVAL-no-target)
|
||||
run_cmake(TARGET_GENEX_EVAL-non-valid-target)
|
||||
run_cmake(TARGET_GENEX_EVAL-recursion1)
|
||||
run_cmake(TARGET_GENEX_EVAL-recursion2)
|
||||
run_cmake(TARGET_GENEX_EVAL)
|
||||
run_cmake(GENEX_EVAL-recursion1)
|
||||
run_cmake(GENEX_EVAL-recursion2)
|
||||
run_cmake(GENEX_EVAL)
|
||||
|
||||
run_cmake(ImportedTarget-TARGET_BUNDLE_DIR)
|
||||
run_cmake(ImportedTarget-TARGET_BUNDLE_CONTENT_DIR)
|
||||
|
@ -0,0 +1,6 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/TARGET_GENEX_EVAL-generated.txt" content)
|
||||
|
||||
set(expected "BEFORE_PROPERTY1_AFTER")
|
||||
if(NOT content STREQUAL expected)
|
||||
set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
|
||||
endif()
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
^CMake Error at TARGET_GENEX_EVAL-no-arg.cmake:4 \(add_custom_command\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<TARGET_GENEX_EVAL:>
|
||||
|
||||
\$<TARGET_GENEX_EVAL> expression requires 2 comma separated parameters, but
|
||||
got 1 instead.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,7 @@
|
||||
|
||||
cmake_policy(VERSION 3.11)
|
||||
|
||||
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c"
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.c" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<TARGET_GENEX_EVAL:>.c"
|
||||
)
|
||||
add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c")
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
^CMake Error at TARGET_GENEX_EVAL-no-target.cmake:2 \(add_custom_command\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<TARGET_GENEX_EVAL:,>
|
||||
|
||||
\$<TARGET_GENEX_EVAL:tgt, ...> expression requires a non-empty valid target
|
||||
name.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,5 @@
|
||||
|
||||
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c"
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.c" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<TARGET_GENEX_EVAL:,>.c"
|
||||
)
|
||||
add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c")
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,8 @@
|
||||
^CMake Error at TARGET_GENEX_EVAL-non-valid-target.cmake:2 \(add_custom_command\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<TARGET_GENEX_EVAL:bad-target,>
|
||||
|
||||
\$<TARGET_GENEX_EVAL:tgt, ...> target "bad-target" not found.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,5 @@
|
||||
|
||||
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c"
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.c" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<TARGET_GENEX_EVAL:bad-target,>.c"
|
||||
)
|
||||
add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c")
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
^CMake Error at TARGET_GENEX_EVAL-recursion1.cmake:7 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<TARGET_GENEX_EVAL:recursion,\$<TARGET_PROPERTY:CUSTOM_PROPERTY>>
|
||||
|
||||
Self reference on target "recursion".
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,9 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
add_library (recursion SHARED empty.c)
|
||||
set_property (TARGET recursion PROPERTY CUSTOM_PROPERTY "$<TARGET_GENEX_EVAL:recursion,$<TARGET_PROPERTY:CUSTOM_PROPERTY>>")
|
||||
|
||||
add_custom_target (drive
|
||||
COMMAND echo "$<TARGET_GENEX_EVAL:recursion,$<TARGET_PROPERTY:recursion,CUSTOM_PROPERTY>>"
|
||||
DEPENDS recursion)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,26 @@
|
||||
^CMake Error at TARGET_GENEX_EVAL-recursion2.cmake:10 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<TARGET_GENEX_EVAL:recursion1,\$<TARGET_PROPERTY:recursion1,CUSTOM_PROPERTY1>>
|
||||
|
||||
Dependency loop found.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
|
||||
|
||||
CMake Error at TARGET_GENEX_EVAL-recursion2.cmake:10 \(add_custom_target\):
|
||||
Loop step 1
|
||||
|
||||
\$<TARGET_GENEX_EVAL:recursion2,\$<TARGET_PROPERTY:recursion2,CUSTOM_PROPERTY2>>
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
|
||||
|
||||
CMake Error at TARGET_GENEX_EVAL-recursion2.cmake:10 \(add_custom_target\):
|
||||
Loop step 2
|
||||
|
||||
\$<TARGET_GENEX_EVAL:recursion1,\$<TARGET_PROPERTY:recursion1,CUSTOM_PROPERTY1>>
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,12 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
add_library (recursion1 SHARED empty.c)
|
||||
set_property (TARGET recursion1 PROPERTY CUSTOM_PROPERTY1 "$<TARGET_GENEX_EVAL:recursion2,$<TARGET_PROPERTY:recursion2,CUSTOM_PROPERTY2>>")
|
||||
|
||||
add_library (recursion2 SHARED empty.c)
|
||||
set_property (TARGET recursion2 PROPERTY CUSTOM_PROPERTY2 "$<TARGET_GENEX_EVAL:recursion1,$<TARGET_PROPERTY:recursion1,CUSTOM_PROPERTY1>>")
|
||||
|
||||
add_custom_target (drive
|
||||
COMMAND echo "$<TARGET_GENEX_EVAL:recursion1,$<TARGET_PROPERTY:recursion1,CUSTOM_PROPERTY1>>"
|
||||
DEPENDS recursion)
|
10
Tests/RunCMake/GeneratorExpression/TARGET_GENEX_EVAL.cmake
Normal file
10
Tests/RunCMake/GeneratorExpression/TARGET_GENEX_EVAL.cmake
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
cmake_policy(VERSION 3.11)
|
||||
|
||||
enable_language(C)
|
||||
|
||||
add_library (example SHARED empty.c)
|
||||
set_property (TARGET example PROPERTY CUSTOM_PROPERTY1 "PROPERTY1")
|
||||
set_property (TARGET example PROPERTY CUSTOM_PROPERTY2 "BEFORE_$<TARGET_PROPERTY:CUSTOM_PROPERTY1>_AFTER")
|
||||
|
||||
file(GENERATE OUTPUT "TARGET_GENEX_EVAL-generated.txt" CONTENT "$<TARGET_GENEX_EVAL:example,$<TARGET_PROPERTY:example,CUSTOM_PROPERTY2>>")
|
Loading…
Reference in New Issue
Block a user