From 7e03bc39b8bcdaa4e83e72ac99e117561c124951 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Mon, 15 Jun 2020 09:50:42 +0200 Subject: [PATCH] CMake: Improve sanitizer detection The change fixes the labels to show up correctly in the configure summary. It also allows enabling the sanitizer via the feature flags, e.g. -DFEATURE_sanitize_address=ON. Finally the qtbase sanitizer option is saved in QtBuildInternalsExtra so that repos built after qtbase have the same sanitizer options enabled. Change-Id: Ic9d9e3ce3c7ebbc244ced2e6d163d1ac8ee06b12 Fixes: QTBUG-84721 Reviewed-by: Fabian Kosmale Reviewed-by: Joerg Bornemann --- cmake/QtBuild.cmake | 32 +++++++++++++++++++++++++++++++ cmake/QtPostProcess.cmake | 5 +++++ cmake/QtSetup.cmake | 1 + configure.cmake | 25 ++++++++++++++++++++++++ util/cmake/configurejson2cmake.py | 6 +----- 5 files changed, 64 insertions(+), 5 deletions(-) diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake index a0fefc71d1..e4d501f1f6 100644 --- a/cmake/QtBuild.cmake +++ b/cmake/QtBuild.cmake @@ -5406,6 +5406,38 @@ function(qt_apply_rpaths) endif() endfunction() +function(qt_internal_set_up_sanitizer_features) + set(ECM_ENABLE_SANITIZERS "" CACHE STRING "Enable sanitizers") + set_property(CACHE ECM_ENABLE_SANITIZERS PROPERTY STRINGS "address;memory;thread;undefined") + + # If FEATURE_sanitize_foo is set on the command line, make sure to set the appropriate + # ECM_ENABLE_SANITIZERS value. Also the other way around. This basically allows setting either + # the feature or ECM_ENABLE_SANITIZERS directly. + # + # TODO: Decide which one of these should be the source of truth, because reconfiguration with + # different options might not work as expected when ECM_ENABLE_SANITIZERS is provided instead of + # the features. + set(enabled_sanitizer_features "") + foreach(sanitizer_type address memory thread undefined) + if(FEATURE_sanitize_${sanitizer_type}) + list(APPEND enabled_sanitizer_features "${sanitizer_type}") + endif() + endforeach() + if(enabled_sanitizer_features) + set(ECM_ENABLE_SANITIZERS + "${enabled_sanitizer_features}" CACHE STRING "Enable sanitizers" FORCE) + endif() + + if(ECM_ENABLE_SANITIZERS) + foreach(sanitizer_type ${ECM_ENABLE_SANITIZERS}) + message(STATUS "Enabling sanitizer: ${sanitizer_type}") + set(feature_name "FEATURE_sanitize_${sanitizer_type}") + set(${feature_name} "ON" CACHE BOOL "Enable ${sanitizer_type} sanitizer" FORCE) + set(QT_${feature_name} "ON" CACHE BOOL "Enable ${sanitizer_type} sanitizer" FORCE) + endforeach() + endif() +endfunction() + # Compatibility macros that should be removed once all their usages are removed. function(extend_target) qt_extend_target(${ARGV}) diff --git a/cmake/QtPostProcess.cmake b/cmake/QtPostProcess.cmake index 06afd4583c..bb601e3432 100644 --- a/cmake/QtPostProcess.cmake +++ b/cmake/QtPostProcess.cmake @@ -411,6 +411,11 @@ endif()\n") "set(QT_BUILD_TOOLS_WHEN_CROSSCOMPILING \"TRUE\" CACHE BOOL \"\" FORCE)\n") endif() + if(ECM_ENABLE_SANITIZERS) + string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS + "set(ECM_ENABLE_SANITIZERS \"${ECM_ENABLE_SANITIZERS}\" CACHE BOOL \"\" FORCE)\n") + endif() + # Rpath related things that need to be re-used when building other repos. string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS "set(CMAKE_INSTALL_RPATH \"${CMAKE_INSTALL_RPATH}\" CACHE STRING \"\")\n") diff --git a/cmake/QtSetup.cmake b/cmake/QtSetup.cmake index df13af93f7..607b3afebd 100644 --- a/cmake/QtSetup.cmake +++ b/cmake/QtSetup.cmake @@ -181,6 +181,7 @@ if (CMAKE_CROSSCOMPILING AND NOT IS_DIRECTORY ${QT_HOST_PATH}) endif() ## Enable support for sanitizers: +qt_internal_set_up_sanitizer_features() include(${CMAKE_CURRENT_LIST_DIR}/3rdparty/extra-cmake-modules/modules/ECMEnableSanitizers.cmake) option(QT_USE_CCACHE "Enable the use of ccache") diff --git a/configure.cmake b/configure.cmake index 3863f34285..b229e4df2c 100644 --- a/configure.cmake +++ b/configure.cmake @@ -467,12 +467,37 @@ qt_feature("testcocoon" AUTODETECT OFF ) qt_feature_config("testcocoon" QMAKE_PUBLIC_CONFIG) +qt_feature("sanitize_address" + LABEL "Addresses" + AUTODETECT OFF +) +qt_feature_config("sanitize_address" QMAKE_PUBLIC_CONFIG) +qt_feature("sanitize_thread" + LABEL "Threads" + AUTODETECT OFF +) +qt_feature_config("sanitize_thread" QMAKE_PUBLIC_CONFIG) +qt_feature("sanitize_memory" + LABEL "Memory" + AUTODETECT OFF +) +qt_feature_config("sanitize_memory" QMAKE_PUBLIC_CONFIG) qt_feature("sanitize_fuzzer_no_link" LABEL "Fuzzer (instrumentation only)" PURPOSE "Adds instrumentation for fuzzing to the binaries but links to the usual main function instead of a fuzzer's." AUTODETECT OFF ) qt_feature_config("sanitize_fuzzer_no_link" QMAKE_PUBLIC_CONFIG) +qt_feature("sanitize_undefined" + LABEL "Undefined" + AUTODETECT OFF +) +qt_feature_config("sanitize_undefined" QMAKE_PUBLIC_CONFIG) +qt_feature("sanitizer" + LABEL "Sanitizers" + CONDITION QT_FEATURE_sanitize_address OR QT_FEATURE_sanitize_thread OR QT_FEATURE_sanitize_memory OR QT_FEATURE_sanitize_fuzzer_no_link OR QT_FEATURE_sanitize_undefined +) +qt_feature_config("sanitizer" QMAKE_PUBLIC_CONFIG) qt_feature("coverage_trace_pc_guard" LABEL "trace-pc-guard" AUTODETECT OFF diff --git a/util/cmake/configurejson2cmake.py b/util/cmake/configurejson2cmake.py index ce032fafaf..8b2c51cfe9 100755 --- a/util/cmake/configurejson2cmake.py +++ b/util/cmake/configurejson2cmake.py @@ -903,11 +903,7 @@ def get_feature_mapping(): "autoDetect": "1", "condition": "BUILD_SHARED_LIBS AND UNIX AND NOT WIN32 AND NOT ANDROID", }, - "sanitize_address": None, # sanitizer - "sanitize_memory": None, - "sanitizer": None, - "sanitize_thread": None, - "sanitize_undefined": None, + "shared": { "condition": "BUILD_SHARED_LIBS", "output": [