file: Teach GLOB to list directories optionally
GLOB lists directories by default and GLOB_RECURSE does not. LIST_DIRECTORIES enables user to control the behavior explicitly for consistently for both GLOB and GLOB_RECURSE.
This commit is contained in:
parent
a5cab2e739
commit
a2c068a7ce
|
@ -92,9 +92,12 @@ store it in a ``<variable>``.
|
|||
|
||||
::
|
||||
|
||||
file(GLOB <variable> [RELATIVE <path>] [<globbing-expressions>...])
|
||||
file(GLOB_RECURSE <variable> [RELATIVE <path>]
|
||||
[FOLLOW_SYMLINKS] [<globbing-expressions>...])
|
||||
file(GLOB <variable>
|
||||
[LIST_DIRECTORIES true|false] [RELATIVE <path>]
|
||||
[<globbing-expressions>...])
|
||||
file(GLOB_RECURSE <variable> [FOLLOW_SYMLINKS]
|
||||
[LIST_DIRECTORIES true|false] [RELATIVE <path>]
|
||||
[<globbing-expressions>...])
|
||||
|
||||
Generate a list of files that match the ``<globbing-expressions>`` and
|
||||
store it into the ``<variable>``. Globbing expressions are similar to
|
||||
|
@ -102,6 +105,9 @@ regular expressions, but much simpler. If ``RELATIVE`` flag is
|
|||
specified, the results will be returned as relative paths to the given
|
||||
path.
|
||||
|
||||
By default ``GLOB`` lists directories - directories are omited in result if
|
||||
``LIST_DIRECTORIES`` is set to false.
|
||||
|
||||
.. note::
|
||||
We do not recommend using GLOB to collect a list of source files from
|
||||
your source tree. If no CMakeLists.txt file changes when a source is
|
||||
|
@ -119,6 +125,11 @@ matched directory and match the files. Subdirectories that are symlinks
|
|||
are only traversed if ``FOLLOW_SYMLINKS`` is given or policy
|
||||
:policy:`CMP0009` is not set to ``NEW``.
|
||||
|
||||
By default ``GLOB_RECURSE`` omits directories from result list - setting
|
||||
``LIST_DIRECTORIES`` to true adds directories to result list.
|
||||
If ``FOLLOW_SYMLINKS`` is given or policy :policy:`CMP0009` is not set to
|
||||
``OLD`` then ``LIST_DIRECTORIES`` treats symlinks as directories.
|
||||
|
||||
Examples of recursive globbing include::
|
||||
|
||||
/dir/*.py - match all python files in /dir and subdirectories
|
||||
|
|
|
@ -920,6 +920,35 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
|
|||
bool first = true;
|
||||
for ( ; i != args.end(); ++i )
|
||||
{
|
||||
if( *i == "LIST_DIRECTORIES" )
|
||||
{
|
||||
++i;
|
||||
if(i != args.end())
|
||||
{
|
||||
if(cmSystemTools::IsOn(i->c_str()))
|
||||
{
|
||||
g.SetListDirs(true);
|
||||
g.SetRecurseListDirs(true);
|
||||
}
|
||||
else if(cmSystemTools::IsOff(i->c_str()))
|
||||
{
|
||||
g.SetListDirs(false);
|
||||
g.SetRecurseListDirs(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->SetError("LIST_DIRECTORIES missing bool value.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->SetError("LIST_DIRECTORIES missing bool value.");
|
||||
return false;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
if ( recurse && (*i == "FOLLOW_SYMLINKS") )
|
||||
{
|
||||
explicitFollowSymlinks = true;
|
||||
|
@ -950,6 +979,7 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
|
|||
}
|
||||
}
|
||||
|
||||
cmsys::Glob::GlobMessages globMessages;
|
||||
if ( !cmsys::SystemTools::FileIsFullPath(i->c_str()) )
|
||||
{
|
||||
std::string expr = this->Makefile->GetCurrentDirectory();
|
||||
|
@ -957,16 +987,42 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
|
|||
if (!expr.empty())
|
||||
{
|
||||
expr += "/" + *i;
|
||||
g.FindFiles(expr);
|
||||
g.FindFiles(expr, &globMessages);
|
||||
}
|
||||
else
|
||||
{
|
||||
g.FindFiles(*i);
|
||||
g.FindFiles(*i, &globMessages);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g.FindFiles(*i);
|
||||
g.FindFiles(*i, &globMessages);
|
||||
}
|
||||
|
||||
if(!globMessages.empty())
|
||||
{
|
||||
bool shouldExit = false;
|
||||
for(cmsys::Glob::GlobMessagesIterator it=globMessages.begin();
|
||||
it != globMessages.end(); ++it)
|
||||
{
|
||||
if(it->type == cmsys::Glob::cyclicRecursion)
|
||||
{
|
||||
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING,
|
||||
"Cyclic recursion detected while globbing for '"
|
||||
+ *i + "':\n" + it->content);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->Makefile->IssueMessage(cmake::FATAL_ERROR,
|
||||
"Error has occured while globbing for '"
|
||||
+ *i + "' - " + it->content);
|
||||
shouldExit = true;
|
||||
}
|
||||
}
|
||||
if(shouldExit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string>::size_type cc;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1 @@
|
|||
.*file LIST_DIRECTORIES missing bool value\.
|
|
@ -0,0 +1 @@
|
|||
file(GLOB CONTENT_LIST LIST_DIRECTORIES)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1 @@
|
|||
.*file LIST_DIRECTORIES missing bool value\.
|
|
@ -0,0 +1 @@
|
|||
file(GLOB CONTENT_LIST LIST_DIRECTORIES 13)
|
|
@ -0,0 +1,6 @@
|
|||
content: 6[ ]
|
||||
.*/test/dir 1/dir 1 file;.*/test/dir 1/empty_dir;.*/test/dir 1/non_empty_dir;.*/test/dir 2/dir 2 file;.*/test/dir 2/empty_dir;.*/test/dir 2/non_empty_dir
|
||||
content: 6[ ]
|
||||
.*/test/dir 1/dir 1 file;.*/test/dir 1/empty_dir;.*/test/dir 1/non_empty_dir;.*/test/dir 2/dir 2 file;.*/test/dir 2/empty_dir;.*/test/dir 2/non_empty_dir
|
||||
content: 2[ ]
|
||||
.*/test/dir 1/dir 1 file;.*/test/dir 2/dir 2 file
|
|
@ -0,0 +1,28 @@
|
|||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/dir 1/empty_dir")
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/dir 1/non_empty_dir")
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/dir 2/empty_dir")
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/dir 2/non_empty_dir")
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/dir 1/dir 1 file" "test file")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/dir 1/non_empty_dir/dir 1 subdir file" "test file")
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/dir 2/dir 2 file" "test file")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/dir 2/non_empty_dir/dir 2 subdir file" "test file")
|
||||
|
||||
file(GLOB CONTENT_LIST "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||
message("content: ${CONTENT_COUNT} ")
|
||||
list(SORT CONTENT_LIST)
|
||||
message("${CONTENT_LIST}")
|
||||
|
||||
file(GLOB CONTENT_LIST LIST_DIRECTORIES true "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||
message("content: ${CONTENT_COUNT} ")
|
||||
list(SORT CONTENT_LIST)
|
||||
message("${CONTENT_LIST}")
|
||||
|
||||
file(GLOB CONTENT_LIST LIST_DIRECTORIES false "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||
message("content: ${CONTENT_COUNT} ")
|
||||
list(SORT CONTENT_LIST)
|
||||
message("${CONTENT_LIST}")
|
|
@ -0,0 +1,15 @@
|
|||
.*Cyclic recursion detected while globbing for.*
|
||||
.*/test/depth1/depth2/depth3.*
|
||||
.*/test/depth1/depth2/depth3/recursion.*
|
||||
content: 4[ ]
|
||||
.*/test/abc;.*/test/depth1/depth2/depth3/file_symlink;.*/test/depth1/depth2/depth3/recursion/abc;.*/test/depth1/depth2/depth3/recursion/depth1/depth2/depth3/file_symlink
|
||||
.*Cyclic recursion detected while globbing for.*
|
||||
.*/test/depth1/depth2/depth3.*
|
||||
.*/test/depth1/depth2/depth3/recursion.*
|
||||
content: 4[ ]
|
||||
.*/test/abc;.*/test/depth1/depth2/depth3/file_symlink;.*/test/depth1/depth2/depth3/recursion/abc;.*/test/depth1/depth2/depth3/recursion/depth1/depth2/depth3/file_symlink
|
||||
.*Cyclic recursion detected while globbing for.*
|
||||
.*/test/depth1/depth2/depth3.*
|
||||
.*/test/depth1/depth2/depth3/recursion.*
|
||||
content: 11[ ]
|
||||
.*/test/abc;.*/test/depth1;.*/test/depth1/depth2;.*/test/depth1/depth2/depth3;.*/test/depth1/depth2/depth3/file_symlink;.*/test/depth1/depth2/depth3/recursion;.*/test/depth1/depth2/depth3/recursion/abc;.*/test/depth1/depth2/depth3/recursion/depth1;.*/test/depth1/depth2/depth3/recursion/depth1/depth2;.*/test/depth1/depth2/depth3/recursion/depth1/depth2/depth3;.*/test/depth1/depth2/depth3/recursion/depth1/depth2/depth3/file_symlink
|
|
@ -0,0 +1,23 @@
|
|||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/depth1/depth2/depth3")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_BINARY_DIR}/test" "${CMAKE_CURRENT_BINARY_DIR}/test/depth1/depth2/depth3/recursion")
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/abc" "message to write")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_BINARY_DIR}/test/abc" "${CMAKE_CURRENT_BINARY_DIR}/test/depth1/depth2/depth3/file_symlink")
|
||||
|
||||
file(GLOB_RECURSE CONTENT_LIST FOLLOW_SYMLINKS "${CMAKE_CURRENT_BINARY_DIR}/test/*")
|
||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||
message("content: ${CONTENT_COUNT} ")
|
||||
list(SORT CONTENT_LIST)
|
||||
message("${CONTENT_LIST}")
|
||||
|
||||
file(GLOB_RECURSE CONTENT_LIST LIST_DIRECTORIES false FOLLOW_SYMLINKS "${CMAKE_CURRENT_BINARY_DIR}/test/*")
|
||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||
message("content: ${CONTENT_COUNT} ")
|
||||
list(SORT CONTENT_LIST)
|
||||
message("${CONTENT_LIST}")
|
||||
|
||||
file(GLOB_RECURSE CONTENT_LIST LIST_DIRECTORIES true FOLLOW_SYMLINKS "${CMAKE_CURRENT_BINARY_DIR}/test/*")
|
||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||
message("content: ${CONTENT_COUNT} ")
|
||||
list(SORT CONTENT_LIST)
|
||||
message("${CONTENT_LIST}")
|
|
@ -0,0 +1,6 @@
|
|||
content: 4[ ]
|
||||
.*/test/dir 1/dir 1 file;.*/test/dir 1/non_empty_dir/dir 1 subdir file;.*/test/dir 2/dir 2 file;.*/test/dir 2/non_empty_dir/dir 2 subdir file
|
||||
content: 4[ ]
|
||||
.*/test/dir 1/dir 1 file;.*/test/dir 1/non_empty_dir/dir 1 subdir file;.*/test/dir 2/dir 2 file;.*/test/dir 2/non_empty_dir/dir 2 subdir file
|
||||
content: 8[ ]
|
||||
.*/test/dir 1/dir 1 file;.*/test/dir 1/empty_dir;.*/test/dir 1/non_empty_dir;.*/test/dir 1/non_empty_dir/dir 1 subdir file;.*/test/dir 2/dir 2 file;.*/test/dir 2/empty_dir;.*/test/dir 2/non_empty_dir;.*/test/dir 2/non_empty_dir/dir 2 subdir file
|
|
@ -0,0 +1,28 @@
|
|||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/dir 1/empty_dir")
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/dir 1/non_empty_dir")
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/dir 2/empty_dir")
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/dir 2/non_empty_dir")
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/dir 1/dir 1 file" "test file")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/dir 1/non_empty_dir/dir 1 subdir file" "test file")
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/dir 2/dir 2 file" "test file")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/dir 2/non_empty_dir/dir 2 subdir file" "test file")
|
||||
|
||||
file(GLOB_RECURSE CONTENT_LIST "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||
message("content: ${CONTENT_COUNT} ")
|
||||
list(SORT CONTENT_LIST)
|
||||
message("${CONTENT_LIST}")
|
||||
|
||||
file(GLOB_RECURSE CONTENT_LIST LIST_DIRECTORIES false "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||
message("content: ${CONTENT_COUNT} ")
|
||||
list(SORT CONTENT_LIST)
|
||||
message("${CONTENT_LIST}")
|
||||
|
||||
file(GLOB_RECURSE CONTENT_LIST LIST_DIRECTORIES true "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||
message("content: ${CONTENT_COUNT} ")
|
||||
list(SORT CONTENT_LIST)
|
||||
message("${CONTENT_LIST}")
|
|
@ -17,3 +17,13 @@ run_cmake(LOCK-error-no-result-variable)
|
|||
run_cmake(LOCK-error-no-timeout)
|
||||
run_cmake(LOCK-error-timeout)
|
||||
run_cmake(LOCK-error-unknown-option)
|
||||
run_cmake(GLOB)
|
||||
run_cmake(GLOB_RECURSE)
|
||||
# test is valid both for GLOB and GLOB_RECURSE
|
||||
run_cmake(GLOB-error-LIST_DIRECTORIES-not-boolean)
|
||||
# test is valid both for GLOB and GLOB_RECURSE
|
||||
run_cmake(GLOB-error-LIST_DIRECTORIES-no-arg)
|
||||
|
||||
if(NOT WIN32 OR CYGWIN)
|
||||
run_cmake(GLOB_RECURSE-cyclic-recursion)
|
||||
endif()
|
||||
|
|
Loading…
Reference in New Issue