mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-11 08:20:18 -06:00
Genex: Add policy to handle empty list items in $<IN_LIST:...>
The old behavior of $<IN_LIST:...> is inconsistent with that of if(IN_LIST), in that it does not find an empty search item even if the list contains empty items. This change adds a new policy to correctly handle empty items and make the behavior more consistent with if(IN_LIST). Fixes: #18556
This commit is contained in:
@@ -57,6 +57,7 @@ Policies Introduced by CMake 3.14
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
CMP0085: IN_LIST generator expression handles empty list items. </policy/CMP0085>
|
||||
CMP0084: The FindQt module does not exist for find_package(). </policy/CMP0084>
|
||||
CMP0083: Add PIE options when linking executable. </policy/CMP0083>
|
||||
CMP0082: Install rules from add_subdirectory() are interleaved with those in caller. </policy/CMP0082>
|
||||
|
||||
21
Help/policy/CMP0085.rst
Normal file
21
Help/policy/CMP0085.rst
Normal file
@@ -0,0 +1,21 @@
|
||||
CMP0085
|
||||
-------
|
||||
|
||||
``$<IN_LIST:...>`` handles empty list items.
|
||||
|
||||
In CMake 3.13 and lower, the ``$<IN_LIST:...>`` generator expression always
|
||||
returned ``0`` if the first argument was empty, even if the list contained an
|
||||
empty item. This behavior is inconsistent with the ``IN_LIST`` behavior of
|
||||
:command:`if`, which this generator expression is meant to emulate. CMake 3.14
|
||||
and later handles this case correctly.
|
||||
|
||||
The ``OLD`` behavior of this policy is for ``$<IN_LIST:...>`` to always return
|
||||
``0`` if the first argument is empty. The ``NEW`` behavior is to return ``1``
|
||||
if the first argument is empty and the list contains an empty item.
|
||||
|
||||
This policy was introduced in CMake version 3.14. CMake version
|
||||
|release| warns when the policy is not set and uses ``OLD`` behavior.
|
||||
Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW``
|
||||
explicitly.
|
||||
|
||||
.. include:: DEPRECATED.txt
|
||||
5
Help/release/dev/genex-in_list-empty-args.rst
Normal file
5
Help/release/dev/genex-in_list-empty-args.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
genex-in_list-empty-args
|
||||
------------------------
|
||||
|
||||
* The $<IN_LIST:...> generator expression now correctly handles an empty
|
||||
argument. See :policy:`CMP0085` for details.
|
||||
@@ -283,14 +283,39 @@ static const struct InListNode : public cmGeneratorExpressionNode
|
||||
|
||||
std::string Evaluate(
|
||||
const std::vector<std::string>& parameters,
|
||||
cmGeneratorExpressionContext* /*context*/,
|
||||
cmGeneratorExpressionContext* context,
|
||||
const GeneratorExpressionContent* /*content*/,
|
||||
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
|
||||
{
|
||||
std::vector<std::string> values;
|
||||
cmSystemTools::ExpandListArgument(parameters[1], values);
|
||||
if (values.empty()) {
|
||||
return "0";
|
||||
std::vector<std::string> values, checkValues;
|
||||
bool check = false;
|
||||
switch (context->LG->GetPolicyStatus(cmPolicies::CMP0085)) {
|
||||
case cmPolicies::WARN:
|
||||
if (parameters.front().empty()) {
|
||||
check = true;
|
||||
cmSystemTools::ExpandListArgument(parameters[1], checkValues, true);
|
||||
}
|
||||
CM_FALLTHROUGH;
|
||||
case cmPolicies::OLD:
|
||||
cmSystemTools::ExpandListArgument(parameters[1], values);
|
||||
if (check && values != checkValues) {
|
||||
std::ostringstream e;
|
||||
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0085)
|
||||
<< "\nSearch Item:\n \"" << parameters.front()
|
||||
<< "\"\nList:\n \"" << parameters[1] << "\"\n";
|
||||
context->LG->GetCMakeInstance()->IssueMessage(
|
||||
cmake::AUTHOR_WARNING, e.str(), context->Backtrace);
|
||||
return "0";
|
||||
}
|
||||
if (values.empty()) {
|
||||
return "0";
|
||||
}
|
||||
break;
|
||||
case cmPolicies::REQUIRED_IF_USED:
|
||||
case cmPolicies::REQUIRED_ALWAYS:
|
||||
case cmPolicies::NEW:
|
||||
cmSystemTools::ExpandListArgument(parameters[1], values, true);
|
||||
break;
|
||||
}
|
||||
|
||||
return std::find(values.cbegin(), values.cend(), parameters.front()) ==
|
||||
|
||||
@@ -249,7 +249,9 @@ class cmMakefile;
|
||||
0, cmPolicies::WARN) \
|
||||
SELECT(POLICY, CMP0084, \
|
||||
"The FindQt module does not exist for find_package().", 3, 14, 0, \
|
||||
cmPolicies::WARN)
|
||||
cmPolicies::WARN) \
|
||||
SELECT(POLICY, CMP0085, "$<IN_LIST:...> handles empty list items.", 3, 14, \
|
||||
0, cmPolicies::WARN)
|
||||
|
||||
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
|
||||
#define CM_FOR_EACH_POLICY_ID(POLICY) \
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/CMP0085-NEW-generated.txt" content)
|
||||
|
||||
set(expected "101011")
|
||||
if(NOT content STREQUAL expected)
|
||||
set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
|
||||
endif()
|
||||
4
Tests/RunCMake/GeneratorExpression/CMP0085-NEW.cmake
Normal file
4
Tests/RunCMake/GeneratorExpression/CMP0085-NEW.cmake
Normal file
@@ -0,0 +1,4 @@
|
||||
cmake_policy(SET CMP0070 NEW)
|
||||
file(GENERATE OUTPUT CMP0085-NEW-generated.txt CONTENT
|
||||
"$<IN_LIST:,>$<IN_LIST:,a>$<IN_LIST:,;a>$<IN_LIST:a,>$<IN_LIST:a,a>$<IN_LIST:a,;a>"
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/CMP0085-OLD-generated.txt" content)
|
||||
|
||||
set(expected "000011")
|
||||
if(NOT content STREQUAL expected)
|
||||
set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
|
||||
endif()
|
||||
4
Tests/RunCMake/GeneratorExpression/CMP0085-OLD.cmake
Normal file
4
Tests/RunCMake/GeneratorExpression/CMP0085-OLD.cmake
Normal file
@@ -0,0 +1,4 @@
|
||||
cmake_policy(SET CMP0070 NEW)
|
||||
file(GENERATE OUTPUT CMP0085-OLD-generated.txt CONTENT
|
||||
"$<IN_LIST:,>$<IN_LIST:,a>$<IN_LIST:,;a>$<IN_LIST:a,>$<IN_LIST:a,a>$<IN_LIST:a,;a>"
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/CMP0085-WARN-generated.txt" content)
|
||||
|
||||
set(expected "000011")
|
||||
if(NOT content STREQUAL expected)
|
||||
set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
|
||||
endif()
|
||||
33
Tests/RunCMake/GeneratorExpression/CMP0085-WARN-stderr.txt
Normal file
33
Tests/RunCMake/GeneratorExpression/CMP0085-WARN-stderr.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
CMake Warning \(dev\) at CMP0085-WARN\.cmake:[0-9]+ \(file\):
|
||||
Policy CMP0085 is not set: \$<IN_LIST:\.\.\.> handles empty list items\. Run
|
||||
"cmake --help-policy CMP0085" for policy details\. Use the cmake_policy
|
||||
command to set the policy and suppress this warning\.
|
||||
|
||||
Search Item:
|
||||
|
||||
""
|
||||
|
||||
List:
|
||||
|
||||
""
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
This warning is for project developers\. Use -Wno-dev to suppress it\.
|
||||
|
||||
CMake Warning \(dev\) at CMP0085-WARN\.cmake:[0-9]+ \(file\):
|
||||
Policy CMP0085 is not set: \$<IN_LIST:\.\.\.> handles empty list items\. Run
|
||||
"cmake --help-policy CMP0085" for policy details\. Use the cmake_policy
|
||||
command to set the policy and suppress this warning\.
|
||||
|
||||
Search Item:
|
||||
|
||||
""
|
||||
|
||||
List:
|
||||
|
||||
";a"
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
This warning is for project developers\. Use -Wno-dev to suppress it\.
|
||||
4
Tests/RunCMake/GeneratorExpression/CMP0085-WARN.cmake
Normal file
4
Tests/RunCMake/GeneratorExpression/CMP0085-WARN.cmake
Normal file
@@ -0,0 +1,4 @@
|
||||
cmake_policy(SET CMP0070 NEW)
|
||||
file(GENERATE OUTPUT CMP0085-WARN-generated.txt CONTENT
|
||||
"$<IN_LIST:,>$<IN_LIST:,a>$<IN_LIST:,;a>$<IN_LIST:a,>$<IN_LIST:a,a>$<IN_LIST:a,;a>"
|
||||
)
|
||||
@@ -61,3 +61,13 @@ if(LINKER_SUPPORTS_PDB)
|
||||
else()
|
||||
run_cmake(NonValidCompiler-TARGET_PDB_FILE)
|
||||
endif()
|
||||
|
||||
set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0085:STRING=OLD)
|
||||
run_cmake(CMP0085-OLD)
|
||||
unset(RunCMake_TEST_OPTIONS)
|
||||
|
||||
run_cmake(CMP0085-WARN)
|
||||
|
||||
set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0085:STRING=NEW)
|
||||
run_cmake(CMP0085-NEW)
|
||||
unset(RunCMake_TEST_OPTIONS)
|
||||
|
||||
Reference in New Issue
Block a user