Skip to content

Commit

Permalink
Add the 'exceptions' feature
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
semlanik committed Aug 12, 2024
1 parent 442cac6 commit f98fd70
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 46 deletions.
8 changes: 4 additions & 4 deletions cmake/Qt3rdPartyLibraryHelpers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand Down
6 changes: 5 additions & 1 deletion cmake/QtExecutableHelpers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
36 changes: 8 additions & 28 deletions cmake/QtFlagHandlingHelpers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand Down
67 changes: 67 additions & 0 deletions cmake/QtInternalTargets.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
"$<OR:"
"$<STREQUAL:$<TARGET_PROPERTY:_qt_internal_use_exceptions>,DEFAULT>,"
"$<STREQUAL:$<TARGET_PROPERTY:_qt_internal_use_exceptions>,>"
">"
)

string(JOIN "" flag_genex
"$<IF:"
"${check_default_genex},"
"${default_flag},"
"$<IF:"
"$<BOOL:$<TARGET_PROPERTY:_qt_internal_use_exceptions>>,"
"${enable_flag},"
"${disable_flag}"
">"
">"
)

string(JOIN "" defs_genex
"$<IF:"
"${check_default_genex},"
"${default_defs},"
"$<IF:"
"$<BOOL:$<TARGET_PROPERTY:_qt_internal_use_exceptions>>,"
"${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
Expand Down
8 changes: 4 additions & 4 deletions cmake/QtModuleHelpers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
7 changes: 5 additions & 2 deletions cmake/QtPluginHelpers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions configure.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 8 additions & 7 deletions tests/auto/corelib/text/qbytearray_large/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)

0 comments on commit f98fd70

Please sign in to comment.