macOS: Log Qt and macOS version information at startup

The SDK and deployment target versions are helpful to know when
diagnosing issues.

Change-Id: I85026bd9c1d706a923e8953837bd59bf9ed0266f
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
bb10
Tor Arne Vestbø 2018-10-18 18:00:40 +02:00
parent ae57e271e8
commit 199b67f11c
3 changed files with 141 additions and 0 deletions

View File

@ -52,6 +52,7 @@
//
#include "qt_mac_p.h"
#include <private/qguiapplication_p.h>
#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/qpalette.h>
#include <QtGui/qscreen.h>
@ -60,6 +61,8 @@
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSView));
struct mach_header;
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcQpaWindow)
@ -173,6 +176,34 @@ T qt_mac_resolveOption(const T &fallback, QWindow *window, const QByteArray &pro
return fallback;
}
// -------------------------------------------------------------------------
#if !defined(Q_PROCESSOR_X86_64)
#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
// @compatibility_alias doesn't work with protocols

View File

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

View File

@ -79,6 +79,32 @@ static void initResources()
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpa, "qt.qpa", QtWarningMsg);
static void logVersionInformation()
{
if (!lcQpa().isInfoEnabled())
return;
auto osVersion = QMacVersion::currentRuntime();
auto qtBuildSDK = QMacVersion::buildSDK(QMacVersion::QtLibraries);
auto qtDeploymentTarget = QMacVersion::deploymentTarget(QMacVersion::QtLibraries);
auto appBuildSDK = QMacVersion::buildSDK(QMacVersion::ApplicationBinary);
auto appDeploymentTarget = QMacVersion::deploymentTarget(QMacVersion::ApplicationBinary);
qCInfo(lcQpa, "Loading macOS (Cocoa) platform plugin for Qt " QT_VERSION_STR ", running on macOS %d.%d.%d\n\n" \
" Component SDK version Deployment target \n" \
" ------------- ------------- -------------------\n" \
" Qt " QT_VERSION_STR " %d.%d.%d %d.%d.%d\n" \
" Application %d.%d.%d %d.%d.%d\n",
osVersion.majorVersion(), osVersion.minorVersion(), osVersion.microVersion(),
qtBuildSDK.majorVersion(), qtBuildSDK.minorVersion(), qtBuildSDK.microVersion(),
qtDeploymentTarget.majorVersion(), qtDeploymentTarget.minorVersion(), qtDeploymentTarget.microVersion(),
appBuildSDK.majorVersion(), appBuildSDK.minorVersion(), appBuildSDK.microVersion(),
appDeploymentTarget.majorVersion(), appDeploymentTarget.minorVersion(), appDeploymentTarget.microVersion());
}
class QCoreTextFontEngine;
class QFontEngineFT;
@ -112,6 +138,8 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
, mServices(new QCocoaServices)
, mKeyboardMapper(new QCocoaKeyMapper)
{
logVersionInformation();
if (mInstance)
qWarning("Creating multiple Cocoa platform integrations is not supported");
mInstance = this;