Skip to content
Snippets Groups Projects
Commit 90dead02 authored by Robert Maynard's avatar Robert Maynard Committed by Brad King
Browse files

CheckCompilerFlag: unified way to check compiler flags per language

parent 0cd1ef09
No related branches found
No related tags found
No related merge requests found
......@@ -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
......
.. 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)
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()
include(CheckCompilerFlag)
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)
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()
include(CheckCompilerFlag)
macro (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT)
check_compiler_flag(CXX "${_FLAG}" ${_RESULT})
endmacro ()
# 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 ()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment