5.13.2: back port big sur detection

This commit is contained in:
kleuter 2020-11-18 11:33:42 +01:00
parent 730c5b3b96
commit 2ce8eeeed3
7 changed files with 185 additions and 103 deletions

View File

@ -42,6 +42,10 @@
#include "qoperatingsystemversion_p.h"
#endif
#if defined(Q_OS_DARWIN)
#include <QtCore/private/qcore_mac_p.h>
#endif
#include <qversionnumber.h>
#include <qdebug.h>
@ -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).

View File

@ -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;

View File

@ -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

View File

@ -45,6 +45,9 @@
#include "qmutex.h"
#include "qvarlengtharray.h"
#include <dlfcn.h>
#include <mach-o/dyld.h>
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<load_command *>(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<version_min_command *>(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<build_version_command *>(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<mach_header*>(qtCoreImage.dli_fbase));
}();
return version;
}
// -------------------------------------------------------------------------
QT_END_NAMESPACE

View File

@ -53,6 +53,9 @@
#include "private/qglobal_p.h"
#include <QtCore/qoperatingsystemversion.h>
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<QOperatingSystemVersion, QOperatingSystemVersion>;
static VersionTuple versionsForImage(const mach_header *machHeader);
static VersionTuple applicationVersion();
static VersionTuple libraryVersion();
};
// -------------------------------------------------------------------------
QT_END_NAMESPACE
#endif // QCORE_MAC_P_H

View File

@ -194,26 +194,6 @@ constexpr backwards_t<R> backwards(R&& r) { return {std::forward<R>(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<QOperatingSystemVersion, QOperatingSystemVersion>;
static VersionTuple versionsForImage(const mach_header *machHeader);
static VersionTuple applicationVersion();
static VersionTuple libraryVersion();
};
// -------------------------------------------------------------------------
QT_END_NAMESPACE

View File

@ -55,9 +55,6 @@
#include <algorithm>
#include <mach-o/dyld.h>
#include <dlfcn.h>
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<load_command *>(commandCursor);
if (loadCommand->cmd == LC_VERSION_MIN_MACOSX) {
auto versionCommand = reinterpret_cast<version_min_command *>(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<build_version_command *>(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<mach_header*>(cocoaPluginImage.dli_fbase));
}();
return version;
}
QT_END_NAMESPACE
/*! \internal