genex: Add TARGET_NAME_IF_EXISTS expression

Define `$<TARGET_NAME_IF_EXISTS:tgt>` to mean `tgt` if the target
exists and otherwise an empty string.
This commit is contained in:
Alex Turbov 2018-03-27 04:57:44 +03:00 committed by Brad King
parent 6792c7787a
commit 7b173a2933
14 changed files with 87 additions and 0 deletions

View File

@ -274,6 +274,9 @@ Available output expressions are:
Marks ``...`` as being the name of a target. This is required if exporting
targets to multiple dependent export sets. The ``...`` must be a literal
name of a target- it may not contain generator expressions.
``$<TARGET_NAME_IF_EXISTS:...>``
Expands to the ``...`` if the given target exists, an empty string
otherwise.
``$<LINK_ONLY:...>``
Content of ``...`` except when evaluated in a link interface while
propagating :ref:`Target Usage Requirements`, in which case it is the

View File

@ -0,0 +1,6 @@
genex-TARGET_NAME_IF_EXISTS
---------------------------
* A new ``$<TARGET_NAME_IF_EXISTS:...>``
:manual:`generator expression <cmake-generator-expressions(7)>`
has been added.

View File

@ -331,6 +331,40 @@ static const struct TargetExistsNode : public cmGeneratorExpressionNode
}
} targetExistsNode;
static const struct TargetNameIfExistsNode : public cmGeneratorExpressionNode
{
TargetNameIfExistsNode() {}
int NumExpectedParameters() const override { return 1; }
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
if (parameters.size() != 1) {
reportError(context, content->GetOriginalExpression(),
"$<TARGET_NAME_IF_EXISTS:...> expression requires one "
"parameter");
return std::string();
}
std::string targetName = parameters.front();
if (targetName.empty() ||
!cmGeneratorExpression::IsValidTargetName(targetName)) {
reportError(context, content->GetOriginalExpression(),
"$<TARGET_NAME_IF_EXISTS:tgt> expression requires a "
"non-empty valid target name.");
return std::string();
}
return context->LG->GetMakefile()->FindTargetToUse(targetName)
? targetName
: std::string();
}
} targetNameIfExistsNode;
static const struct LowerCaseNode : public cmGeneratorExpressionNode
{
LowerCaseNode() {}
@ -1897,6 +1931,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
nodeMap["TARGET_OBJECTS"] = &targetObjectsNode;
nodeMap["TARGET_POLICY"] = &targetPolicyNode;
nodeMap["TARGET_EXISTS"] = &targetExistsNode;
nodeMap["TARGET_NAME_IF_EXISTS"] = &targetNameIfExistsNode;
nodeMap["BUILD_INTERFACE"] = &buildInterfaceNode;
nodeMap["INSTALL_INTERFACE"] = &installInterfaceNode;
nodeMap["INSTALL_PREFIX"] = &installPrefixNode;

View File

@ -38,6 +38,10 @@ run_cmake(TARGET_EXISTS-no-arg)
run_cmake(TARGET_EXISTS-empty-arg)
run_cmake(TARGET_EXISTS)
run_cmake(TARGET_EXISTS-not-a-target)
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(ImportedTarget-TARGET_BUNDLE_DIR)
run_cmake(ImportedTarget-TARGET_BUNDLE_CONTENT_DIR)

View File

@ -0,0 +1,6 @@
file(READ "${RunCMake_TEST_BINARY_DIR}/TARGET_NAME_IF_EXISTS-generated.txt" content)
set(expected "foo")
if(NOT content STREQUAL expected)
set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
endif()

View File

@ -0,0 +1,9 @@
CMake Error at TARGET_NAME_IF_EXISTS-empty-arg.cmake:2 \(file\):
Error evaluating generator expression:
\$<TARGET_NAME_IF_EXISTS:>
\$<TARGET_NAME_IF_EXISTS:tgt> expression requires a non-empty valid target
name.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)

View File

@ -0,0 +1,2 @@
cmake_policy(SET CMP0070 NEW)
file(GENERATE OUTPUT TARGET_NAME_IF_EXISTS-generated.txt CONTENT "$<TARGET_NAME_IF_EXISTS:${empty}>")

View File

@ -0,0 +1,8 @@
CMake Error at TARGET_NAME_IF_EXISTS-no-arg.cmake:2 \(file\):
Error evaluating generator expression:
\$<TARGET_NAME_IF_EXISTS>
\$<TARGET_NAME_IF_EXISTS> expression requires exactly one parameter.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)

View File

@ -0,0 +1,2 @@
cmake_policy(SET CMP0070 NEW)
file(GENERATE OUTPUT TARGET_NAME_IF_EXISTS-generated.txt CONTENT "$<TARGET_NAME_IF_EXISTS>")

View File

@ -0,0 +1,5 @@
file(READ "${RunCMake_TEST_BINARY_DIR}/TARGET_NAME_IF_EXISTS-not-a-target-generated.txt" content)
if(content)
set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected an empty string")
endif()

View File

@ -0,0 +1,2 @@
cmake_policy(SET CMP0070 NEW)
file(GENERATE OUTPUT TARGET_NAME_IF_EXISTS-not-a-target-generated.txt CONTENT "$<TARGET_NAME_IF_EXISTS:just-random-string>")

View File

@ -0,0 +1,3 @@
cmake_policy(SET CMP0070 NEW)
add_custom_target(foo)
file(GENERATE OUTPUT TARGET_NAME_IF_EXISTS-generated.txt CONTENT "$<TARGET_NAME_IF_EXISTS:foo>")