Index: docs/module/ECMAddCompilerFlag.rst =================================================================== --- /dev/null +++ docs/module/ECMAddCompilerFlag.rst @@ -0,0 +1 @@ +.. ecm-module:: ../../modules/ECMAddCompilerFlag.cmake Index: kde-modules/KDECompilerSettings.cmake =================================================================== --- kde-modules/KDECompilerSettings.cmake +++ kde-modules/KDECompilerSettings.cmake @@ -186,6 +186,8 @@ # Language and toolchain features ############################################################ +include(ECMAddCompilerFlag) + # Pick sensible versions of the C and C++ standards. # Note that MSVC does not have equivalent flags; the features are either # supported or they are not. @@ -369,20 +371,14 @@ # Make some warnings errors set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=return-type") endif() -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR - (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)) - # -Wvla: use of variable-length arrays (an extension to C++) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wvla") -endif() -if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) OR - (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)) - include(CheckCXXCompilerFlag) - check_cxx_compiler_flag(-Wdate-time HAVE_DATE_TIME) - if (HAVE_DATE_TIME) - # -Wdate-time: warn if we use __DATE__ or __TIME__ (we want to be able to reproduce the exact same binary) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wdate-time") - endif() -endif() +ecm_add_cxx_compiler_flags_if_supported(FLAGS -Wvla + SUPPORTED_IF CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR + (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5) + QUERY_IF APPLE) +ecm_add_cxx_compiler_flags_if_supported(FLAGS -Wdate-time + SUPPORTED_IF (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) OR + (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5) + QUERY_IF APPLE) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0.0") @@ -492,12 +488,13 @@ set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--export-all-symbols") endif() -if (CMAKE_GENERATOR STREQUAL "Ninja" AND - ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR - (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5))) +if (CMAKE_GENERATOR STREQUAL "Ninja") # Force colored warnings in Ninja's output, if the compiler has -fdiagnostics-color support. # Rationale in https://github.com/ninja-build/ninja/issues/814 - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always") + ecm_add_cxx_compiler_flags_if_supported(FLAGS -fdiagnostics-color=always + SUPPORTED_IF ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR + (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)) + QUERY_IF APPLE) endif() include("${ECM_MODULE_DIR}/ECMEnableSanitizers.cmake") Index: kde-modules/KDEFrameworkCompilerSettings.cmake =================================================================== --- kde-modules/KDEFrameworkCompilerSettings.cmake +++ kde-modules/KDEFrameworkCompilerSettings.cmake @@ -61,18 +61,9 @@ add_definitions(-DQT_STRICT_ITERATORS) endif() -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic") -endif() - -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0.0") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wzero-as-null-pointer-constant" ) - endif() -endif() +ecm_add_cxx_compiler_flags_if_supported(FLAGS -pedantic + SUPPORTED_IF CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") -if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0.0") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wzero-as-null-pointer-constant" ) - endif() -endif() +ecm_add_cxx_compiler_flags_if_supported(FLAGS -Wzero-as-null-pointer-constant + SUPPORTED_IF CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0.0" + QUERY_IF CMAKE_CXX_COMPILER_ID MATCHES "Clang") Index: modules/ECMAddCompilerFlag.cmake =================================================================== --- /dev/null +++ modules/ECMAddCompilerFlag.cmake @@ -0,0 +1,150 @@ +#.rst: +# ECMAddCompilerFlag +# ------------------ +# +# Add compiler one or more flag conditionally +# +# :: +# +# ECM_ADD_CXX_COMPILER_FLAGS_IF_SUPPORTED(FLAGS +# [SUPPORTED_IF ] +# [QUERY_IF ]) +# +# C-language equivalent:: +# +# ECM_ADD_C_COMPILER_FLAGS_IF_SUPPORTED(FLAGS +# [SUPPORTED_IF ] +# [QUERY_IF ]) +# +# add ```` or ```` to CMAKE_CXX_FLAGS if the compiler supports them. +# Support is determined by the ``SUPPORTED_IF`` expression if provided or by +# querying the compiler directly if a ``QUERY_IF`` expression is true. The +# ``QUERY_IF`` expression takes precedence if it evaluates to true. +# The compiler is also queried if no conditions are given at all. +# The compiler is queried for each flag in turn and only the supported +# flag(s) are added. The ``SUPPORTED_IF`` condition applies to all flags. +# +# examples: +# +# add flags -a, -b and -c when using a GCC compiler or Clang: +# +# .. code-block:: cmake +# +# ecm_add_cxx_compiler_flags_if_supported(FLAGS -a -b -c SUPPORTED_IF CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") +# +# add flags -d, -e and/or -f if the compiler supports them: +# +# .. code-block:: cmake +# +# ecm_add_cxx_compiler_flags_if_supported(FLAGS -d -e -f) +# +# add flag -a when using a GCC > 5 compiler, or query the compiler when running on a Mac +# (a more specific test would be APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "Clang" but there is +# little chance another compiler will be used on that platform): +# +# .. code-block:: cmake +# +# ecm_add_c_compiler_flags_if_supported(FLAGS -g +# SUPPORTED_IF CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0.0" +# QUERY_IF APPLE) +# +# Since 5.xx + +#============================================================================= +# Copyright 2018,9 René J.V. Bertin +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include(CMakeParseArguments) +include(CheckCXXCompilerFlag) +include(CheckCCompilerFlag) + + +function(ECM_ADD_CXX_COMPILER_FLAGS_IF_SUPPORTED) + set(_OPTIONS_ARGS) + set(_ONE_VALUE_ARGS) + set(_MULTI_VALUE_ARGS FLAGS SUPPORTED_IF QUERY_IF) + + cmake_parse_arguments(EASCXXFLAGS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) + if(NOT EASCXXFLAGS_FLAGS) + message(FATAL_ERROR "ecm_add_cxx_compiler_flags_if_supported: 'FLAGS' is a required argument.") + endif() + # if the user provided conditions, evaluate them now to simplify things later + if(EASCXXFLAGS_IF_SUPPORTED AND (${EASCXXFLAGS_IF_SUPPORTED})) + set(EASCXXFLAGS_is_supported ON) + endif() + if((EASCXXFLAGS_QUERY_IF AND (${EASCXXFLAGS_QUERY_IF})) + OR (NOT EASCXXFLAGS_IF_SUPPORTED AND NOT EASCXXFLAGS_QUERY_IF)) + set(EASCXXFLAGS_needs_query ON) + endif() + if(EASCXXFLAGS_needs_query) + # without conditions, or when QUERY_IF is true we'll need to ask the compiler directly. + # one flag at a time: + foreach(flag IN ITEMS ${EASCXXFLAGS_FLAGS}) + # use a standardised and informative cached test variable + set(HASFLAG "${CMAKE_CXX_COMPILER_ID}++_ACCEPTS${flag}") + check_cxx_compiler_flag(${flag} ${HASFLAG}) + if({${HASFLAG}}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE) + endif() + endforeach() + elseif(EASCXXFLAGS_is_supported) + # all flags can be appended at once + string(REPLACE ";" " " FLAGS "${EASCXXFLAGS_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}" PARENT_SCOPE) + endif() +endfunction() + +function(ECM_ADD_C_COMPILER_FLAGS_IF_SUPPORTED) + set(_OPTIONS_ARGS) + set(_ONE_VALUE_ARGS) + set(_MULTI_VALUE_ARGS FLAGS SUPPORTED_IF QUERY_IF) + + cmake_parse_arguments(EASCFLAGS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) + if(NOT EASCFLAGS_FLAGS) + message(FATAL_ERROR "ecm_add_c_compiler_flags_if_supported: 'FLAGS' is a required argument.") + endif() + # if the user provided conditions, evaluate them now to simplify things later + if(EASCFLAGS_IF_SUPPORTED AND (${EASCFLAGS_IF_SUPPORTED})) + set(EASCFLAGS_is_supported ON) + endif() + if((EASCFLAGS_QUERY_IF AND (${EASCFLAGS_QUERY_IF})) + OR (NOT EASCFLAGS_IF_SUPPORTED AND NOT EASCFLAGS_QUERY_IF)) + set(EASCFLAGS_needs_query ON) + endif() + if(EASCFLAGS_needs_query) + # one flag at a time: + foreach(flag IN ITEMS ${EASCFLAGS_FLAGS}) + set(HASFLAG "${CMAKE_C_COMPILER_ID}_ACCEPTS${flag}") + check_c_compiler_flag(${flag} ${HASFLAG}) + if({${HASFLAG}}) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}" PARENT_SCOPE) + endif() + endforeach() + elseif(EASCFLAGS_is_supported) + string(REPLACE ";" " " FLAGS "${EASCFLAGS_FLAGS}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}" PARENT_SCOPE) + endif() +endfunction() +