FetchContent: Move log level detection into step script

A step with a custom command shouldn't be seen as out-of-date
just because the user re-runs configure with a different log level.
Previously, the log level was written directly to the step scripts,
but that meant the script changes if the user specifies a different
effective log level to the previous configure. Now we move the
log level detection into the script so that the script remains the
same no matter what log level the user asks for.

This was most noticeable with the PATCH step, since that always
uses a custom command when present. Changing the log level
would cause the PATCH step to re-run, which usually results in
an error because PATCH typically only expects to run once after
a DOWNLOAD. But the underlying problem would affect any step
with a custom command, not just PATCH.

Fixes: #28055
This commit is contained in:
Craig Scott
2026-09-13 21:23:27 +10:00
parent 3f99c9ddab
commit d410092ece
4 changed files with 51 additions and 6 deletions
@@ -766,18 +766,26 @@ function(_ep_add_script_commands script_var work_dir cmd)
# There can be multiple COMMANDs, but we have to split those up to
# one command per call to execute_process()
string(CONCAT execute_process_precmd
"cmake_language(GET_MESSAGE_LOG_LEVEL _ep_step_log_level)\n"
"if(_ep_step_log_level MATCHES \"VERBOSE|DEBUG|TRACE\")\n"
" set(_ep_step_maybe_command_echo COMMAND_ECHO STDOUT)\n"
"else()\n"
" set(_ep_step_maybe_command_echo)\n"
"endif()\n"
)
string(CONCAT execute_process_cmd
"execute_process(\n"
" WORKING_DIRECTORY \"${work_dir}\"\n"
" COMMAND_ERROR_IS_FATAL LAST\n"
" \${_ep_step_maybe_command_echo}\n"
" COMMAND "
)
cmake_language(GET_MESSAGE_LOG_LEVEL active_log_level)
if(active_log_level MATCHES "VERBOSE|DEBUG|TRACE")
string(APPEND execute_process_cmd " COMMAND_ECHO STDOUT\n")
endif()
string(APPEND execute_process_cmd " COMMAND ")
string(APPEND ${script_var} "${execute_process_cmd}")
string(APPEND ${script_var}
"${execute_process_precmd}"
"${execute_process_cmd}"
)
foreach(cmd_arg IN LISTS cmd)
if(cmd_arg STREQUAL "COMMAND")
@@ -0,0 +1,19 @@
cmake_policy(SET CMP0168 NEW)
include(FetchContent)
set(patch_count_file "${CMAKE_CURRENT_BINARY_DIR}/patch-count.txt")
FetchContent_Declare(
t1
DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E make_directory <SOURCE_DIR>
PATCH_COMMAND ${CMAKE_COMMAND}
-DPATCH_COUNT_FILE=${patch_count_file}
-P ${CMAKE_CURRENT_LIST_DIR}/LogLevelPatch.cmake
)
FetchContent_MakeAvailable(t1)
file(READ "${patch_count_file}" patch_count)
if(NOT patch_count EQUAL 1)
message(SEND_ERROR "Patch step ran ${patch_count} times, expected once")
endif()
@@ -0,0 +1,7 @@
if(EXISTS "${PATCH_COUNT_FILE}")
file(READ "${PATCH_COUNT_FILE}" patch_count)
else()
set(patch_count 0)
endif()
math(EXPR patch_count "${patch_count} + 1")
file(WRITE "${PATCH_COUNT_FILE}" "${patch_count}")
@@ -36,6 +36,17 @@ run_cmake_with_cmp0168(MakeAvailable)
run_cmake_with_cmp0168(MakeAvailableTwice)
run_cmake_with_cmp0168(MakeAvailableUndeclared)
run_cmake_with_cmp0168(VerifyHeaderSet)
block(SCOPE_FOR VARIABLES)
# The direct-population scripts must be independent of the configure-time
# log level. Steps should not be seen as out-of-date just because the user
# re-ran configure with a different verbosity.
# Reuse the build tree for a quiet then verbose configuration.
set(RunCMake_TEST_NO_CLEAN 1)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/LogLevel-direct-build)
run_cmake(LogLevel)
set(RunCMake_TEST_VARIANT_DESCRIPTION "-verbose")
run_cmake_with_options(LogLevel --log-level=VERBOSE)
endblock()
run_cmake_with_cmp0168(FindDependencyExport
-D "CMAKE_PROJECT_TOP_LEVEL_INCLUDES=${CMAKE_CURRENT_LIST_DIR}/FindDependencyExportDP.cmake"