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

Reply via email to