mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-18 17:31:57 +08:00
CheckCompilerFlag: unified way to check compiler flags per language
This commit is contained in:

committed by
Brad King

parent
0cd1ef0932
commit
90dead024c
@@ -45,6 +45,7 @@ These modules are loaded using the :command:`include` command.
|
||||
/module/CheckOBJCXXSourceRuns
|
||||
/module/CheckPIESupported
|
||||
/module/CheckPrototypeDefinition
|
||||
/module/CheckCompilerFlag
|
||||
/module/CheckSourceCompiles
|
||||
/module/CheckSourceRuns
|
||||
/module/CheckStructHasMember
|
||||
|
1
Help/module/CheckCompilerFlag.rst
Normal file
1
Help/module/CheckCompilerFlag.rst
Normal file
@@ -0,0 +1 @@
|
||||
.. cmake-module:: ../../Modules/CheckCompilerFlag.cmake
|
@@ -8,3 +8,7 @@ check-source-modules
|
||||
* The :module:`CheckSourceRuns` module has been added to
|
||||
generalize :module:`CheckCSourceRuns` and
|
||||
:module:`CheckCXXSourceRuns` to more languages.
|
||||
|
||||
* The :module:`CheckCompilerFlag` module has been added to
|
||||
generalize :module:`CheckCCompilerFlag` and
|
||||
:module:`CheckCXXCompilerFlag` to more languages.
|
||||
|
@@ -34,24 +34,8 @@ effect or even a specific one is beyond the scope of this module.
|
||||
|
||||
include_guard(GLOBAL)
|
||||
include(CheckCSourceCompiles)
|
||||
include(CMakeCheckCompilerFlagCommonPatterns)
|
||||
include(CheckCompilerFlag)
|
||||
|
||||
function(check_c_compiler_flag _flag _var)
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "${_flag}")
|
||||
|
||||
# Normalize locale during test compilation.
|
||||
set(_locale_vars LC_ALL LC_MESSAGES LANG)
|
||||
foreach(v IN LISTS _locale_vars)
|
||||
set(_locale_vars_saved_${v} "$ENV{${v}}")
|
||||
set(ENV{${v}} C)
|
||||
endforeach()
|
||||
check_compiler_flag_common_patterns(_common_patterns)
|
||||
check_c_source_compiles("int main(void) { return 0; }" ${_var}
|
||||
# Some compilers do not fail with a bad flag
|
||||
FAIL_REGEX "command line option .* is valid for .* but not for C" # GNU
|
||||
${_common_patterns}
|
||||
)
|
||||
foreach(v IN LISTS _locale_vars)
|
||||
set(ENV{${v}} ${_locale_vars_saved_${v}})
|
||||
endforeach()
|
||||
endfunction()
|
||||
macro (CHECK_C_COMPILER_FLAG _FLAG _RESULT)
|
||||
check_compiler_flag(C "${_FLAG}" ${_RESULT})
|
||||
endmacro ()
|
||||
|
@@ -34,24 +34,8 @@ effect or even a specific one is beyond the scope of this module.
|
||||
|
||||
include_guard(GLOBAL)
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(CMakeCheckCompilerFlagCommonPatterns)
|
||||
include(CheckCompilerFlag)
|
||||
|
||||
function(check_cxx_compiler_flag _flag _var)
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "${_flag}")
|
||||
|
||||
# Normalize locale during test compilation.
|
||||
set(_locale_vars LC_ALL LC_MESSAGES LANG)
|
||||
foreach(v IN LISTS _locale_vars)
|
||||
set(_locale_vars_saved_${v} "$ENV{${v}}")
|
||||
set(ENV{${v}} C)
|
||||
endforeach()
|
||||
check_compiler_flag_common_patterns(_common_patterns)
|
||||
check_cxx_source_compiles("int main() { return 0; }" ${_var}
|
||||
# Some compilers do not fail with a bad flag
|
||||
FAIL_REGEX "command line option .* is valid for .* but not for C\\\\+\\\\+" # GNU
|
||||
${_common_patterns}
|
||||
)
|
||||
foreach(v IN LISTS _locale_vars)
|
||||
set(ENV{${v}} ${_locale_vars_saved_${v}})
|
||||
endforeach()
|
||||
endfunction()
|
||||
macro (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT)
|
||||
check_compiler_flag(CXX "${_FLAG}" ${_RESULT})
|
||||
endmacro ()
|
||||
|
105
Modules/CheckCompilerFlag.cmake
Normal file
105
Modules/CheckCompilerFlag.cmake
Normal file
@@ -0,0 +1,105 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
CheckCompilerFlag
|
||||
---------------------
|
||||
|
||||
.. versionadded:: 3.19
|
||||
|
||||
Check whether the compiler supports a given flag.
|
||||
|
||||
.. command:: check_compiler_flag
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
check_compiler_flag(<lang> <flag> <var>)
|
||||
|
||||
Check that the ``<flag>`` is accepted by the compiler without a diagnostic.
|
||||
Stores the result in an internal cache entry named ``<var>``.
|
||||
|
||||
This command temporarily sets the ``CMAKE_REQUIRED_DEFINITIONS`` variable
|
||||
and calls the ``check_source_compiles(<LANG>`` function from the
|
||||
:module:`CheckSourceCompiles` module. See documentation of that
|
||||
module for a listing of variables that can otherwise modify the build.
|
||||
|
||||
A positive result from this check indicates only that the compiler did not
|
||||
issue a diagnostic message when given the flag. Whether the flag has any
|
||||
effect or even a specific one is beyond the scope of this module.
|
||||
|
||||
.. note::
|
||||
Since the :command:`try_compile` command forwards flags from variables
|
||||
like :variable:`CMAKE_<LANG>_FLAGS <CMAKE_<LANG>_FLAGS>`, unknown flags
|
||||
in such variables may cause a false negative for this check.
|
||||
#]=======================================================================]
|
||||
|
||||
include_guard(GLOBAL)
|
||||
include(CheckSourceCompiles)
|
||||
include(CMakeCheckCompilerFlagCommonPatterns)
|
||||
|
||||
cmake_policy(PUSH)
|
||||
cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
|
||||
cmake_policy(SET CMP0057 NEW) # if() supports IN_LIST
|
||||
|
||||
function(CHECK_COMPILER_FLAG _lang _flag _var)
|
||||
|
||||
if(_lang STREQUAL C)
|
||||
set(_lang_src "int main(void) { return 0; }")
|
||||
set(_lang_fail_regex FAIL_REGEX "command line option .* is valid for .* but not for C")
|
||||
elseif(_lang STREQUAL CXX)
|
||||
set(_lang_src "int main() { return 0; }")
|
||||
set(_lang_fail_regex FAIL_REGEX "command line option .* is valid for .* but not for C\\+\\+")
|
||||
elseif(_lang STREQUAL Fortran)
|
||||
set(_lang_src " program test\n stop\n end program")
|
||||
set(_lang_fail_regex FAIL_REGEX "command line option .* is valid for .* but not for Fortran")
|
||||
elseif(_lang STREQUAL OBJC)
|
||||
set(_lang_src [=[
|
||||
#ifndef __OBJC__
|
||||
# error "Not an Objective-C compiler"
|
||||
#endif
|
||||
int main(void) { return 0; }]=])
|
||||
set(_lang_fail_regex FAIL_REGEX "command line option .* is valid for .* but not for Objective-C" # GNU
|
||||
FAIL_REGEX "argument unused during compilation: .*") # Clang
|
||||
elseif(_lang STREQUAL OBJCXX)
|
||||
set(_lang_src [=[
|
||||
#ifndef __OBJC__
|
||||
# error "Not an Objective-C++ compiler"
|
||||
#endif
|
||||
int main(void) { return 0; }]=])
|
||||
set(_lang_fail_regex FAIL_REGEX "command line option .* is valid for .* but not for Objective-C\\+\\+" # GNU
|
||||
FAIL_REGEX "argument unused during compilation: .*") # Clang
|
||||
else()
|
||||
message (SEND_ERROR "check_compiler_flag: ${_lang}: unknown language.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
get_property (_supported_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||
if (NOT _lang IN_LIST _supported_languages)
|
||||
message (SEND_ERROR "check_compiler_flag: ${_lang}: needs to be enabled before use.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_DEFINITIONS ${_flag})
|
||||
|
||||
# Normalize locale during test compilation.
|
||||
set(_locale_vars LC_ALL LC_MESSAGES LANG)
|
||||
foreach(v IN LISTS _locale_vars)
|
||||
set(_locale_vars_saved_${v} "$ENV{${v}}")
|
||||
set(ENV{${v}} C)
|
||||
endforeach()
|
||||
|
||||
check_compiler_flag_common_patterns(_common_patterns)
|
||||
check_source_compiles(${_lang}
|
||||
"${_lang_src}"
|
||||
${_var}
|
||||
${_lang_fail_regex}
|
||||
${_common_patterns}
|
||||
)
|
||||
|
||||
foreach(v IN LISTS _locale_vars)
|
||||
set(ENV{${v}} ${_locale_vars_saved_${v}})
|
||||
endforeach()
|
||||
set(${_var} "${${_var}}" PARENT_SCOPE)
|
||||
endfunction ()
|
||||
|
||||
cmake_policy(POP)
|
@@ -36,30 +36,8 @@ effect or even a specific one is beyond the scope of this module.
|
||||
|
||||
include_guard(GLOBAL)
|
||||
include(CheckFortranSourceCompiles)
|
||||
include(CMakeCheckCompilerFlagCommonPatterns)
|
||||
include(CheckCompilerFlag)
|
||||
|
||||
macro (CHECK_Fortran_COMPILER_FLAG _FLAG _RESULT)
|
||||
set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
|
||||
|
||||
# Normalize locale during test compilation.
|
||||
set(_CheckFortranCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG)
|
||||
foreach(v ${_CheckFortranCompilerFlag_LOCALE_VARS})
|
||||
set(_CheckFortranCompilerFlag_SAVED_${v} "$ENV{${v}}")
|
||||
set(ENV{${v}} C)
|
||||
endforeach()
|
||||
CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckFortranCompilerFlag_COMMON_PATTERNS)
|
||||
CHECK_Fortran_SOURCE_COMPILES(" program test\n stop\n end program" ${_RESULT}
|
||||
# Some compilers do not fail with a bad flag
|
||||
FAIL_REGEX "command line option .* is valid for .* but not for Fortran" # GNU
|
||||
${_CheckFortranCompilerFlag_COMMON_PATTERNS}
|
||||
)
|
||||
foreach(v ${_CheckFortranCompilerFlag_LOCALE_VARS})
|
||||
set(ENV{${v}} ${_CheckFortranCompilerFlag_SAVED_${v}})
|
||||
unset(_CheckFortranCompilerFlag_SAVED_${v})
|
||||
endforeach()
|
||||
unset(_CheckFortranCompilerFlag_LOCALE_VARS)
|
||||
unset(_CheckFortranCompilerFlag_COMMON_PATTERNS)
|
||||
|
||||
set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
|
||||
macro (CHECK_FORTRAN_COMPILER_FLAG _FLAG _RESULT)
|
||||
check_compiler_flag(Fortran "${_FLAG}" ${_RESULT})
|
||||
endmacro ()
|
||||
|
@@ -36,31 +36,8 @@ effect or even a specific one is beyond the scope of this module.
|
||||
|
||||
include_guard(GLOBAL)
|
||||
include(CheckOBJCSourceCompiles)
|
||||
include(CMakeCheckCompilerFlagCommonPatterns)
|
||||
include(CheckCompilerFlag)
|
||||
|
||||
macro (CHECK_OBJC_COMPILER_FLAG _FLAG _RESULT)
|
||||
set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
|
||||
|
||||
# Normalize locale during test compilation.
|
||||
set(_CheckOBJCCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG)
|
||||
foreach(v ${_CheckOBJCCompilerFlag_LOCALE_VARS})
|
||||
set(_CheckOBJCCompilerFlag_SAVED_${v} "$ENV{${v}}")
|
||||
set(ENV{${v}} OBJC)
|
||||
endforeach()
|
||||
CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckOBJCCompilerFlag_COMMON_PATTERNS)
|
||||
CHECK_OBJC_SOURCE_COMPILES("#ifndef __OBJC__\n# error \"Not an Objective-C compiler\"\n#endif\nint main(void) { return 0; }" ${_RESULT}
|
||||
# Some compilers do not fail with a bad flag
|
||||
FAIL_REGEX "command line option .* is valid for .* but not for Objective-C" # GNU
|
||||
FAIL_REGEX "argument unused during compilation: .*" # Clang
|
||||
${_CheckOBJCCompilerFlag_COMMON_PATTERNS}
|
||||
)
|
||||
foreach(v ${_CheckOBJCCompilerFlag_LOCALE_VARS})
|
||||
set(ENV{${v}} ${_CheckOBJCCompilerFlag_SAVED_${v}})
|
||||
unset(_CheckOBJCCompilerFlag_SAVED_${v})
|
||||
endforeach()
|
||||
unset(_CheckOBJCCompilerFlag_LOCALE_VARS)
|
||||
unset(_CheckOBJCCompilerFlag_COMMON_PATTERNS)
|
||||
|
||||
set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
|
||||
check_compiler_flag(OBJC "${_FLAG}" ${_RESULT})
|
||||
endmacro ()
|
||||
|
@@ -36,31 +36,8 @@ effect or even a specific one is beyond the scope of this module.
|
||||
|
||||
include_guard(GLOBAL)
|
||||
include(CheckOBJCXXSourceCompiles)
|
||||
include(CMakeCheckCompilerFlagCommonPatterns)
|
||||
include(CheckCompilerFlag)
|
||||
|
||||
macro (CHECK_OBJCXX_COMPILER_FLAG _FLAG _RESULT)
|
||||
set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
|
||||
|
||||
# Normalize locale during test compilation.
|
||||
set(_CheckOBJCXXCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG)
|
||||
foreach(v ${_CheckOBJCXXCompilerFlag_LOCALE_VARS})
|
||||
set(_CheckOBJCXXCompilerFlag_SAVED_${v} "$ENV{${v}}")
|
||||
set(ENV{${v}} OBJCXX)
|
||||
endforeach()
|
||||
CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckOBJCXXCompilerFlag_COMMON_PATTERNS)
|
||||
CHECK_OBJCXX_SOURCE_COMPILES("#ifndef __OBJC__\n# error \"Not an Objective-C++ compiler\"\n#endif\nint main(void) { return 0; }" ${_RESULT}
|
||||
# Some compilers do not fail with a bad flag
|
||||
FAIL_REGEX "command line option .* is valid for .* but not for Objective-C\\\\+\\\\+" # GNU
|
||||
FAIL_REGEX "argument unused during compilation: .*" # Clang
|
||||
${_CheckOBJCXXCompilerFlag_COMMON_PATTERNS}
|
||||
)
|
||||
foreach(v ${_CheckOBJCXXCompilerFlag_LOCALE_VARS})
|
||||
set(ENV{${v}} ${_CheckOBJCXXCompilerFlag_SAVED_${v}})
|
||||
unset(_CheckOBJCXXCompilerFlag_SAVED_${v})
|
||||
endforeach()
|
||||
unset(_CheckOBJCXXCompilerFlag_LOCALE_VARS)
|
||||
unset(_CheckOBJCXXCompilerFlag_COMMON_PATTERNS)
|
||||
|
||||
set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
|
||||
check_compiler_flag(OBJCXX "${_FLAG}" ${_RESULT})
|
||||
endmacro ()
|
||||
|
Reference in New Issue
Block a user