summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa/qcocoahelpers.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoahelpers.mm')
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 0f5ddfa49a..36841c77ab 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -55,6 +55,9 @@
#include <algorithm>
+#include <mach-o/dyld.h>
+#include <dlfcn.h>
+
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window");
@@ -368,6 +371,85 @@ QString qt_mac_removeAmpersandEscapes(QString s)
return QPlatformTheme::removeMnemonics(s).trimmed();
}
+// -------------------------------------------------------------------------
+
+#if !defined(Q_PROCESSOR_X86_64)
+#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)
+{
+ 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);
+ uint32_t dt = versionCommand->version; // Deployment target
+ uint32_t sdk = versionCommand->sdk; // Build 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)
+ );
+ }
+ commandCursor += loadCommand->cmdsize;
+ }
+ Q_ASSERT_X(false, "QCocoaIntegration", "Could not find version-min 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