From f98fd705290ac7bd9434552a07e38b775e6a6dbf Mon Sep 17 00:00:00 2001 From: Alexey Edelev Date: Thu, 1 Aug 2024 16:25:09 +0200 Subject: [PATCH] Add the 'exceptions' feature The feature allows enabling/disabling exceptions for the Qt builds. The feature is disabled by default. This commit reworks the way the exception flags are set for Qt targets. Instead of setting them per-target, flags now are set for the QtPlatformCommonInternal target, which transitively propagates the flag to other Qt targets. To disable/enable exception flags the newly introduced property _qt_internal_use_exceptions can be used. The flags enabling/disabling now can happen any time, but not only at target creation time. The property has 3 states: TRUE, FALSE, DEFAULT(or empty). If the property is not set or is set to DEFAULT, the exceptions feature value is used to set the required exceptions flags. Otherwise the flags are set according to the property value. The logic of EXCEPTION argument of the various qt_internal_add_ functions was also updated. If the argument is not provided, the _qt_internal_use_exceptions property value is set to DEFAULT, which gives the control on the exception flags to the feature. If the argument is provided, the exceptions are enabled by setting the _qt_internal_use_exceptions property to TRUE. Task-number: QTBUG-118901 Change-Id: I83e3bf52d48a3d16977cce849c9b0765c34f1f21 Reviewed-by: Alexandru Croitor --- cmake/Qt3rdPartyLibraryHelpers.cmake | 8 +-- cmake/QtExecutableHelpers.cmake | 6 +- cmake/QtFlagHandlingHelpers.cmake | 36 +++------- cmake/QtInternalTargets.cmake | 67 +++++++++++++++++++ cmake/QtModuleHelpers.cmake | 8 +-- cmake/QtPluginHelpers.cmake | 7 +- configure.cmake | 6 ++ .../text/qbytearray_large/CMakeLists.txt | 15 +++-- 8 files changed, 107 insertions(+), 46 deletions(-) diff --git a/cmake/Qt3rdPartyLibraryHelpers.cmake b/cmake/Qt3rdPartyLibraryHelpers.cmake index 7d40145efa1..980a4c99805 100644 --- a/cmake/Qt3rdPartyLibraryHelpers.cmake +++ b/cmake/Qt3rdPartyLibraryHelpers.cmake @@ -228,10 +228,10 @@ function(qt_internal_add_3rdparty_library target) qt_autogen_tools_initial_setup(${target}) endif() - if(NOT arg_EXCEPTIONS AND NOT arg_INTERFACE) - qt_internal_set_exceptions_flags("${target}" FALSE) - elseif(arg_EXCEPTIONS) - qt_internal_set_exceptions_flags("${target}" TRUE) + if(NOT DEFINED arg_EXCEPTIONS) + qt_internal_set_exceptions_flags("${target}" "DEFAULT") + else() + qt_internal_set_exceptions_flags("${target}" "${arg_EXCEPTIONS}") endif() qt_internal_extend_target("${target}" diff --git a/cmake/QtExecutableHelpers.cmake b/cmake/QtExecutableHelpers.cmake index 4c91df8425e..c63ffa221f3 100644 --- a/cmake/QtExecutableHelpers.cmake +++ b/cmake/QtExecutableHelpers.cmake @@ -149,7 +149,11 @@ function(qt_internal_add_executable name) MACOSX_BUNDLE "${arg_GUI}" ) - qt_internal_set_exceptions_flags("${name}" ${arg_EXCEPTIONS}) + if(NOT DEFINED arg_EXCEPTIONS) + qt_internal_set_exceptions_flags("${name}" "DEFAULT") + else() + qt_internal_set_exceptions_flags("${name}" "${arg_EXCEPTIONS}") + endif() # 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 3cfab2abf61..507004897bd 100644 --- a/cmake/QtFlagHandlingHelpers.cmake +++ b/cmake/QtFlagHandlingHelpers.cmake @@ -235,7 +235,6 @@ function(qt_internal_apply_gc_binaries target visibility) endif() endfunction() -# Only applied to Bootstrap and BundledPCRE2. function(qt_internal_apply_intel_cet target visibility) if(NOT QT_FEATURE_intelcet) return() @@ -285,34 +284,15 @@ function(qt_internal_skip_intel_cet_hardening target) set_target_properties("${target}" PROPERTIES _qt_no_intel_cet_harderning TRUE) endfunction() -# 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") - if((MSVC_VERSION GREATER_EQUAL 1929) AND NOT CLANG) - # Use the undocumented compiler flag to make our binary smaller on x64. - # https://devblogs.microsoft.com/cppblog/making-cpp-exception-handling-smaller-x64/ - # NOTE: It seems we'll use this new exception handling model unconditionally without - # this hack since some unknown MSVC version. - set(_flag ${_flag} "/d2FH4") - endif() - else() - set(_flag "-fexceptions") - endif() - else() - set(_defs "QT_NO_EXCEPTIONS") - if(MSVC) - set(_flag "/EHs-c-" "/wd4530" "/wd4577") - else() - set(_flag "-fno-exceptions") - endif() +# Sets the exceptions flags for the given target according to value. +# If the value is not defined, set it to the exceptions feature value. +function(qt_internal_set_exceptions_flags target value) + #INTERFACE libraries compile nothing + get_target_property(target_type ${target} TYPE) + if(target_type STREQUAL "INTERFACE_LIBRARY") + return() endif() - - target_compile_definitions("${target}" PRIVATE ${_defs}) - target_compile_options("${target}" PRIVATE ${_flag}) + set_target_properties(${target} PROPERTIES _qt_internal_use_exceptions ${value}) endfunction() function(qt_skip_warnings_are_errors target) diff --git a/cmake/QtInternalTargets.cmake b/cmake/QtInternalTargets.cmake index 60135355632..d1aaed19e89 100644 --- a/cmake/QtInternalTargets.cmake +++ b/cmake/QtInternalTargets.cmake @@ -375,6 +375,73 @@ if(DEFINED QT_EXTRA_FRAMEWORKPATHS AND APPLE) unset(__qt_fw_flags) endif() +function(qt_internal_add_exceptions_flags) + set(enable_defs "") + if(MSVC) + set(enable_flag "/EHsc") + if((MSVC_VERSION GREATER_EQUAL 1929) AND NOT CLANG) + # Use the undocumented compiler flag to make our binary smaller on x64. + # https://devblogs.microsoft.com/cppblog/making-cpp-exception-handling-smaller-x64/ + # NOTE: It seems we'll use this new exception handling model unconditionally without + # this hack since some unknown MSVC version. + set(enable_flag "${enable_flag}" "/d2FH4") + endif() + else() + set(enable_flag "-fexceptions") + endif() + + set(disable_defs "QT_NO_EXCEPTIONS") + if(MSVC) + set(disable_flag "/EHs-c-" "/wd4530" "/wd4577") + else() + set(disable_flag "-fno-exceptions") + endif() + + if(QT_FEATURE_exceptions) + set(default_flag "${enable_flag}") + set(default_defs "${enable_defs}") + else() + set(default_flag "${disable_flag}") + set(default_defs "${disable_defs}") + endif() + + string(JOIN "" check_default_genex + "$,DEFAULT>," + "$,>" + ">" + ) + + string(JOIN "" flag_genex + "$>," + "${enable_flag}," + "${disable_flag}" + ">" + ">" + ) + + string(JOIN "" defs_genex + "$>," + "${enable_defs}," + "${disable_defs}" + ">" + ">" + ) + + target_compile_definitions(PlatformCommonInternal INTERFACE ${defs_genex}) + target_compile_options(PlatformCommonInternal INTERFACE ${flag_genex}) +endfunction() + +qt_internal_add_exceptions_flags() + qt_internal_get_active_linker_flags(__qt_internal_active_linker_flags) if(__qt_internal_active_linker_flags) qt_internal_platform_link_options(PlatformCommonInternal INTERFACE diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake index d92e1524fee..08db3f3ba72 100644 --- a/cmake/QtModuleHelpers.cmake +++ b/cmake/QtModuleHelpers.cmake @@ -649,10 +649,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_exceptions_flags("${target}" FALSE) - elseif(arg_EXCEPTIONS) - qt_internal_set_exceptions_flags("${target}" TRUE) + if(NOT DEFINED arg_EXCEPTIONS) + qt_internal_set_exceptions_flags("${target}" "DEFAULT") + else() + qt_internal_set_exceptions_flags("${target}" "${arg_EXCEPTIONS}") endif() set(configureFile "${CMAKE_CURRENT_SOURCE_DIR}/configure.cmake") diff --git a/cmake/QtPluginHelpers.cmake b/cmake/QtPluginHelpers.cmake index e0a8d2a20b3..3110b002c90 100644 --- a/cmake/QtPluginHelpers.cmake +++ b/cmake/QtPluginHelpers.cmake @@ -319,8 +319,11 @@ function(qt_internal_add_plugin target) qt_internal_add_repo_local_defines("${target}") - qt_internal_set_exceptions_flags("${target}" ${arg_EXCEPTIONS}) - + if(NOT DEFINED arg_EXCEPTIONS) + qt_internal_set_exceptions_flags("${target}" "DEFAULT") + else() + qt_internal_set_exceptions_flags("${target}" "${arg_EXCEPTIONS}") + endif() set(qt_libs_private "") qt_internal_get_qt_all_known_modules(known_modules) diff --git a/configure.cmake b/configure.cmake index e61a49ac82d..f42d921d7ba 100644 --- a/configure.cmake +++ b/configure.cmake @@ -673,6 +673,12 @@ qt_feature("force_asserts" PUBLIC LABEL "Force assertions" AUTODETECT OFF ) + +qt_feature("exceptions" + LABEL "Enable exceptions" + AUTODETECT OFF +) + qt_feature("framework" PUBLIC LABEL "Build Apple Frameworks" AUTODETECT ON diff --git a/tests/auto/corelib/text/qbytearray_large/CMakeLists.txt b/tests/auto/corelib/text/qbytearray_large/CMakeLists.txt index 3a2c6b7216d..8737599518b 100644 --- a/tests/auto/corelib/text/qbytearray_large/CMakeLists.txt +++ b/tests/auto/corelib/text/qbytearray_large/CMakeLists.txt @@ -7,18 +7,19 @@ if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() -set(compile_and_link_options "") -if(WASM) - list(APPEND compile_and_link_options "-fexceptions") -endif() - qt_internal_add_test(tst_qbytearray_large SOURCES tst_qbytearray_large.cpp LIBRARIES Qt::Core TESTDATA "rfc3252.txt" - COMPILE_OPTIONS ${compile_and_link_options} - LINK_OPTIONS ${compile_and_link_options} ) +qt_internal_is_in_test_batch(in_batch tst_qbytearray_large) +if(in_batch) + _qt_internal_test_batch_target_name(test_target) +else() + set(test_target tst_qbytearray_large) +endif() + +qt_internal_set_exceptions_flags(${test_target} TRUE)