diff --git a/Modules/Internal/CheckSourceCompiles.cmake b/Modules/Internal/CheckSourceCompiles.cmake index e5c0ef12de..18ee7d17ae 100644 --- a/Modules/Internal/CheckSourceCompiles.cmake +++ b/Modules/Internal/CheckSourceCompiles.cmake @@ -97,6 +97,40 @@ function(CMAKE_CHECK_SOURCE_COMPILES _lang _source _var) 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() + if(NOT CMAKE_REQUIRED_QUIET) message(CHECK_START "Performing Test ${_var}") endif() @@ -106,7 +140,9 @@ function(CMAKE_CHECK_SOURCE_COMPILES _lang _source _var) COMPILE_DEFINITIONS -D${_var} ${CMAKE_REQUIRED_DEFINITIONS} ${CHECK_${LANG}_SOURCE_COMPILES_ADD_LINK_OPTIONS} ${CHECK_${LANG}_SOURCE_COMPILES_ADD_LIBRARIES} - CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${CMAKE_REQUIRED_FLAGS} + CMAKE_FLAGS + -DCOMPILE_DEFINITIONS:STRING=${CMAKE_REQUIRED_FLAGS} + ${_CSC_EXTRA_CMAKE_ARGUMENTS} "${CHECK_${LANG}_SOURCE_COMPILES_ADD_INCLUDES}" "${_CSC_LINK_DIRECTORIES}" OUTPUT_VARIABLE OUTPUT) diff --git a/Modules/Internal/CheckSourceRuns.cmake b/Modules/Internal/CheckSourceRuns.cmake index 5df37e0710..a698e867ce 100644 --- a/Modules/Internal/CheckSourceRuns.cmake +++ b/Modules/Internal/CheckSourceRuns.cmake @@ -88,6 +88,40 @@ function(CMAKE_CHECK_SOURCE_RUNS _lang _source _var) 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() + if(NOT CMAKE_REQUIRED_QUIET) message(CHECK_START "Performing Test ${_var}") endif() @@ -97,7 +131,9 @@ function(CMAKE_CHECK_SOURCE_RUNS _lang _source _var) COMPILE_DEFINITIONS -D${_var} ${CMAKE_REQUIRED_DEFINITIONS} ${CHECK_${_lang}_SOURCE_COMPILES_ADD_LINK_OPTIONS} ${CHECK_${_lang}_SOURCE_COMPILES_ADD_LIBRARIES} - CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${CMAKE_REQUIRED_FLAGS} + 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}" diff --git a/Tests/RunCMake/CheckSourceCompiles/Extra.cmake b/Tests/RunCMake/CheckSourceCompiles/Extra.cmake new file mode 100644 index 0000000000..edabced92b --- /dev/null +++ b/Tests/RunCMake/CheckSourceCompiles/Extra.cmake @@ -0,0 +1 @@ +message(WARNING "Hello from Extra.cmake") diff --git a/Tests/RunCMake/CheckSourceCompiles/Issue27893.cmake b/Tests/RunCMake/CheckSourceCompiles/Issue27893.cmake new file mode 100644 index 0000000000..ec3dfe8600 --- /dev/null +++ b/Tests/RunCMake/CheckSourceCompiles/Issue27893.cmake @@ -0,0 +1,9 @@ +enable_language (C) +include(CheckSourceCompiles) + +# If CMAKE_REQUIRED_FLAGS is a list, all items but the first are passed as +# arguments to 'cmake'. This was never supported, but arguments that start with +# '-W' were silently ignored by CMake < 4.4. Starting with 4.4, CMake complains +# about unknown warning flags. Therefore, for compatibility, we strip them. +set(CMAKE_REQUIRED_FLAGS -DFOO -Wseen-by-cmake) +check_source_compiles(C "int main() {return 0;}" SHOULD_BUILD) diff --git a/Tests/RunCMake/CheckSourceCompiles/RequiredFlags-stderr.txt b/Tests/RunCMake/CheckSourceCompiles/RequiredFlags-stderr.txt new file mode 100644 index 0000000000..c7e01537bd --- /dev/null +++ b/Tests/RunCMake/CheckSourceCompiles/RequiredFlags-stderr.txt @@ -0,0 +1,7 @@ +CMake Warning at [^ +]*/Tests/RunCMake/CheckSourceCompiles/Extra\.cmake:[0-9]+ \(message\): + Hello from Extra\.cmake +Call Stack \(most recent call first\): + [^ +]*/Tests/RunCMake/CheckSourceCompiles/RequiredFlags-build/CMakeFiles/CMakeScratch/TryCompile-[^ +]*/CMakeLists\.txt:[0-9]+ \(project\) diff --git a/Tests/RunCMake/CheckSourceCompiles/RequiredFlags.cmake b/Tests/RunCMake/CheckSourceCompiles/RequiredFlags.cmake new file mode 100644 index 0000000000..3d10f5dd4b --- /dev/null +++ b/Tests/RunCMake/CheckSourceCompiles/RequiredFlags.cmake @@ -0,0 +1,17 @@ +enable_language (C) +include(CheckSourceCompiles) + +# If CMAKE_REQUIRED_FLAGS is a list, all items but the first are passed as +# arguments to 'cmake'. For backwards compatibility, test that this works. +# +# It would be nice if we could also test that a literal semicolon makes it +# through. Unfortunately, that needs different levels of escaping depending on +# the generator, because the build rule may or may not be subject to shell +# evaluation. +set(CMAKE_REQUIRED_FLAGS + "-DFUNC=main" + "-DCMAKE_PROJECT_INCLUDE=${CMAKE_CURRENT_LIST_DIR}/Extra.cmake") +check_source_compiles(C "int FUNC() {return 0;}" SHOULD_BUILD) +if(NOT SHOULD_BUILD) + message(SEND_ERROR "Test fail for valid C source.") +endif() diff --git a/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake b/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake index afee71e30e..6bfafdf75f 100644 --- a/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake +++ b/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake @@ -5,6 +5,9 @@ run_cmake(NonExistentLanguage) run_cmake(UnknownArgument) run_cmake(MultipleLanguages) +run_cmake(RequiredFlags) +run_cmake(Issue27893) + run_cmake(CheckCSourceCompiles) run_cmake(CheckCXXSourceCompiles) run_cmake(CheckSourceCompilesC) diff --git a/Tests/RunCMake/CheckSourceRuns/Extra.cmake b/Tests/RunCMake/CheckSourceRuns/Extra.cmake new file mode 100644 index 0000000000..edabced92b --- /dev/null +++ b/Tests/RunCMake/CheckSourceRuns/Extra.cmake @@ -0,0 +1 @@ +message(WARNING "Hello from Extra.cmake") diff --git a/Tests/RunCMake/CheckSourceRuns/Issue27893.cmake b/Tests/RunCMake/CheckSourceRuns/Issue27893.cmake new file mode 100644 index 0000000000..227d38d216 --- /dev/null +++ b/Tests/RunCMake/CheckSourceRuns/Issue27893.cmake @@ -0,0 +1,9 @@ +enable_language (C) +include(CheckSourceRuns) + +# If CMAKE_REQUIRED_FLAGS is a list, all items but the first are passed as +# arguments to 'cmake'. This was never supported, but arguments that start with +# '-W' were silently ignored by CMake < 4.4. Starting with 4.4, CMake complains +# about unknown warning flags. Therefore, for compatibility, we strip them. +set(CMAKE_REQUIRED_FLAGS -DFOO -Wseen-by-cmake) +check_source_runs(C "int main() {return 0;}" SHOULD_RUN) diff --git a/Tests/RunCMake/CheckSourceRuns/RequiredFlags-stderr.txt b/Tests/RunCMake/CheckSourceRuns/RequiredFlags-stderr.txt new file mode 100644 index 0000000000..341d24407c --- /dev/null +++ b/Tests/RunCMake/CheckSourceRuns/RequiredFlags-stderr.txt @@ -0,0 +1,7 @@ +CMake Warning at [^ +]*/Tests/RunCMake/CheckSourceRuns/Extra\.cmake:[0-9]+ \(message\): + Hello from Extra\.cmake +Call Stack \(most recent call first\): + [^ +]*/Tests/RunCMake/CheckSourceRuns/RequiredFlags-build/CMakeFiles/CMakeScratch/TryCompile-[^ +]*/CMakeLists\.txt:[0-9]+ \(project\) diff --git a/Tests/RunCMake/CheckSourceRuns/RequiredFlags.cmake b/Tests/RunCMake/CheckSourceRuns/RequiredFlags.cmake new file mode 100644 index 0000000000..c54b70de67 --- /dev/null +++ b/Tests/RunCMake/CheckSourceRuns/RequiredFlags.cmake @@ -0,0 +1,17 @@ +enable_language (C) +include(CheckSourceRuns) + +# If CMAKE_REQUIRED_FLAGS is a list, all items but the first are passed as +# arguments to 'cmake'. For backwards compatibility, test that this works. +# +# It would be nice if we could also test that a literal semicolon makes it +# through. Unfortunately, that needs different levels of escaping depending on +# the generator, because the build rule may or may not be subject to shell +# evaluation. +set(CMAKE_REQUIRED_FLAGS + "-DFUNC=main" + "-DCMAKE_PROJECT_INCLUDE=${CMAKE_CURRENT_LIST_DIR}/Extra.cmake") +check_source_runs(C "int FUNC() {return 0;}" SHOULD_RUN) +if(NOT SHOULD_RUN) + message(SEND_ERROR "C check_source_runs failed for valid C executable.") +endif() diff --git a/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake b/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake index 64cecfc0e5..9c51a6be9a 100644 --- a/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake +++ b/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake @@ -4,6 +4,9 @@ run_cmake(NotEnabledLanguage) run_cmake(NonExistentLanguage) run_cmake(UnknownArgument) +run_cmake(RequiredFlags) +run_cmake(Issue27893) + run_cmake(CheckCSourceRuns) run_cmake(CheckCXXSourceRuns) run_cmake(CheckSourceRunsC)