From 606924132ff1f11b9d7b4357251f07ccabb8bdb6 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 18 Aug 2016 22:24:26 +0200 Subject: Add support for safe feature checking at compile time Added a qtConfig(feature) function to qmake, and a QT_CONFIG(feature) macro. These can safely check whether a certain compile time feature of Qt is enabled or not. For this to work the feature has to have a publicFeature or privateFeature output in the configure.json file. In pro files, please use the qtConfig(feature) test function instead of checking contains(QT_CONFIG, feature), as the latter will be unreliable with the upcoming modularization (it requires a load(qt_module_config) before doing any such checks). Note that feature names are now lowercase, and identical (except for hyphens versus underscores currently) in the pro and c++ files. This makes the logic easier to follow, as we avoid all double negations, and most importantly, QT_CONFIG and qtConfig are implemented in a way that you'll get a build error for a mistyped or non-existent feature. This will also prevent accidental use of a widget feature in gui in the future. This gives us complete symmetry between the handling in pro and c++ files. Change-Id: I60404f97953724e639ffb6386cce2e8b1e4b735a Reviewed-by: Lars Knoll Reviewed-by: Oswald Buddenhagen --- mkspecs/features/qt_configure.prf | 15 +++++++++++++++ mkspecs/features/qt_functions.prf | 9 +++++++++ src/corelib/global/qglobal.h | 12 +++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index 7d5814e4b1..72dd1c4c8d 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -1397,6 +1397,21 @@ defineTest(qtConfOutput_feature) { } } +defineTest(qtConfOutput_publicFeature) { + name = "$$eval($${1}.name)" + isEmpty(name): \ + name = $$eval($${1}.feature) + feature = $$replace(name, [-+.], _) + + $${2} { + qtConfOutputVar(append, "publicPro", "QT.global.enabled_features", $$name) + qtConfOutputSetDefine("publicHeader", "QT_FEATURE_$$feature", 1) + } else { + qtConfOutputVar(append, "publicPro", "QT.global.disabled_features", $$name) + qtConfOutputSetDefine("publicHeader", "QT_FEATURE_$$feature", -1) + } +} + # currently this is somewhat inconsistent, as the feature is output to the public pro file, # whereas the define is being added to the private pro file. # This should get cleaned up to add to the private pro and header instead. diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index f03472d940..7e6433814b 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -302,3 +302,12 @@ defineTest(prepareRecursiveTarget) { export($${target}.CONFIG) export($${target}.recurse_target) } + +defineTest(qtConfig) { + contains(QT.global.enabled_features, $$1): \ + return(true) + contains(QT.global.disabled_features, $$1): \ + return(false) + + error("Could not find feature $${1}.") +} diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index d9ffca3810..e6d65b0f99 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -62,13 +62,23 @@ #endif // The QT_SUPPORTS macro is deprecated. Don't use it in new code. -// Instead, use #ifdef/ndef QT_NO_feature. +// Instead, use QT_CONFIG(feature) // ### Qt6: remove macro #ifdef _MSC_VER # define QT_SUPPORTS(FEATURE) (!defined QT_NO_##FEATURE) #else # define QT_SUPPORTS(FEATURE) (!defined(QT_NO_##FEATURE)) #endif + +/* + The QT_CONFIG macro implements a safe compile time check for features of Qt. + Features can be in three states: + 0 or undefined: This will lead to a compile error when testing for it + -1: The feature is not available + 1: The feature is available +*/ +#define QT_CONFIG(feature) (1/QT_FEATURE_##feature == 1) + #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) # define QT_NO_UNSHARABLE_CONTAINERS #endif -- cgit v1.2.3