Add a safety check to prevent apps from running on unsupported OSes

Although Qt declares its minimum supported OS version to the compiler
and linker, the OS ignores this information when loading shared
libraries, so instead of failing with a useful error message, the
program will simply crash at runtime. This attempts to bring that
failure as early in the lifecycle as possible, and provide a better
error message as well.

Change-Id: Ic58b44f8895eac718c94e62cad6e2506dbea8a7e
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Jake Petroules 2017-07-19 23:45:18 -07:00
parent 854fdaaf76
commit 8418a6335b
3 changed files with 35 additions and 0 deletions

View File

@ -280,6 +280,36 @@ Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode)
#endif // Q_OS_OSX
void qt_apple_check_os_version()
{
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
const char *os = "iOS";
const int version = __IPHONE_OS_VERSION_MIN_REQUIRED;
#elif defined(__TV_OS_VERSION_MIN_REQUIRED)
const char *os = "tvOS";
const int version = __TV_OS_VERSION_MIN_REQUIRED;
#elif defined(__WATCH_OS_VERSION_MIN_REQUIRED)
const char *os = "watchOS";
const int version = __WATCH_OS_VERSION_MIN_REQUIRED;
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
const char *os = "macOS";
const int version = __MAC_OS_X_VERSION_MIN_REQUIRED;
#endif
const NSOperatingSystemVersion required = version >= 100000
? (NSOperatingSystemVersion){version / 10000, version / 100 % 100, version % 100}
: (NSOperatingSystemVersion){version / 100, version / 10 % 10, version % 10};
const NSOperatingSystemVersion current = NSProcessInfo.processInfo.operatingSystemVersion;
if (![NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:required]) {
fprintf(stderr, "You can't use this version of %s with this version of %s. "
"You have %s %ld.%ld.%ld. Qt requires %s %ld.%ld.%ld or later.\n",
((NSString *)NSBundle.mainBundle.infoDictionary[@"CFBundleName"]).UTF8String,
os,
os, current.majorVersion, current.minorVersion, current.patchVersion,
os, required.majorVersion, required.minorVersion, required.patchVersion);
abort();
}
}
// -------------------------------------------------------------------------
QT_END_NAMESPACE

View File

@ -152,6 +152,8 @@ Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key);
Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
#endif
Q_CORE_EXPORT void qt_apple_check_os_version();
QT_END_NAMESPACE
#endif // QCORE_MAC_P_H

View File

@ -437,6 +437,9 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
, q_ptr(0)
#endif
{
#if defined(Q_OS_DARWIN)
qt_apple_check_os_version();
#endif
app_compile_version = flags & 0xffffff;
static const char *const empty = "";
if (argc == 0 || argv == 0) {