file(): TOUCH, TOUCH_NOCREATE and MAKE_DIRECTORY accept empty lists

Projects may be generating a list of files or directories to pass as arguments
to file(TOUCH), file(TOUCH_NOCREATE), or file(MAKE_DIRECTORY). Those
lists might end up being empty, so rather than requiring at least one item,
allow an empty list.

Fixes: #24897
This commit is contained in:
Craig Scott
2024-05-31 21:20:30 +10:00
parent 140766867b
commit 7c516f7e28
7 changed files with 29 additions and 21 deletions

View File

@@ -192,6 +192,10 @@ Writing
With ``TOUCH`` and ``TOUCH_NOCREATE``, the contents of an existing file
will not be modified.
.. versionchanged:: 3.30
``<files>`` can be an empty list. CMake 3.29 and earlier required
at least one file to be given.
.. signature::
file(GENERATE [...])
@@ -398,6 +402,10 @@ Filesystem
Create the given directories and their parents as needed.
.. versionchanged:: 3.30
``<directories>`` can be an empty list. CMake 3.29 and earlier required
at least one directory to be given.
.. signature::
file(REMOVE <files>...)
file(REMOVE_RECURSE <files>...)

View File

@@ -73,6 +73,11 @@ namespace {
bool HandleWriteImpl(std::vector<std::string> const& args, bool append,
cmExecutionStatus& status)
{
if (args.size() < 2) {
status.SetError(cmStrCat(
args[0], " must be called with at least one additional argument."));
return false;
}
auto i = args.begin();
i++; // Get rid of subcommand
@@ -658,8 +663,11 @@ bool HandleStringsCommand(std::vector<std::string> const& args,
bool HandleGlobImpl(std::vector<std::string> const& args, bool recurse,
cmExecutionStatus& status)
{
// File commands has at least one argument
assert(args.size() > 1);
if (args.size() < 2) {
status.SetError(cmStrCat(
args[0], " must be called with at least one additional argument."));
return false;
}
auto i = args.begin();
@@ -869,8 +877,8 @@ bool HandleGlobRecurseCommand(std::vector<std::string> const& args,
bool HandleMakeDirectoryCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
// File command has at least one argument
assert(args.size() > 1);
// Projects might pass a dynamically generated list of directories, and it
// could be an empty list. We should not assume there is at least one.
std::string expr;
for (std::string const& arg :
@@ -903,8 +911,8 @@ bool HandleMakeDirectoryCommand(std::vector<std::string> const& args,
bool HandleTouchImpl(std::vector<std::string> const& args, bool create,
cmExecutionStatus& status)
{
// File command has at least one argument
assert(args.size() > 1);
// Projects might pass a dynamically generated list of files, and it
// could be an empty list. We should not assume there is at least one.
for (std::string const& arg :
cmMakeRange(args).advance(1)) // Get rid of subcommand
@@ -3918,8 +3926,9 @@ bool HandleChmodRecurseCommand(std::vector<std::string> const& args,
bool cmFileCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
if (args.size() < 2) {
status.SetError("must be called with at least two arguments.");
if (args.empty()) {
status.SetError(
"given no arguments, but it requires at least a sub-command.");
return false;
}

View File

@@ -13,13 +13,13 @@ set(Copy-NoDest-STDERR "given no DESTINATION")
set(Copy-NoFile-RESULT 1)
set(Copy-NoFile-STDERR "COPY cannot find.*/does_not_exist\\.txt")
set(Glob-NoArg-RESULT 1)
set(Glob-NoArg-STDERR "file must be called with at least two arguments")
set(Glob-NoArg-STDERR "file GLOB must be called with at least one additional argument\\.")
set(Make_Directory-NoArg-RESULT 1)
set(Make-Directory-NoArg-STDERR "file must be called with at least two arguments")
set(MD5-NoFile-RESULT 1)
set(MD5-NoFile-STDERR "file MD5 failed to read file")
set(MD5-BadArg1-RESULT 1)
set(MD5-BadArg1-STDERR "file must be called with at least two arguments")
set(MD5-BadArg1-STDERR "file MD5 requires a file name and output variable")
set(MD5-BadArg2-RESULT 1)
set(MD5-BadArg2-STDERR "file MD5 requires a file name and output variable")
set(MD5-BadArg4-RESULT 1)

View File

@@ -1,4 +1,4 @@
CMake Error at LOCK-error-no-path.cmake:[0-9]+ \(file\):
file must be called with at least two arguments.
sub-command LOCK requires at least two arguments\.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)

View File

@@ -1 +0,0 @@
1

View File

@@ -1,9 +0,0 @@
^CMake Error at TOUCH\.cmake:[0-9]+ \(file\):
file must be called with at least two arguments\.
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)
+
CMake Error at TOUCH\.cmake:[0-9]+ \(file\):
file must be called with at least two arguments\.
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)

View File

@@ -12,5 +12,6 @@ if(NOT EXISTS "${file}")
endif()
file(REMOVE "${file}")
# Empty arguments used to be an error, but this is valid since CMake 3.30
file(TOUCH)
file(TOUCH_NOCREATE)