From 2ce8eeeed3f23ededb3b14ff658fedf0b4fd1e3c Mon Sep 17 00:00:00 2001 From: kleuter Date: Wed, 18 Nov 2020 11:33:42 +0100 Subject: [PATCH] 5.13.2: back port big sur detection --- .../global/qoperatingsystemversion.cpp | 25 ++++ .../corelib/global/qoperatingsystemversion.h | 1 + .../src/corelib/global/qsystemdetection.h | 6 + .../qtbase/src/corelib/kernel/qcore_mac.cpp | 127 ++++++++++++++++++ .../qtbase/src/corelib/kernel/qcore_mac_p.h | 26 ++++ .../plugins/platforms/cocoa/qcocoahelpers.h | 20 --- .../plugins/platforms/cocoa/qcocoahelpers.mm | 83 ------------ 7 files changed, 185 insertions(+), 103 deletions(-) diff --git a/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.cpp b/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.cpp index bc6adb5..a0ea801 100644 --- a/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.cpp +++ b/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.cpp @@ -42,6 +42,10 @@ #include "qoperatingsystemversion_p.h" #endif +#if defined(Q_OS_DARWIN) +#include +#endif + #include #include @@ -445,6 +449,27 @@ const QOperatingSystemVersion QOperatingSystemVersion::MacOSMojave = const QOperatingSystemVersion QOperatingSystemVersion::MacOSCatalina = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 15); +/*! + \variable QOperatingSystemVersion::MacOSBigSur + \brief a version corresponding to macOS Big Sur + + The actual version number depends on whether the application was built + using the Xcode 12 SDK. If it was, the version number corresponds + to macOS 11.0. If not it will correspond to macOS 10.16. + + By comparing QOperatingSystemVersion::current() to this constant + you will always end up comparing to the right version number. + \since 6.0 + */ +const QOperatingSystemVersion QOperatingSystemVersion::MacOSBigSur = [] { +#if defined(Q_OS_DARWIN) + if (QMacVersion::buildSDK(QMacVersion::ApplicationBinary) >= QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 16)) + return QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 11, 0); + else +#endif + return QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 16); +}(); + /*! \variable QOperatingSystemVersion::AndroidJellyBean \brief a version corresponding to Android Jelly Bean (version 4.1, API level 16). diff --git a/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.h b/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.h index 89c60c4..db4da1a 100644 --- a/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.h +++ b/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.h @@ -72,6 +72,7 @@ public: static const QOperatingSystemVersion MacOSHighSierra; static const QOperatingSystemVersion MacOSMojave; static const QOperatingSystemVersion MacOSCatalina; + static const QOperatingSystemVersion MacOSBigSur; static const QOperatingSystemVersion AndroidJellyBean; static const QOperatingSystemVersion AndroidJellyBean_MR1; diff --git a/5.13.2/qtbase/src/corelib/global/qsystemdetection.h b/5.13.2/qtbase/src/corelib/global/qsystemdetection.h index 3e38e67..d87e181 100644 --- a/5.13.2/qtbase/src/corelib/global/qsystemdetection.h +++ b/5.13.2/qtbase/src/corelib/global/qsystemdetection.h @@ -234,6 +234,9 @@ # if !defined(__MAC_10_15) # define __MAC_10_15 101500 # endif +# if !defined(__MAC_10_16) +# define __MAC_10_16 101600 +# endif # if !defined(MAC_OS_X_VERSION_10_11) # define MAC_OS_X_VERSION_10_11 __MAC_10_11 # endif @@ -249,6 +252,9 @@ # if !defined(MAC_OS_X_VERSION_10_15) # define MAC_OS_X_VERSION_10_15 __MAC_10_15 # endif +# if !defined(MAC_OS_X_VERSION_10_16) +# define MAC_OS_X_VERSION_10_16 __MAC_10_16 +# endif # # if !defined(__IPHONE_10_0) # define __IPHONE_10_0 100000 diff --git a/5.13.2/qtbase/src/corelib/kernel/qcore_mac.cpp b/5.13.2/qtbase/src/corelib/kernel/qcore_mac.cpp index b048576..22b5b54 100644 --- a/5.13.2/qtbase/src/corelib/kernel/qcore_mac.cpp +++ b/5.13.2/qtbase/src/corelib/kernel/qcore_mac.cpp @@ -45,6 +45,9 @@ #include "qmutex.h" #include "qvarlengtharray.h" +#include +#include + QT_BEGIN_NAMESPACE QCFString::operator QString() const @@ -159,4 +162,128 @@ os_log_t AppleUnifiedLogger::cachedLog(const QString &subsystem, const QString & // -------------------------------------------------------------------------- +QOperatingSystemVersion QMacVersion::buildSDK(VersionTarget target) +{ + switch (target) { + case ApplicationBinary: return applicationVersion().second; + case QtLibraries: return libraryVersion().second; + } + Q_UNREACHABLE(); +} + +QOperatingSystemVersion QMacVersion::deploymentTarget(VersionTarget target) +{ + switch (target) { + case ApplicationBinary: return applicationVersion().first; + case QtLibraries: return libraryVersion().first; + } + Q_UNREACHABLE(); +} + +QOperatingSystemVersion QMacVersion::currentRuntime() +{ + return QOperatingSystemVersion::current(); +} + +// Mach-O platforms +enum Platform { + macOS = 1, + iOS = 2, + tvOS = 3, + watchOS = 4, + bridgeOS = 5, + macCatalyst = 6, + iOSSimulator = 7, + tvOSSimulator = 8, + watchOSSimulator = 9 +}; + +QMacVersion::VersionTuple QMacVersion::versionsForImage(const mach_header *machHeader) +{ + static auto osForLoadCommand = [](uint32_t cmd) { + switch (cmd) { + case LC_VERSION_MIN_MACOSX: return QOperatingSystemVersion::MacOS; + case LC_VERSION_MIN_IPHONEOS: return QOperatingSystemVersion::IOS; + case LC_VERSION_MIN_TVOS: return QOperatingSystemVersion::TvOS; + case LC_VERSION_MIN_WATCHOS: return QOperatingSystemVersion::WatchOS; + default: return QOperatingSystemVersion::Unknown; + } + }; + + static auto osForPlatform = [](uint32_t platform) { + switch (platform) { + case Platform::macOS: + return QOperatingSystemVersion::MacOS; + case Platform::iOS: + case Platform::iOSSimulator: + return QOperatingSystemVersion::IOS; + case Platform::tvOS: + case Platform::tvOSSimulator: + return QOperatingSystemVersion::TvOS; + case Platform::watchOS: + case Platform::watchOSSimulator: + return QOperatingSystemVersion::WatchOS; + default: + return QOperatingSystemVersion::Unknown; + } + }; + + static auto makeVersionTuple = [](uint32_t dt, uint32_t sdk, QOperatingSystemVersion::OSType osType) { + return qMakePair( + QOperatingSystemVersion(osType, dt >> 16 & 0xffff, dt >> 8 & 0xff, dt & 0xff), + QOperatingSystemVersion(osType, sdk >> 16 & 0xffff, sdk >> 8 & 0xff, sdk & 0xff) + ); + }; + + const bool is64Bit = machHeader->magic == MH_MAGIC_64 || machHeader->magic == MH_CIGAM_64; + auto commandCursor = uintptr_t(machHeader) + (is64Bit ? sizeof(mach_header_64) : sizeof(mach_header)); + + for (uint32_t i = 0; i < machHeader->ncmds; ++i) { + load_command *loadCommand = reinterpret_cast(commandCursor); + if (loadCommand->cmd == LC_VERSION_MIN_MACOSX || loadCommand->cmd == LC_VERSION_MIN_IPHONEOS + || loadCommand->cmd == LC_VERSION_MIN_TVOS || loadCommand->cmd == LC_VERSION_MIN_WATCHOS) { + auto versionCommand = reinterpret_cast(loadCommand); + return makeVersionTuple(versionCommand->version, versionCommand->sdk, osForLoadCommand(loadCommand->cmd)); +#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13, __IPHONE_11_0, __TVOS_11_0, __WATCHOS_4_0) + } else if (loadCommand->cmd == LC_BUILD_VERSION) { + auto versionCommand = reinterpret_cast(loadCommand); + return makeVersionTuple(versionCommand->minos, versionCommand->sdk, osForPlatform(versionCommand->platform)); +#endif + } + commandCursor += loadCommand->cmdsize; + } + Q_ASSERT_X(false, "QMacVersion", "Could not find any version load command"); + Q_UNREACHABLE(); +} + +QMacVersion::VersionTuple QMacVersion::applicationVersion() +{ + static VersionTuple version = []() { + const mach_header *executableHeader = nullptr; + for (uint32_t i = 0; i < _dyld_image_count(); ++i) { + auto header = _dyld_get_image_header(i); + if (header->filetype == MH_EXECUTE) { + executableHeader = header; + break; + } + } + Q_ASSERT_X(executableHeader, "QMacVersion", "Failed to resolve Mach-O header of executable"); + return versionsForImage(executableHeader); + }(); + return version; +} + +QMacVersion::VersionTuple QMacVersion::libraryVersion() +{ + static VersionTuple version = []() { + Dl_info qtCoreImage; + dladdr((const void *)&QMacVersion::libraryVersion, &qtCoreImage); + Q_ASSERT_X(qtCoreImage.dli_fbase, "QMacVersion", "Failed to resolve Mach-O header of QtCore"); + return versionsForImage(static_cast(qtCoreImage.dli_fbase)); + }(); + return version; +} + +// ------------------------------------------------------------------------- + QT_END_NAMESPACE diff --git a/5.13.2/qtbase/src/corelib/kernel/qcore_mac_p.h b/5.13.2/qtbase/src/corelib/kernel/qcore_mac_p.h index 168e041..b78bc32 100644 --- a/5.13.2/qtbase/src/corelib/kernel/qcore_mac_p.h +++ b/5.13.2/qtbase/src/corelib/kernel/qcore_mac_p.h @@ -53,6 +53,9 @@ #include "private/qglobal_p.h" +#include +struct mach_header; + #ifndef __IMAGECAPTURE__ # define __IMAGECAPTURE__ #endif @@ -72,6 +75,7 @@ #include "qstring.h" #include "qscopedpointer.h" +#include "qpair.h" #if defined( __OBJC__) && defined(QT_NAMESPACE) #define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__) @compatibility_alias __KLASS__ QT_MANGLE_NAMESPACE(__KLASS__) @@ -397,6 +401,28 @@ private: // ------------------------------------------------------------------------- +class Q_CORE_EXPORT QMacVersion +{ +public: + enum VersionTarget { + ApplicationBinary, + QtLibraries + }; + + static QOperatingSystemVersion buildSDK(VersionTarget target = ApplicationBinary); + static QOperatingSystemVersion deploymentTarget(VersionTarget target = ApplicationBinary); + static QOperatingSystemVersion currentRuntime(); + +private: + QMacVersion() = default; + using VersionTuple = QPair; + static VersionTuple versionsForImage(const mach_header *machHeader); + static VersionTuple applicationVersion(); + static VersionTuple libraryVersion(); +}; + +// ------------------------------------------------------------------------- + QT_END_NAMESPACE #endif // QCORE_MAC_P_H diff --git a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h b/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h index 69a1854..8dc642b 100644 --- a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -194,26 +194,6 @@ constexpr backwards_t backwards(R&& r) { return {std::forward(r)}; } #error "32-bit builds are not supported" #endif -class QMacVersion -{ -public: - enum VersionTarget { - ApplicationBinary, - QtLibraries - }; - - static QOperatingSystemVersion buildSDK(VersionTarget target = ApplicationBinary); - static QOperatingSystemVersion deploymentTarget(VersionTarget target = ApplicationBinary); - static QOperatingSystemVersion currentRuntime(); - -private: - QMacVersion() = default; - using VersionTuple = QPair; - static VersionTuple versionsForImage(const mach_header *machHeader); - static VersionTuple applicationVersion(); - static VersionTuple libraryVersion(); -}; - // ------------------------------------------------------------------------- QT_END_NAMESPACE diff --git a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm b/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm index c9eafa8..53ea8bc 100644 --- a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -55,9 +55,6 @@ #include -#include -#include - QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window"); @@ -376,86 +373,6 @@ QString qt_mac_removeAmpersandEscapes(QString s) #error "32-bit builds are not supported" #endif -QOperatingSystemVersion QMacVersion::buildSDK(VersionTarget target) -{ - switch (target) { - case ApplicationBinary: return applicationVersion().second; - case QtLibraries: return libraryVersion().second; - } - Q_UNREACHABLE(); -} - -QOperatingSystemVersion QMacVersion::deploymentTarget(VersionTarget target) -{ - switch (target) { - case ApplicationBinary: return applicationVersion().first; - case QtLibraries: return libraryVersion().first; - } - Q_UNREACHABLE(); -} - -QOperatingSystemVersion QMacVersion::currentRuntime() -{ - return QOperatingSystemVersion::current(); -} - -QMacVersion::VersionTuple QMacVersion::versionsForImage(const mach_header *machHeader) -{ - static auto makeVersionTuple = [](uint32_t dt, uint32_t sdk) { - return qMakePair( - QOperatingSystemVersion(QOperatingSystemVersion::MacOS, - dt >> 16 & 0xffff, dt >> 8 & 0xff, dt & 0xff), - QOperatingSystemVersion(QOperatingSystemVersion::MacOS, - sdk >> 16 & 0xffff, sdk >> 8 & 0xff, sdk & 0xff) - ); - }; - - auto commandCursor = uintptr_t(machHeader) + sizeof(mach_header_64); - for (uint32_t i = 0; i < machHeader->ncmds; ++i) { - load_command *loadCommand = reinterpret_cast(commandCursor); - if (loadCommand->cmd == LC_VERSION_MIN_MACOSX) { - auto versionCommand = reinterpret_cast(loadCommand); - return makeVersionTuple(versionCommand->version, versionCommand->sdk); -#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13) - } else if (loadCommand->cmd == LC_BUILD_VERSION) { - auto versionCommand = reinterpret_cast(loadCommand); - return makeVersionTuple(versionCommand->minos, versionCommand->sdk); -#endif - } - commandCursor += loadCommand->cmdsize; - } - Q_ASSERT_X(false, "QCocoaIntegration", "Could not find any version load command"); - Q_UNREACHABLE(); -} - -QMacVersion::VersionTuple QMacVersion::applicationVersion() -{ - static VersionTuple version = []() { - const mach_header *executableHeader = nullptr; - for (uint32_t i = 0; i < _dyld_image_count(); ++i) { - auto header = _dyld_get_image_header(i); - if (header->filetype == MH_EXECUTE) { - executableHeader = header; - break; - } - } - Q_ASSERT_X(executableHeader, "QCocoaIntegration", "Failed to resolve Mach-O header of executable"); - return versionsForImage(executableHeader); - }(); - return version; -} - -QMacVersion::VersionTuple QMacVersion::libraryVersion() -{ - static VersionTuple version = []() { - Dl_info cocoaPluginImage; - dladdr((const void *)&QMacVersion::libraryVersion, &cocoaPluginImage); - Q_ASSERT_X(cocoaPluginImage.dli_fbase, "QCocoaIntegration", "Failed to resolve Mach-O header of Cocoa plugin"); - return versionsForImage(static_cast(cocoaPluginImage.dli_fbase)); - }(); - return version; -} - QT_END_NAMESPACE /*! \internal