1: Test command: /opt/cmake_3_20_5/bin/cmake "-E" "echo"
while CMake 3.29.6 will show it as:
1: Test command: /home/kees-jan/src/cmake/cmake-build/bin/cmake "-E" "echo" ""
the difference being that CMake 3.29.6 passes along an empty string
argument, while 3.20.5 does not. In my actual usecase, a custom tool is
being called that complains about the extra argument.
Normally, I’d remove the quotes from "${include_dir_options}", but that
keeps the generator expression from being expanded, resulting in
incorrect behavior
Why was the behavior changed? Can we get the old behavior back? Any
other tips for solving this?
I don’t know when the behavior changed, so you’d need to do a git bisect or some other way to work out precisely what changed it. But the new behavior is the more correct behavior. If you put quotes around an argument, you’re saying that there must be an argument there, even if it evaluates to an empty string. If you want empty evaluation to result in no argument being added, using it unquoted is what you should do.
When you use the value unquoted, you’re probably hitting the problem that the semicolons are causing argument splitting. Since you’re only using this as a string to echo to the output, you could replace semicolons with spaces in that printed value. Something like the following might get you close:
But you also mention that you have a real tool accepting these arguments, so I’m assuming the “echo” is just a simplified example. If you need real arguments to pass to a real tool, another choice might be to replace the semicolons with $<SEMICOLON> instead of a space. I don’t know if that will work, but COMMAND_EXPAND_LISTS will probably be needed in this case.
1: Test command: /home/kees-jan/src/cmake/cmake-build/bin/cmake “-E” “echo” “-I dir1 dir2 dir3”
As you can see, "-I dir1 dir2 dir3" is now passed as a single argument with no -I in between the directories, instead of the intended "-I" "dir1" "-I" "dir2" "-I" "dir3"
My apologies. I completely missed the fact that $<SEMICOLON> is a generator expression and therefore didn’t understand the last paragraph. Also I was wrong (as you pointed out) that I need quotes to have my generator expression expanded.
I’ve now hopefully correctly applied all of your tips, and ended up with
It would be useful to pin down the exact commit where the behavior changed. I’m focused on other activities at the moment. If you want build CMake locally yourself and do a git bisect to find where the behavior changed, that would be most welcome. Once we know where/why it changes, we’ll be in a better position to know what’s involved in supporting the original behavior.
1df3287bf6a49d410b81be670218259afc3474d4 is the first bad commit
commit 1df3287bf6a49d410b81be670218259afc3474d4
Author: Marc Chevrier <marc.chevrier@gmail.com>
Date: Fri Jun 9 11:44:27 2023 +0200
add_test: Restore support for empty test arguments
This was regressed by refactoring in commit e08ba229ee (CMake code rely
on cmList class for CMake lists management (part. 1), 2023-04-14,
v3.27.0-rc1~174^2). Fix it and add a test case.
Fixes: #24986
Source/cmTestGenerator.cxx | 3 ++-
Tests/RunCMake/add_test/CheckEmptyArgument.cmake | 11 +++++++++++
Tests/RunCMake/add_test/EmptyArgument.cmake | 5 +++++
Tests/RunCMake/add_test/RunCMakeTest.cmake | 8 ++++++++
4 files changed, 26 insertions(+), 1 deletion(-)
create mode 100644 Tests/RunCMake/add_test/CheckEmptyArgument.cmake
create mode 100644 Tests/RunCMake/add_test/EmptyArgument.cmake
Thanks for that. It looks like there may have been another fix and regression between 3.20.5 and 3.27.0-rc1 though. Looking at the referenced issue, the commit you referenced refers to changes for 3.27.0-rc1 that caused empty arguments to be dropped. This means somewhere before 3.27.0-rc1, empty arguments were already being kept, which is contrary to your observation for 3.20.5. There must have been another change in between. If you’re able to find where that was, that would also be helpful. In the meantime, I will create an issue in our issue tracker related to this. I think there may still be a bug in the latest implementation, but I need to dig into he code a bit more to understand what’s intended versus what’s actually happening.
I created issue 26272 to track this apparent regression, but it may have been intentional. I’ve added a link back to this discussion thread here for context.
I see the issue you’ve created describes the original problem I’ve reported. However, with the lessons learned from our discussion, I would now phrase the problem differently.
You pointed out that expanding quoted empty variables to quoted empty strings is more correct. I concur, and it is no doubt the goal of the first failing commit we uncovered. My only objection was that without quotes, I couldn’t get the generator expression to expand. You’ve since been teaching me about argument splitting and $<SEMICOLON>.
With all that, my new problem description would be that I feel that empty variables and variables that contain a generator expression that evaluates to nothing should be treated the same (regardless of them being quoted). I.e. in
I’d expect the same test to be run twice (with no empty string argument, because there are no quotes). However, that’s currently not the case. I get
1: Test command: /usr/bin/cmake "-E" "echo"
and
2: Test command: /usr/bin/cmake "-E" "echo" ""
I’d argue that if I had used quotes, they should both have an empty string argument (and that part is indeed working correctly), but now that I don’t use quotes, they both should not. This is were the case with the generator expression goes wrong.
I’ve been doing some additional testing. This new problem I’m describing is already present in 3.20.5, so I can’t really call it a (recent) regression. This means that my original use-case would not have worked with that version either, and I have found a bug on our side
That does make me turn full circle to my original problem: In the scenario where there are no include directories, I would like there to be no (empty) arguments to my test. How’s that done?
I typed that, and immediately felt uncomfortable. I knew things worked well before. I just couldn’t explain why at the time. Thus, I did some additional experimentation.
Consider
add_test(NAME test COMMAND ${CMAKE_COMMAND} -E echo "")
That’s a quoted empty string, and it should be passed on to the test. Both 3.20 and 3.29 handle that case correctly. That also tells me that the regresson of empty strings not being supported happened somewhere after 3.20.
Next consider
add_test(NAME test COMMAND ${CMAKE_COMMAND} -E echo "" COMMAND_EXPAND_LISTS)
Now that, at least to me, is a quoted empty list. And empty lists (quoted or otherwise) should expand to absolutely nothing. 3.20 seems to agree with me, but that changed after commit 1df3287b cited above.
Now I’ll happily agree that there is some room for interpretation. After all, without the presence of a semicolon, it is hard to tell whether something is a list or not. But without any statistics to back me up, I’d still argue that empty lists are more common than empty strings, and therefore we should, in this case, err on the side of assuming that things are lists.