mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
The `CMAKE_REQUIRED_FLAGS` variable, used by the various entry points to
`cmake_check_source_{compiles,runs}`, specifies that flags shall not be
separated by semicolons. This is because the way in which it is passed
to the child `cmake` process means that, when considered as a list (with
semicolon separated items), only the first item is actually used as
compile flags, with any additional items actually seen as arguments to
the child `cmake` process. While this usage is unsupported, if invoked
accidentally, flags starting with `-W` were silently ignored by CMake.
However, CMake 4.4 newly complains about unrecognized warning
categories, which means that uses which were silently broken now result
in a hard error.
In the longer term, it would be helpful to introduce a policy to repair
improper use of semicolons in `CMAKE_REQUIRED_FLAGS` in order to do what
the user probably meant. However, for various reasons, we do not want to
introduce a policy to CMake 4.4 at this time, and anyway, the policy
won't help users that haven't enabled it. Therefore, alter the 'check
source' functions to detect arguments being passed to `cmake` rather
than the compiler, and remove any such that start with `-W`. This
removes any arguments that newly cause errors starting with CMake 4.4,
while not otherwise altering behavior in case any users were abusing
this implementation quirk.
Strictly speaking, this means that users can no longer abuse this quirk
to alter CMake's diagnostics. However, the only case in which this
should be observable is if the user is already abusing the quirk to
inject their own CMake logic into the CMake-provided test projects.
Since this was never supported, anyone doing that can keep the pieces.
Issue: #27901
Fixes: #27893
174 lines
5.8 KiB
CMake
174 lines
5.8 KiB
CMake
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
# file LICENSE.rst or https://cmake.org/licensing for details.
|
|
|
|
include_guard(GLOBAL)
|
|
|
|
function(CMAKE_CHECK_SOURCE_COMPILES _lang _source _var)
|
|
if(NOT DEFINED "${_var}")
|
|
set(_lang_filename "src")
|
|
if(_lang STREQUAL "C")
|
|
set(_lang_textual "C")
|
|
set(_lang_ext "c")
|
|
elseif(_lang STREQUAL "CXX")
|
|
set(_lang_textual "C++")
|
|
set(_lang_ext "cxx")
|
|
elseif(_lang STREQUAL "CUDA")
|
|
set(_lang_textual "CUDA")
|
|
set(_lang_ext "cu")
|
|
elseif(_lang STREQUAL "Fortran")
|
|
set(_lang_textual "Fortran")
|
|
set(_lang_ext "F90")
|
|
elseif(_lang STREQUAL "HIP")
|
|
set(_lang_textual "HIP")
|
|
set(_lang_ext "hip")
|
|
elseif(_lang STREQUAL "ISPC")
|
|
set(_lang_textual "ISPC")
|
|
set(_lang_ext "ispc")
|
|
elseif(_lang STREQUAL "OBJC")
|
|
set(_lang_textual "Objective-C")
|
|
set(_lang_ext "m")
|
|
elseif(_lang STREQUAL "OBJCXX")
|
|
set(_lang_textual "Objective-C++")
|
|
set(_lang_ext "mm")
|
|
elseif(_lang STREQUAL "Swift")
|
|
set(_lang_textual "Swift")
|
|
set(_lang_ext "swift")
|
|
if (NOT DEFINED CMAKE_TRY_COMPILE_TARGET_TYPE
|
|
OR CMAKE_TRY_COMPILE_TARGET_TYPE STREQUAL "EXECUTABLE")
|
|
set(_lang_filename "main")
|
|
endif()
|
|
else()
|
|
message (SEND_ERROR "check_source_compiles: ${_lang}: unknown language.")
|
|
return()
|
|
endif()
|
|
|
|
get_property (_supported_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
|
|
if (NOT _lang IN_LIST _supported_languages)
|
|
message (SEND_ERROR "check_source_compiles: ${_lang}: needs to be enabled before use.")
|
|
return()
|
|
endif()
|
|
|
|
set(_FAIL_REGEX)
|
|
set(_SRC_EXT)
|
|
set(_key)
|
|
foreach(arg ${ARGN})
|
|
if("${arg}" MATCHES "^(FAIL_REGEX|SRC_EXT|OUTPUT_VARIABLE)$")
|
|
set(_key "${arg}")
|
|
elseif(_key STREQUAL "FAIL_REGEX")
|
|
list(APPEND _FAIL_REGEX "${arg}")
|
|
elseif(_key STREQUAL "SRC_EXT")
|
|
set(_SRC_EXT "${arg}")
|
|
set(_key "")
|
|
elseif(_key STREQUAL "OUTPUT_VARIABLE")
|
|
set(_OUTPUT_VARIABLE "${arg}")
|
|
set(_key "")
|
|
else()
|
|
message(FATAL_ERROR "Unknown argument:\n ${arg}\n")
|
|
endif()
|
|
endforeach()
|
|
|
|
if(NOT _SRC_EXT)
|
|
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()
|
|
|
|
if(NOT CMAKE_REQUIRED_QUIET)
|
|
message(CHECK_START "Performing Test ${_var}")
|
|
endif()
|
|
string(APPEND _source "\n")
|
|
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}
|
|
CMAKE_FLAGS
|
|
-DCOMPILE_DEFINITIONS:STRING=${CMAKE_REQUIRED_FLAGS}
|
|
${_CSC_EXTRA_CMAKE_ARGUMENTS}
|
|
"${CHECK_${LANG}_SOURCE_COMPILES_ADD_INCLUDES}"
|
|
"${_CSC_LINK_DIRECTORIES}"
|
|
OUTPUT_VARIABLE OUTPUT)
|
|
unset(_CSC_LINK_DIRECTORIES)
|
|
|
|
foreach(_regex ${_FAIL_REGEX})
|
|
if("${OUTPUT}" MATCHES "${_regex}")
|
|
set(${_var} 0)
|
|
endif()
|
|
endforeach()
|
|
|
|
if (_OUTPUT_VARIABLE)
|
|
set(${_OUTPUT_VARIABLE} "${OUTPUT}" PARENT_SCOPE)
|
|
endif()
|
|
|
|
if(${_var})
|
|
set(${_var} 1 CACHE INTERNAL "Test ${_var}")
|
|
if(NOT CMAKE_REQUIRED_QUIET)
|
|
message(CHECK_PASS "Success")
|
|
endif()
|
|
else()
|
|
if(NOT CMAKE_REQUIRED_QUIET)
|
|
message(CHECK_FAIL "Failed")
|
|
endif()
|
|
set(${_var} "" CACHE INTERNAL "Test ${_var}")
|
|
endif()
|
|
endif()
|
|
endfunction()
|