Why Big Sur won’t stumble over version numbers

The surprise announcement of WWDC this year wasn’t the new Apple Silicon Macs, which had been widely expected, but the decision to number the next major version of macOS 11.0 rather than 10.16. That’s one choice Apple could have come to regret, and this article explains how it’s having to engineer its way out of breaking features in existing apps.

Ever since anyone can remember, Apple has identified Mac operating system versions using three version numbers:

  1. The first is the major version number, which ran up to 9 in Classic Mac OS, and has been 10 ever since the first release of Mac OS X.
  2. The second is the minor version number, which in Classic days seldom rose far. In recent Mac OS X, though, there’s been a new version each year, such as Mojave 10.14 and Catalina 10.15.
  3. The third is the patch number. In recent macOS, this has risen to x.x.6 at the end of each release cycle.

In the five years from the release of Mac System Software 1.0 in 1986, the major version rose to 7. When you developed software for Classic Mac OS, it was usually that number which counted most in determining features and compatibility. Then, when Apple released Mac OS X 10.0 in 2001, version numbering changed completely. Over those 19 years, the major version has remained fixed at 10, and the minor version has steadily climbed to 15.

We’re all well aware of the multitude of changes that come with each new ‘minor’ version. My apps that offer log extracts but run on El Capitan and later require code to disable their log feature for 10.11, as the unified log wasn’t introduced until 10.12. Commands using softwareupdate have also changed with different versions of macOS.

To cater for all these differences, many apps use conditional statements. In effect, they might say ‘if I’m running on Sierra, do this; if it’s High Sierra or later, do that.’ One of the most widely used methods of checking which version of macOS is running is to inspect the Operating System version; in Swift, a call such as ProcessInfo.processInfo.operatingSystemVersion returns complete information ready for use in the conditional.

So a typical code fragment in Swift might be
let osVersion = ProcessInfo.processInfo.operatingSystemVersion.minorVersion
if (osVersion > 13) {

// we’re on Mojave or later
} else if (osVersion == 13) {
// we’re on High Sierra
} else {
// we’re on Sierra or earlier

Most of us had assumed that the next major release of macOS, now dubbed Big Sur, was going to continue the number sequence as 10.16. Apparently not long before it was announced at WWDC, this was changed to become 11.0, with the major version number incremented from 10 to 11, and the minor version number reset to 0 from 15. If you step your way through the example code above, you’ll notice that it could now break. If Big Sur were to be numbered 10.16, the first if condition would be satisfied, and it would be treated the same as Mojave and later. If Big Sur were to be 11.0, then the app would fall through to the last of the conditionals, and be treated the same as Sierra and earlier, clearly the wrong choice.

The only solution which wouldn’t break a great deal of existing software would be for Big Sur to return a major version of 10 and a minor version of 16. But at the same time, it has to return a major version of 11 and a minor version of 0, or it wouldn’t really be macOS 11 after all. And Big Sur actually does both, depending on how it’s asked.

Apps which have been developed with Xcode 11 and earlier use the 10.15 SDK and its antecedents; when they check ProcessInfo.processInfo.operatingSystemVersion.minorVersion (or its equivalent), Big Sur identifies itself as macOS 10.16. This is the most compatible solution, and should, for instance, allow you to run your existing Intel apps on Apple Silicon without them acting as if they were running on OS X 10.0.

Apps which are being ported to Xcode 12 use the 11.0 SDK; when they check ProcessInfo.processInfo.operatingSystemVersion.minorVersion (or its equivalent), Big Sur identifies itself as macOS 11.0. This has been confirmed for the DTK by @yiningkarlli.

There’s one temporary issue: the initial developer beta for Intel Macs doesn’t yet work like that, but seems to return a version number of 10.16 to everything. Apple mentions this in its macOS Big Sur 11 Beta Release Notes:
“The system ProductVersion is reported as 11.0 only on the Developer Transition Kit at this time. Existing Mac systems will temporarily report the value as 10.16.”

This is unfortunate, as it makes porting to Intel Macs too easy. Conflicts with Big Sur’s version number therefore won’t become readily apparent until Intel beta releases behave as does the DTK. But this only applies to those apps which have already been built with Xcode 12 on Intel Macs.

There’s also a sting in the tail for those who use development systems other than Xcode: they need to check how their SDK handles macOS versions on both Intel and Apple Silicon Macs. This is most critical for anyone using command tools to detect the version of macOS which is running. Among the most popular is
sw_vers -productVersion
which currently returns 10.16 when running in Big Sur on an Intel Mac, presumably changing soon to 11.0, and 11.0 on an Apple Silicon Mac, as stated by Apple.

As I wrote last week, this is going to prove one of the biggest headaches for developers, scripters and users when upgrading to Big Sur. There are lots of possible workarounds, but for those who don’t need to worry about macOS 10.9 or earlier, or macOS 11.10 or later, one quick fix is:
var osVersion = ProcessInfo.processInfo.operatingSystemVersion.minorVersion
if osVersion < 10 { osVersion += 16 }

In the longer term, it would be much simpler if Apple were to provide a monotonically increasing positive integer which increased by 1 with every patch number. This would spare everyone from having to change code whenever a new major version appears.

When you upgrade to Big Sur, remember that some software may behave strangely, as if running on a much older version of macOS. If you come across any, ask its developer whether it detects the macOS version number correctly.