Hi all,
I've recently merged some changes into qtbase that I think warrant a
warning/announcement to help people understand some strange errors that might
pop up in the future.
The background is this: in Xcode 9, there is a new Clang builtin function
called __builtin_available (C, C++) / @available (Objective-C). There is also a
new warning, unguarded-availability, which will be emitted whenever you
unconditionally call an API that might not be available on your deployment
target (for example if we call an API introduced in macOS Sierra v10.12, but Qt
must still be compatible with OS X Yosemite v10.10). By wrapping the API call
site like so:
if (__builtin_available(macOS 10.12, *)) {
// Call 10.12 API normally
} else {
// Do something else for 10.10 and 10.11
}
we inform the compiler via __builtin_available that we are performing the
necessary runtime check for the OS version before calling any potentially
unavailable APIs. This means that we get compile time validation of API
availability for APIs we use in Qt, something that has previously only been
availably in Swift. Like always, the compiler automatically takes care of
weak-linking the functions so there is no need to use dlopen/dlsym, and this
works for all languages.
This builtin is part of LLVM 5, here are the docs:
https://clang.llvm.org/docs/LanguageExtensions.html#objective-c-available
Now, as for what this means for Qt. In Qt 5.10 and beyond,
unguarded-availability warnings are now a hard error
(https://codereview.qt-project.org/#/c/206348/). But what about older versions
of Clang, and other compilers, where this builtin is not available? Thanks to a
bit of macro magic (https://codereview.qt-project.org/#/c/206346/16//ALL),
we'll be able to use this new builtin function everywhere in Qt, on all
compilers and platforms. My "polyfill" will simply transform the
__builtin_available calls to an implementation that uses
QOperatingSystemVersion behind the scenes, to perform the check.
Basically, all you need to do is make sure you use __builtin_available where
necessary (and Xcode 9 will force you to). You may no longer use
QSysInfo::macVersion (which is deprecated entirely, by the way),
QOperatingSystemVersion, or respondsToSelector, to perform API availability
checks. If you run into an error like "symbol 'macOS' undefined", you probably
forgot to include qglobal_p.h, where the polyfill is housed.
I've already audited the entire Qt codebase, and adjusted all call sites as
necessary. Unless I missed something, the work is done, but for future
development, now everyone knows.
Cheers,
--
Jake Petroules - jake.petrou...@qt.io
The Qt Company - Silicon Valley
Qbs build tool evangelist - qbs.io
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development