From 7644d557df58a2c25c9cf9e749d42e939fa4e367 Mon Sep 17 00:00:00 2001 From: Matthew Woehlke Date: Mon, 20 Jul 2026 15:57:32 -0400 Subject: [PATCH] Check*: Refactor variable handling Commit 5abaf65154 (Check*: Restore toleration of `;-W...` in CMAKE_REQUIRED_FLAGS, 2026-06-24, v4.4.0-rc3~2^2) introduced logic to prevent `-W*` arguments in `CMAKE_REQUIRED_FLAGS` from being passed as CMake arguments. It was never the intent of `CMAKE_REQUIRED_FLAGS` to support such usage; however, since older versions of CMake would silently accept such arguments, some users were unintentionally passing compiler warnings as CMake arguments. Although this usage is incorrect, it was silently tolerated until CMake 4.4, which began treating unknown `-W*` as an error. Because it turns out that modules besides `CheckSource{Compiles,Runs}` are affected, we are going to need the logic added by that commit in many more places. As a first step toward accommodating that need, move the logic to a new internal helper. While we're at it, try to generally consolidate the common logic for handling the various variables that the `Check*` family of modules uses for injecting arguments into the ultimate `try_compile` calls. --- Modules/Internal/CheckCommon.cmake | 119 +++++++++++++++++++++ Modules/Internal/CheckSourceCompiles.cmake | 70 ++---------- Modules/Internal/CheckSourceRuns.cmake | 72 ++----------- 3 files changed, 133 insertions(+), 128 deletions(-) create mode 100644 Modules/Internal/CheckCommon.cmake diff --git a/Modules/Internal/CheckCommon.cmake b/Modules/Internal/CheckCommon.cmake new file mode 100644 index 0000000000..1de98e7610 --- /dev/null +++ b/Modules/Internal/CheckCommon.cmake @@ -0,0 +1,119 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file LICENSE.rst or https://cmake.org/licensing for details. + + +# Do NOT include this module directly into any of your code. It is meant as +# a library for Check*CompilerFlag.cmake and Check*LinkerFlag.cma modules. +# It's content may change in any way between releases. + +include_guard(GLOBAL) + +macro(CMAKE_CHECK_COMMON_INIT_COMPILE_FLAGS _PREFIX) + set(${_PREFIX}_EXTRA_CMAKE_ARGUMENTS) + string(REPLACE "\\;" "\\\\;" CMAKE_REQUIRED_FLAGS + "${CMAKE_REQUIRED_FLAGS}") + #[[ + cmake_polify(GET CMP0999 ${_PREFIX}_CMP0999) + if(${_PREFIX}_CMP0999 STREQUAL "NEW") + # Join multiple list arguments into the space-separated string that we + # want. This ensures that the entirety of the value gets passed as + # compile arguments, which is what the user almost surely intended. + # + # FIXME(#27901): This needs a policy to be implemented. This will be + # available in a future version of CMake. + list(JOIN CMAKE_REQUIRED_FLAGS " " CMAKE_REQUIRED_FLAGS) + else() + #]] + # If CMAKE_REQUIRED_FLAGS contains an unescaped semicolon, anything after + # gets passed as flags to 'cmake' itself. This is probably not intended, + # but we preserve it for compatibility. + set(${_PREFIX}_EXTRA_CMAKE_ARGUMENTS "${CMAKE_REQUIRED_FLAGS}") + list(POP_FRONT ${_PREFIX}_EXTRA_CMAKE_ARGUMENTS CMAKE_REQUIRED_FLAGS) + if(NOT ${_PREFIX}_EXTRA_CMAKE_ARGUMENTS STREQUAL "") + # cmake_policy(ISSUE_WARNING CMP0999) TODO + # There are known instances of users accidentally passing '-W' arguments + # intended for the compiler as arguments to CMake. Since CMake complains + # about unknown '-W' arguments starting with CMake 4.4, we need to strip + # these for compatibility. + string(REPLACE "\\;" "\\\\;" ${_PREFIX}_EXTRA_CMAKE_ARGUMENTS + "${${_PREFIX}_EXTRA_CMAKE_ARGUMENTS}") + list(FILTER ${_PREFIX}_EXTRA_CMAKE_ARGUMENTS EXCLUDE REGEX "^-W") + endif() + #endif() +endmacro() + +macro(CMAKE_CHECK_COMMON_INIT_INCLUDE_DIRECTORIES _PREFIX) + if(CMAKE_REQUIRED_INCLUDES) + if(${ARGC} GREATER 1) + set(${_PREFIX}_INCLUDE_DIRECTORIES + "-DINCLUDE_DIRECTORIES:STRING=${ARGN};${CMAKE_REQUIRED_INCLUDES}") + else() + set(${_PREFIX}_INCLUDE_DIRECTORIES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") + endif() + elseif(${ARGC} GREATER 1) + set(${_PREFIX}_INCLUDE_DIRECTORIES + "-DINCLUDE_DIRECTORIES:STRING=${ARGN}") + else() + set(${_PREFIX}_INCLUDE_DIRECTORIES) + endif() +endmacro() + +macro(CMAKE_CHECK_COMMON_INIT_LINK_OPTIONS _PREFIX) + if(CMAKE_REQUIRED_LINK_OPTIONS OR ${ARGC} GREATER 1) + set(${_PREFIX}_ADD_LINK_OPTIONS + LINK_OPTIONS ${ARGN} ${CMAKE_REQUIRED_LINK_OPTIONS}) + else() + set(${_PREFIX}_ADD_LINK_OPTIONS) + endif() +endmacro() + +macro(CMAKE_CHECK_COMMON_INIT_LINK_LIBRARIES _PREFIX) + if(CMAKE_REQUIRED_LIBRARIES OR ${ARGC} GREATER 1) + set(${_PREFIX}_ADD_LINK_LIBRARIES + LINK_LIBRARIES ${ARGN} ${CMAKE_REQUIRED_LIBRARIES}) + else() + set(${_PREFIX}_ADD_LINK_LIBRARIES) + endif() +endmacro() + +macro(CMAKE_CHECK_COMMON_INIT_LINK_DIRECTORIES _PREFIX) + if(CMAKE_REQUIRED_LINK_DIRECTORIES) + if(${ARGC} GREATER 1) + set(${_PREFIX}_LINK_DIRECTORIES + "-DLINK_DIRECTORIES:STRING=${ARGN};${CMAKE_REQUIRED_LINK_DIRECTORIES}") + else() + set(${_PREFIX}_LINK_DIRECTORIES + "-DLINK_DIRECTORIES:STRING=${CMAKE_REQUIRED_LINK_DIRECTORIES}") + endif() + elseif(${ARGC} GREATER 1) + set(${_PREFIX}_LINK_DIRECTORIES + "-DLINK_DIRECTORIES:STRING=${ARGN}") + else() + set(${_PREFIX}_LINK_DIRECTORIES) + endif() +endmacro() + +macro(CMAKE_CHECK_COMMON_INIT_COMPILE_ARGS _PREFIX) + cmake_check_common_init_compile_flags(${_PREFIX}) + cmake_check_common_init_include_directories(${_PREFIX}) +endmacro() + +macro(CMAKE_CHECK_COMMON_INIT_LINK_ARGS _PREFIX) + cmake_check_common_init_link_options(${_PREFIX}) + cmake_check_common_init_link_libraries(${_PREFIX}) + cmake_check_common_init_link_directories(${_PREFIX}) +endmacro() + +macro(CMAKE_CHECK_COMMON_INIT_ARGS _PREFIX) + cmake_check_common_init_compile_args(${_PREFIX}) + cmake_check_common_init_link_args(${_PREFIX}) +endmacro() + +macro(CMAKE_CHECK_COMMON_CLEANUP _PREFIX) + unset(${_PREFIX}_ADD_LINK_OPTIONS) + unset(${_PREFIX}_ADD_LINK_LIBRARIES) + unset(${_PREFIX}_LINK_DIRECTORIES) + unset(${_PREFIX}_INCLUDE_DIRECTORIES) + unset(${_PREFIX}_EXTRA_CMAKE_ARGUMENTS) +endmacro() diff --git a/Modules/Internal/CheckSourceCompiles.cmake b/Modules/Internal/CheckSourceCompiles.cmake index 18ee7d17ae..733b62edd8 100644 --- a/Modules/Internal/CheckSourceCompiles.cmake +++ b/Modules/Internal/CheckSourceCompiles.cmake @@ -2,6 +2,7 @@ # file LICENSE.rst or https://cmake.org/licensing for details. include_guard(GLOBAL) +include(Internal/CheckCommon) function(CMAKE_CHECK_SOURCE_COMPILES _lang _source _var) if(NOT DEFINED "${_var}") @@ -71,65 +72,7 @@ function(CMAKE_CHECK_SOURCE_COMPILES _lang _source _var) set(_SRC_EXT ${_lang_ext}) endif() - if(CMAKE_REQUIRED_LINK_OPTIONS) - set(CHECK_${LANG}_SOURCE_COMPILES_ADD_LINK_OPTIONS - LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS}) - else() - set(CHECK_${LANG}_SOURCE_COMPILES_ADD_LINK_OPTIONS) - endif() - if(CMAKE_REQUIRED_LIBRARIES) - set(CHECK_${LANG}_SOURCE_COMPILES_ADD_LIBRARIES - LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) - else() - set(CHECK_${LANG}_SOURCE_COMPILES_ADD_LIBRARIES) - endif() - if(CMAKE_REQUIRED_LINK_DIRECTORIES) - set(_CSC_LINK_DIRECTORIES - "-DLINK_DIRECTORIES:STRING=${CMAKE_REQUIRED_LINK_DIRECTORIES}") - else() - set(_CSC_LINK_DIRECTORIES) - endif() - - if(CMAKE_REQUIRED_INCLUDES) - set(CHECK_${LANG}_SOURCE_COMPILES_ADD_INCLUDES - "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") - else() - set(CHECK_${LANG}_SOURCE_COMPILES_ADD_INCLUDES) - endif() - - set(_CSC_EXTRA_CMAKE_ARGUMENTS) - string(REPLACE "\\;" "\\\\;" CMAKE_REQUIRED_FLAGS - "${CMAKE_REQUIRED_FLAGS}") - #[[ - cmake_polify(GET CMP0999 _CSC_CMP0999) - if(_CSC_CMP0999 STREQUAL "NEW") - # Join multiple list arguments into the space-separated string that we - # want. This ensures that the entirety of the value gets passed as - # compile arguments, which is what the user almost surely intended. - # - # FIXME(#27901): This needs a policy to be implemented. This will be - # available in a future version of CMake. - list(JOIN CMAKE_REQUIRED_FLAGS " " CMAKE_REQUIRED_FLAGS) - else() - #]] - # If CMAKE_REQUIRED_FLAGS contains an unescaped semicolon, anything after - # gets passed as flags to 'cmake' itself. This is probably not intended, - # but we preserve it for compatibility. - set(_CSC_EXTRA_CMAKE_ARGUMENTS "${CMAKE_REQUIRED_FLAGS}") - list(POP_FRONT _CSC_EXTRA_CMAKE_ARGUMENTS CMAKE_REQUIRED_FLAGS) - #[[ - if(NOT CMAKE_REQUIRED_FLAGS STREQUAL "") - cmake_policy(ISSUE_WARNING CMP0999) TODO - endif() - #]] - # There is at least one known instance of users accidentally passing - # '-W' arguments intended for the compiler as arguments to CMake. Since - # CMake complains about unknown '-W' arguments starting with CMake 4.4, - # we need to strip these for compatibility. - string(REPLACE "\\;" "\\\\;" _CSC_EXTRA_CMAKE_ARGUMENTS - "${_CSC_EXTRA_CMAKE_ARGUMENTS}") - list(FILTER _CSC_EXTRA_CMAKE_ARGUMENTS EXCLUDE REGEX "^-W") - #endif() + cmake_check_common_init_args(_CSC) if(NOT CMAKE_REQUIRED_QUIET) message(CHECK_START "Performing Test ${_var}") @@ -138,15 +81,14 @@ function(CMAKE_CHECK_SOURCE_COMPILES _lang _source _var) try_compile(${_var} SOURCE_FROM_VAR "${_lang_filename}.${_SRC_EXT}" _source COMPILE_DEFINITIONS -D${_var} ${CMAKE_REQUIRED_DEFINITIONS} - ${CHECK_${LANG}_SOURCE_COMPILES_ADD_LINK_OPTIONS} - ${CHECK_${LANG}_SOURCE_COMPILES_ADD_LIBRARIES} + ${_CSC_ADD_LINK_OPTIONS} + ${_CSC_ADD_LINK_LIBRARIES} CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${CMAKE_REQUIRED_FLAGS} ${_CSC_EXTRA_CMAKE_ARGUMENTS} - "${CHECK_${LANG}_SOURCE_COMPILES_ADD_INCLUDES}" - "${_CSC_LINK_DIRECTORIES}" + "${_CSC_INCLUDE_DIRECTORIES}" + "${_CSC_LINK_DIRECTORIES}" OUTPUT_VARIABLE OUTPUT) - unset(_CSC_LINK_DIRECTORIES) foreach(_regex ${_FAIL_REGEX}) if("${OUTPUT}" MATCHES "${_regex}") diff --git a/Modules/Internal/CheckSourceRuns.cmake b/Modules/Internal/CheckSourceRuns.cmake index a698e867ce..eaf9632524 100644 --- a/Modules/Internal/CheckSourceRuns.cmake +++ b/Modules/Internal/CheckSourceRuns.cmake @@ -2,6 +2,7 @@ # file LICENSE.rst or https://cmake.org/licensing for details. include_guard(GLOBAL) +include(Internal/CheckCommon) function(CMAKE_CHECK_SOURCE_RUNS _lang _source _var) if(NOT DEFINED "${_var}") @@ -63,64 +64,7 @@ function(CMAKE_CHECK_SOURCE_RUNS _lang _source _var) set(_SRC_EXT ${_lang_ext}) endif() - if(CMAKE_REQUIRED_LINK_OPTIONS) - set(CHECK_${_lang}_SOURCE_COMPILES_ADD_LINK_OPTIONS - LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS}) - else() - set(CHECK_${_lang}_SOURCE_COMPILES_ADD_LINK_OPTIONS) - endif() - if(CMAKE_REQUIRED_LIBRARIES) - set(CHECK_${_lang}_SOURCE_COMPILES_ADD_LIBRARIES - LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) - else() - set(CHECK_${_lang}_SOURCE_COMPILES_ADD_LIBRARIES) - endif() - if(CMAKE_REQUIRED_LINK_DIRECTORIES) - set(_CSR_LINK_DIRECTORIES - "-DLINK_DIRECTORIES:STRING=${CMAKE_REQUIRED_LINK_DIRECTORIES}") - else() - set(_CSR_LINK_DIRECTORIES) - endif() - if(CMAKE_REQUIRED_INCLUDES) - set(CHECK_${_lang}_SOURCE_COMPILES_ADD_INCLUDES - "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") - else() - set(CHECK_${_lang}_SOURCE_COMPILES_ADD_INCLUDES) - endif() - - set(_CSR_EXTRA_CMAKE_ARGUMENTS) - string(REPLACE "\\;" "\\\\;" CMAKE_REQUIRED_FLAGS - "${CMAKE_REQUIRED_FLAGS}") - #[[ - cmake_polify(GET CMP0999 _CSR_CMP0999) - if(_CSR_CMP0999 STREQUAL "NEW") - # Join multiple list arguments into the space-separated string that we - # want. This ensures that the entirety of the value gets passed as - # compile arguments, which is what the user almost surely intended. - # - # FIXME(#27901): This needs a policy to be implemented. This will be - # available in a future version of CMake. - list(JOIN CMAKE_REQUIRED_FLAGS " " CMAKE_REQUIRED_FLAGS) - else() - #]] - # If CMAKE_REQUIRED_FLAGS contains an unescaped semicolon, anything after - # gets passed as flags to 'cmake' itself. This is probably not intended, - # but we preserve it for compatibility. - set(_CSR_EXTRA_CMAKE_ARGUMENTS "${CMAKE_REQUIRED_FLAGS}") - list(POP_FRONT _CSR_EXTRA_CMAKE_ARGUMENTS CMAKE_REQUIRED_FLAGS) - #[[ - if(NOT CMAKE_REQUIRED_FLAGS STREQUAL "") - cmake_policy(ISSUE_WARNING CMP0999) TODO - endif() - #]] - # There is at least one known instance of users accidentally passing - # '-W' arguments intended for the compiler as arguments to CMake. Since - # CMake complains about unknown '-W' arguments starting with CMake 4.4, - # we need to strip these for compatibility. - string(REPLACE "\\;" "\\\\;" _CSR_EXTRA_CMAKE_ARGUMENTS - "${_CSR_EXTRA_CMAKE_ARGUMENTS}") - list(FILTER _CSR_EXTRA_CMAKE_ARGUMENTS EXCLUDE REGEX "^-W") - #endif() + cmake_check_common_init_args(_CSR) if(NOT CMAKE_REQUIRED_QUIET) message(CHECK_START "Performing Test ${_var}") @@ -129,16 +73,16 @@ function(CMAKE_CHECK_SOURCE_RUNS _lang _source _var) try_run(${_var}_EXITCODE ${_var}_COMPILED SOURCE_FROM_VAR "src.${_SRC_EXT}" _source COMPILE_DEFINITIONS -D${_var} ${CMAKE_REQUIRED_DEFINITIONS} - ${CHECK_${_lang}_SOURCE_COMPILES_ADD_LINK_OPTIONS} - ${CHECK_${_lang}_SOURCE_COMPILES_ADD_LIBRARIES} + ${_CSR_ADD_LINK_OPTIONS} + ${_CSR_ADD_LINK_LIBRARIES} CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${CMAKE_REQUIRED_FLAGS} ${_CSR_EXTRA_CMAKE_ARGUMENTS} - -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH} - "${CHECK_${_lang}_SOURCE_COMPILES_ADD_INCLUDES}" - "${_CSR_LINK_DIRECTORIES}" + -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH} + "${_CSR_INCLUDE_DIRECTORIES}" + "${_CSR_LINK_DIRECTORIES}" ) - unset(_CSR_LINK_DIRECTORIES) + # if it did not compile make the return value fail code of 1 if(NOT ${_var}_COMPILED) set(${_var}_EXITCODE 1)