file: Sort GLOB results to make it deterministic (#14491)
Even though the `file(GLOB)` documentation specifically warns against using it to collect a list of source files, projects often do it anyway. Since it uses `readdir()`, the list of files will be unsorted. This list is often passed directly to add_executable / add_library. Linking binaries with an unsorted list will make it unreproducible, which means that the produced binary will differ depending on the unpredictable `readdir()` order. To solve those reproducibility issues in a lot of programs (which don't explicitly `list(SORT)` the list manually), sort the resulting list of the `file(GLOB)` command. A more detailed rationale about reproducible builds is available [here](https://reproducible-builds.org/).
This commit is contained in:
parent
d9fd2f5402
commit
edcccde7d6
|
@ -103,8 +103,9 @@ Generate a list of files that match the ``<globbing-expressions>`` and
|
||||||
store it into the ``<variable>``. Globbing expressions are similar to
|
store it into the ``<variable>``. Globbing expressions are similar to
|
||||||
regular expressions, but much simpler. If ``RELATIVE`` flag is
|
regular expressions, but much simpler. If ``RELATIVE`` flag is
|
||||||
specified, the results will be returned as relative paths to the given
|
specified, the results will be returned as relative paths to the given
|
||||||
path. No specific order of results is defined. If order is important then
|
path. No specific order of results is defined other than that it is
|
||||||
sort the list explicitly (e.g. using the :command:`list(SORT)` command).
|
deterministic. If order is important then sort the list explicitly
|
||||||
|
(e.g. using the :command:`list(SORT)` command).
|
||||||
|
|
||||||
By default ``GLOB`` lists directories - directories are omited in result if
|
By default ``GLOB`` lists directories - directories are omited in result if
|
||||||
``LIST_DIRECTORIES`` is set to false.
|
``LIST_DIRECTORIES`` is set to false.
|
||||||
|
|
|
@ -823,6 +823,7 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
|
||||||
|
|
||||||
std::vector<std::string>::size_type cc;
|
std::vector<std::string>::size_type cc;
|
||||||
std::vector<std::string>& files = g.GetFiles();
|
std::vector<std::string>& files = g.GetFiles();
|
||||||
|
std::sort(files.begin(), files.end());
|
||||||
for (cc = 0; cc < files.size(); cc++) {
|
for (cc = 0; cc < files.size(); cc++) {
|
||||||
if (!first) {
|
if (!first) {
|
||||||
output += ";";
|
output += ";";
|
||||||
|
|
|
@ -12,17 +12,14 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/dir 2/non_empty_dir/dir 2 subdir fi
|
||||||
file(GLOB CONTENT_LIST "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
file(GLOB CONTENT_LIST "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
||||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||||
message("content: ${CONTENT_COUNT} ")
|
message("content: ${CONTENT_COUNT} ")
|
||||||
list(SORT CONTENT_LIST)
|
|
||||||
message("${CONTENT_LIST}")
|
message("${CONTENT_LIST}")
|
||||||
|
|
||||||
file(GLOB CONTENT_LIST LIST_DIRECTORIES true "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
file(GLOB CONTENT_LIST LIST_DIRECTORIES true "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
||||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||||
message("content: ${CONTENT_COUNT} ")
|
message("content: ${CONTENT_COUNT} ")
|
||||||
list(SORT CONTENT_LIST)
|
|
||||||
message("${CONTENT_LIST}")
|
message("${CONTENT_LIST}")
|
||||||
|
|
||||||
file(GLOB CONTENT_LIST LIST_DIRECTORIES false "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
file(GLOB CONTENT_LIST LIST_DIRECTORIES false "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
||||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||||
message("content: ${CONTENT_COUNT} ")
|
message("content: ${CONTENT_COUNT} ")
|
||||||
list(SORT CONTENT_LIST)
|
|
||||||
message("${CONTENT_LIST}")
|
message("${CONTENT_LIST}")
|
||||||
|
|
|
@ -7,17 +7,14 @@ execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_BINA
|
||||||
file(GLOB_RECURSE CONTENT_LIST FOLLOW_SYMLINKS "${CMAKE_CURRENT_BINARY_DIR}/test/*")
|
file(GLOB_RECURSE CONTENT_LIST FOLLOW_SYMLINKS "${CMAKE_CURRENT_BINARY_DIR}/test/*")
|
||||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||||
message("content: ${CONTENT_COUNT} ")
|
message("content: ${CONTENT_COUNT} ")
|
||||||
list(SORT CONTENT_LIST)
|
|
||||||
message("${CONTENT_LIST}")
|
message("${CONTENT_LIST}")
|
||||||
|
|
||||||
file(GLOB_RECURSE CONTENT_LIST LIST_DIRECTORIES false FOLLOW_SYMLINKS "${CMAKE_CURRENT_BINARY_DIR}/test/*")
|
file(GLOB_RECURSE CONTENT_LIST LIST_DIRECTORIES false FOLLOW_SYMLINKS "${CMAKE_CURRENT_BINARY_DIR}/test/*")
|
||||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||||
message("content: ${CONTENT_COUNT} ")
|
message("content: ${CONTENT_COUNT} ")
|
||||||
list(SORT CONTENT_LIST)
|
|
||||||
message("${CONTENT_LIST}")
|
message("${CONTENT_LIST}")
|
||||||
|
|
||||||
file(GLOB_RECURSE CONTENT_LIST LIST_DIRECTORIES true FOLLOW_SYMLINKS "${CMAKE_CURRENT_BINARY_DIR}/test/*")
|
file(GLOB_RECURSE CONTENT_LIST LIST_DIRECTORIES true FOLLOW_SYMLINKS "${CMAKE_CURRENT_BINARY_DIR}/test/*")
|
||||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||||
message("content: ${CONTENT_COUNT} ")
|
message("content: ${CONTENT_COUNT} ")
|
||||||
list(SORT CONTENT_LIST)
|
|
||||||
message("${CONTENT_LIST}")
|
message("${CONTENT_LIST}")
|
||||||
|
|
|
@ -12,17 +12,14 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/dir 2/non_empty_dir/dir 2 subdir fi
|
||||||
file(GLOB_RECURSE CONTENT_LIST "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
file(GLOB_RECURSE CONTENT_LIST "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
||||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||||
message("content: ${CONTENT_COUNT} ")
|
message("content: ${CONTENT_COUNT} ")
|
||||||
list(SORT CONTENT_LIST)
|
|
||||||
message("${CONTENT_LIST}")
|
message("${CONTENT_LIST}")
|
||||||
|
|
||||||
file(GLOB_RECURSE CONTENT_LIST LIST_DIRECTORIES false "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
file(GLOB_RECURSE CONTENT_LIST LIST_DIRECTORIES false "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
||||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||||
message("content: ${CONTENT_COUNT} ")
|
message("content: ${CONTENT_COUNT} ")
|
||||||
list(SORT CONTENT_LIST)
|
|
||||||
message("${CONTENT_LIST}")
|
message("${CONTENT_LIST}")
|
||||||
|
|
||||||
file(GLOB_RECURSE CONTENT_LIST LIST_DIRECTORIES true "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
file(GLOB_RECURSE CONTENT_LIST LIST_DIRECTORIES true "${CMAKE_CURRENT_BINARY_DIR}/test/*/*")
|
||||||
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
list(LENGTH CONTENT_LIST CONTENT_COUNT)
|
||||||
message("content: ${CONTENT_COUNT} ")
|
message("content: ${CONTENT_COUNT} ")
|
||||||
list(SORT CONTENT_LIST)
|
|
||||||
message("${CONTENT_LIST}")
|
message("${CONTENT_LIST}")
|
||||||
|
|
Loading…
Reference in New Issue