diff --git a/cmake/GNUWarnings.cmake b/cmake/GNUWarnings.cmake new file mode 100644 index 00000000..62362ed2 --- /dev/null +++ b/cmake/GNUWarnings.cmake @@ -0,0 +1,94 @@ +# A CMake module to use GNU warning flags with C and C++ +# and detect their availability. +# +# Usage: +# gw_warn(...) +# gw_warn_c(...) +# gw_warn_cxx(...) +# gw_target_warn( ...) +# gw_target_warn_c( ...) +# gw_target_warn_cxx( ...) +# +# Copyright 2020, Jean Pierre Cimalando +# SPDX-License-Identifier: BSD-2-Clause + +function(gw_warn) + gw_warn_c(${ARGN}) + gw_warn_cxx(${ARGN}) +endfunction() + +function(gw_warn_c) + if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") + foreach(flag ${ARGN}) + _gw_check_c_flag_is_silent("${flag}") + if("${GNUWARNINGS_C_FLAG_${flag}_SILENT}") + add_compile_options("$<$:${flag}>") + endif() + endforeach() + endif() +endfunction() + +function(gw_warn_cxx) + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + foreach(flag ${ARGN}) + _gw_check_cxx_flag_is_silent("${flag}") + if("${GNUWARNINGS_CXX_FLAG_${flag}_SILENT}") + add_compile_options("$<$:${flag}>") + endif() + endforeach() + endif() +endfunction() + +function(gw_target_warn TARGET DOMAIN) + gw_target_warn_c("${TARGET}" "${DOMAIN}" ${ARGN}) + gw_target_warn_cxx("${TARGET}" "${DOMAIN}" ${ARGN}) +endfunction() + +function(gw_target_warn_c TARGET DOMAIN) + if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") + foreach(flag ${ARGN}) + _gw_check_c_flag_is_silent("${flag}") + if("${GNUWARNINGS_C_FLAG_${flag}_SILENT}") + target_compile_options("${TARGET}" "${DOMAIN}" "$<$:${flag}>") + endif() + endforeach() + endif() +endfunction() + +function(gw_target_warn_cxx TARGET DOMAIN) + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + foreach(flag ${ARGN}) + _gw_check_cxx_flag_is_silent("${flag}") + if("${GNUWARNINGS_CXX_FLAG_${flag}_SILENT}") + target_compile_options("${TARGET}" "${DOMAIN}" "$<$:${flag}>") + endif() + endforeach() + endif() +endfunction() + +function(_gw_check_c_flag_is_silent FLAG) + if(NOT DEFINED "GNUWARNINGS_C_FLAG_${FLAG}_SILENT") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CheckGNUWarning.c" "") + _gw_check_command_succeeds_silently(_result "${CMAKE_C_COMPILER}" "${FLAG}" "-c" "-o" "${CMAKE_CURRENT_BINARY_DIR}/CheckGNUWarning.o" "${CMAKE_CURRENT_BINARY_DIR}/CheckGNUWarning.c") + message(STATUS "Have C warning ${flag}: ${_result}") + set("GNUWARNINGS_C_FLAG_${FLAG}_SILENT" "${_result}" CACHE BOOL "Have C warning ${flag}") + endif() +endfunction() + +function(_gw_check_cxx_flag_is_silent FLAG) + if(NOT DEFINED "GNUWARNINGS_CXX_FLAG_${FLAG}_SILENT") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CheckGNUWarning.cpp" "") + _gw_check_command_succeeds_silently(_result "${CMAKE_CXX_COMPILER}" "${FLAG}" "-c" "-o" "${CMAKE_CURRENT_BINARY_DIR}/CheckGNUWarning.o" "${CMAKE_CURRENT_BINARY_DIR}/CheckGNUWarning.cpp") + message(STATUS "Have C++ warning ${flag}: ${_result}") + set("GNUWARNINGS_CXX_FLAG_${FLAG}_SILENT" "${_result}" CACHE BOOL "Have C++ warning ${flag}") + endif() +endfunction() + +function(_gw_check_command_succeeds_silently RESULT_VARIABLE) + execute_process(COMMAND ${ARGN} RESULT_VARIABLE _result OUTPUT_VARIABLE _output ERROR_VARIABLE _error OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE) + if(_result EQUAL 0 AND _output STREQUAL "" AND _error STREQUAL "") + set("${RESULT_VARIABLE}" TRUE PARENT_SCOPE) + else() + set("${RESULT_VARIABLE}" FALSE PARENT_SCOPE) + endif() +endfunction()