summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qcore_mac.mm
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2020-07-28 16:45:07 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2020-07-29 13:25:28 +0200
commit19d32f0a5fc8b12e03a84ab6e18845337fd3b70f (patch)
treec0f3e33e8d5fc1d1f9d32b2b5f580b120ede1ba1 /src/corelib/kernel/qcore_mac.mm
parent3e71e2e85124b750c0e385212d44ea57acf270f3 (diff)
Add QOperatingSystemVersion support for macOS Big Sur
Pick-to: 5.15 Pick-to: 5.12 Change-Id: Ide57f675b20b08210f301da5177df45d008423c4 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Diffstat (limited to 'src/corelib/kernel/qcore_mac.mm')
-rw-r--r--src/corelib/kernel/qcore_mac.mm83
1 files changed, 83 insertions, 0 deletions
diff --git a/src/corelib/kernel/qcore_mac.mm b/src/corelib/kernel/qcore_mac.mm
index 57d818ffd4..b94b06adb4 100644
--- a/src/corelib/kernel/qcore_mac.mm
+++ b/src/corelib/kernel/qcore_mac.mm
@@ -53,6 +53,7 @@
#include <dlfcn.h>
#include <cxxabi.h>
#include <objc/runtime.h>
+#include <mach-o/dyld.h>
#include <qdebug.h>
@@ -540,6 +541,88 @@ QT_BEGIN_NAMESPACE
// -------------------------------------------------------------------------
+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::currentType(),
+ dt >> 16 & 0xffff, dt >> 8 & 0xff, dt & 0xff),
+ QOperatingSystemVersion(QOperatingSystemVersion::currentType(),
+ 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 || 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);
+#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);
+#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