From dac4d5a4927316303c2a70039728d57f4309de90 Mon Sep 17 00:00:00 2001 From: Alexey Edelev Date: Thu, 21 Jan 2021 11:17:58 +0100 Subject: [PATCH] Clear non-relevant CMake compiler flags Add internal function to cleanup compiler flags out of the CMAKE_xxx_FLAGS_xxx variables. Use introduced interface to clear the '/EHsc' flag for the MSVC compiler family. This adjusts the CMake behavior to the qmake one. Change the 'EXCEPTIONS' option handling in helper functions. Add ability to add enabling and disabling exception flags. Previously it was only possible to add disabling exception flags. Fixes: QTBUG-89952 Change-Id: I60d47660a97ae9b5a1d1f4107d352c9e97890144 Reviewed-by: Craig Scott Reviewed-by: Joerg Bornemann --- cmake/Qt3rdPartyLibraryHelpers.cmake | 4 +- cmake/QtExecutableHelpers.cmake | 5 +- cmake/QtFlagHandlingHelpers.cmake | 112 ++++++++++++++++++++++----- cmake/QtModuleHelpers.cmake | 6 +- cmake/QtPluginHelpers.cmake | 5 +- 5 files changed, 104 insertions(+), 28 deletions(-) diff --git a/cmake/Qt3rdPartyLibraryHelpers.cmake b/cmake/Qt3rdPartyLibraryHelpers.cmake index c784039556a..d144977c7fd 100644 --- a/cmake/Qt3rdPartyLibraryHelpers.cmake +++ b/cmake/Qt3rdPartyLibraryHelpers.cmake @@ -187,7 +187,9 @@ function(qt_internal_add_3rdparty_library target) endif() if(NOT arg_EXCEPTIONS AND NOT arg_INTERFACE) - qt_internal_set_no_exceptions_flags("${target}") + qt_internal_set_exceptions_flags("${target}" FALSE) + elseif(arg_EXCEPTIONS) + qt_internal_set_exceptions_flags("${target}" TRUE) endif() qt_internal_extend_target("${target}" diff --git a/cmake/QtExecutableHelpers.cmake b/cmake/QtExecutableHelpers.cmake index db4cc06be27..5ab7848aaed 100644 --- a/cmake/QtExecutableHelpers.cmake +++ b/cmake/QtExecutableHelpers.cmake @@ -115,9 +115,8 @@ function(qt_internal_add_executable name) WIN32_EXECUTABLE "${arg_GUI}" MACOSX_BUNDLE "${arg_GUI}" ) - if(NOT ${arg_EXCEPTIONS}) - qt_internal_set_no_exceptions_flags("${name}") - endif() + + qt_internal_set_exceptions_flags("${name}" ${arg_EXCEPTIONS}) # Check if target needs to be excluded from all target. Also affects qt_install. # Set by qt_exclude_tool_directories_from_default_target. diff --git a/cmake/QtFlagHandlingHelpers.cmake b/cmake/QtFlagHandlingHelpers.cmake index e4e58b8a1ee..69558c32db6 100644 --- a/cmake/QtFlagHandlingHelpers.cmake +++ b/cmake/QtFlagHandlingHelpers.cmake @@ -145,27 +145,35 @@ function(qt_internal_library_deprecation_level result) set("${result}" "${deprecations}" PARENT_SCOPE) endfunction() -# Sets the exceptions flags for the given target -function(qt_internal_set_no_exceptions_flags target) - target_compile_definitions("${target}" PRIVATE "QT_NO_EXCEPTIONS") - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(_flag "/wd4530" "/wd4577") - elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - set(_flag "-fno-exceptions") - elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") - set(_flag "-fno-exceptions") - elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - if (MSVC) +# Sets the exceptions flags for the given target according to exceptions_on +function(qt_internal_set_exceptions_flags target exceptions_on) + set(_defs "") + set(_flag "") + if(exceptions_on) + if(MSVC) + set(_flag "/EHsc") + endif() + else() + set(_defs "QT_NO_EXCEPTIONS") + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") set(_flag "/wd4530" "/wd4577") - else() + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + set(_flag "-fno-exceptions") + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") + set(_flag "-fno-exceptions") + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + if (MSVC) + set(_flag "/wd4530" "/wd4577") + else() + set(_flag "-fno-exceptions") + endif() + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") set(_flag "-fno-exceptions") endif() - elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") - set(_flag "-fno-exceptions") - endif() - if (_flag) - target_compile_options("${target}" PRIVATE ${_flag}) endif() + + target_compile_definitions("${target}" PRIVATE ${_defs}) + target_compile_options("${target}" PRIVATE ${_flag}) endfunction() function(qt_skip_warnings_are_errors target) @@ -398,11 +406,17 @@ endfunction() # Helper function used to update compiler and linker flags further below function(qt_internal_remove_flags_impl flag_var_name flag_values IN_CACHE) + cmake_parse_arguments(arg "REGEX" "" "" ${ARGN}) + set(replace_type REPLACE) + if(arg_REGEX) + list(PREPEND replace_type REGEX) + endif() + # This must come before cache variable modification because setting the # cache variable with FORCE will overwrite the non-cache variable in this # function scope, but we need to use the original value before that change. foreach(flag_value IN LISTS flag_values) - string(REPLACE "${flag_value}" "" ${flag_var_name} "${${flag_var_name}}") + string(${replace_type} "${flag_value}" "" ${flag_var_name} "${${flag_var_name}}") endforeach() string(STRIP "${${flag_var_name}}" ${flag_var_name}) set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE) @@ -414,7 +428,7 @@ function(qt_internal_remove_flags_impl flag_var_name flag_values IN_CACHE) # Work exclusively on cache variable value only. set(mod_flags $CACHE{${flag_var_name}}) foreach(flag_value IN LISTS flag_values) - string(REPLACE "${flag_value}" "" mod_flags "${mod_flags}") + string(${replace_type} "${flag_value}" "" mod_flags "${mod_flags}") endforeach() string(STRIP "${mod_flags}" mod_flags) get_property(help_text CACHE ${flag_var_name} PROPERTY HELPSTRING) @@ -485,6 +499,65 @@ function(qt_internal_remove_known_optimization_flags) endforeach() endfunction() +# Removes specified flags from CMAKE__FLAGS[_CONFIGS] variables +# +# IN_CACHE enables flags removal from CACHE +# CONFIGS list of configurations that need to clear flags. Clears all configs by default if not +# specified. +# LANGUAGES list of LANGUAGES that need clear flags. Clears all languages by default if not +# specified. +# REGEX enables the flag processing as a regular expression. +function(qt_internal_remove_compiler_flags flags) + qt_parse_all_arguments(arg + "qt_internal_remove_compiler_flags" + "IN_CACHE;REGEX" + "" + "CONFIGS;LANGUAGES" + ${ARGN} + ) + + if("${flags}" STREQUAL "") + message(WARNING "qt_internal_remove_compiler_flags was called without any flags specified.") + return() + endif() + + if(arg_LANGUAGES) + set(languages "${arg_LANGUAGES}") + else() + qt_internal_get_enabled_languages_for_flag_manipulation(languages) + endif() + + if(arg_CONFIGS) + set(configs "${arg_CONFIGS}") + else() + message(FATAL_ERROR + "You must specify at least one configuration for which to remove the flags.") + endif() + + if(arg_REGEX) + list(APPEND extra_options "REGEX") + endif() + + foreach(lang ${languages}) + set(flag_var_name "CMAKE_${lang}_FLAGS") + qt_internal_remove_flags_impl(${flag_var_name} + "${flags}" + "${arg_IN_CACHE}" + ${extra_options} + ) + set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE) + foreach(config ${configs}) + set(flag_var_name "CMAKE_${lang}_FLAGS_${config}") + qt_internal_remove_flags_impl(${flag_var_name} + "${flags}" + "${arg_IN_CACHE}" + ${extra_options} + ) + set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE) + endforeach() + endforeach() +endfunction() + # Adds compiler flags for the given CONFIGS in the calling scope. Can also update the cache # if asked to do so. The flag variables are always updated in the calling scope, even if they # did not exist beforehand. @@ -857,6 +930,7 @@ function(qt_internal_set_up_config_optimizations_like_in_qmake) CONFIGS RELEASE RELWITHDEBINFO MINSIZEREL TYPES EXE SHARED MODULE # when linking static libraries, link.exe can't recognize this parameter, clang-cl will error out. IN_CACHE) + qt_internal_remove_compiler_flags("(^| )/EH[scra-]*( |$)" LANGUAGES CXX CONFIGS ${configs} IN_CACHE REGEX) endif() # Allow opting into generating debug info in object files with a fake feature. diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake index 834c2ec73ec..597895b7b6a 100644 --- a/cmake/QtModuleHelpers.cmake +++ b/cmake/QtModuleHelpers.cmake @@ -406,8 +406,10 @@ function(qt_internal_add_module target) # thus we can't use qt_internal_extend_target()'s PUBLIC_DEFINES option. target_compile_definitions(${target} INTERFACE QT_${module_define_infix}_LIB) - if(NOT ${arg_EXCEPTIONS} AND NOT ${arg_HEADER_MODULE}) - qt_internal_set_no_exceptions_flags("${target}") + if(NOT arg_EXCEPTIONS AND NOT ${arg_HEADER_MODULE}) + qt_internal_set_exceptions_flags("${target}" FALSE) + elseif(arg_EXCEPTIONS) + qt_internal_set_exceptions_flags("${target}" TRUE) endif() set(configureFile "${CMAKE_CURRENT_SOURCE_DIR}/configure.cmake") diff --git a/cmake/QtPluginHelpers.cmake b/cmake/QtPluginHelpers.cmake index 497ccc0e89e..2c26e5bceea 100644 --- a/cmake/QtPluginHelpers.cmake +++ b/cmake/QtPluginHelpers.cmake @@ -203,9 +203,8 @@ function(qt_internal_add_plugin target) ENABLE_AUTOGEN_TOOLS ${arg_ENABLE_AUTOGEN_TOOLS} DISABLE_AUTOGEN_TOOLS ${arg_DISABLE_AUTOGEN_TOOLS} ) - if(NOT ${arg_EXCEPTIONS}) - qt_internal_set_no_exceptions_flags("${target}") - endif() + + qt_internal_set_exceptions_flags("${target}" ${arg_EXCEPTIONS}) set(qt_libs_private "")