getOSXVersion() shows wrong version on Big Sur

Calling getOSXVersion through SystemStats::getOperatingSystemName() returns Mac OSX 10.16. Can that be fixed?


This string is found by querying the file at /System/Library/CoreServices/SystemVersion.plist. Some early betas of Big Sur reported the version as 10.16, but I thought this was fixed for the release versions.

Please check that you’re not testing on an old beta of Big Sur. If the problem is present on a release version of Big Sur, I’ll take a look.

that file shows:




1983-2021 Apple Inc.









Which version of JUCE are you using?

On JUCE develop, getOSXVersion() just opens the SystemVersion.plist and returns the ProductVersion key. On failure, it returns an empty string:

static String getOSXVersion()
        const String systemVersionPlist ("/System/Library/CoreServices/SystemVersion.plist");

       #if (defined (MAC_OS_X_VERSION_10_13) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_13)
        NSError* error = nullptr;
        NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL: createNSURLFromFile (systemVersionPlist)
                                                                 error: &error];
        NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile: juceStringToNS (systemVersionPlist)];

        if (dict != nullptr)
            return nsStringToJuce ([dict objectForKey: nsStringLiteral ("ProductVersion")]);

        return {};

If the plist lists a version of 11.2.2, I’m not sure where the 10.16 value could be coming from.

I just tried running JUCE’s SystemInfoDemo on a machine with Big Sur 11.2.2 installed, and this outputs “Operating system: Mac OSX 11.2.2”, so this appears to work correctly on develop.

I use the current master branch. The strange thing is that the file “/System/Library/CoreServices/SystemVersion.plist” shows 11.2.2 but in the debugger NSDictionary* dict shows “10.16” as “ProductVersion”

After a bit of googling, it seems this is a compatibility feature. There’s some OS-level trickery which redirects access to this file depending on the contents of the SYSTEM_VERSION_COMPAT environment variable, and potentially also the macOS SDK which was used to build the program accessing the file.

Assuming you’re using an older SDK at the moment, could you try building with the macOS 11 SDK and see whether that resolves the issue?

I use Xcode 12.4 and assume that it uses the latest SDK. There seems to be no setting anymore to change the SDK?

Probably a macOS bug after all?

I’m using Xcode 12.4 here too. I just tried setting the deployment target to an earlier version (10.13) but the system version is still reported as 11.2.2.

This sounds like it’s probably due to the configuration of the system you’re using for testing, or due to some build setting for your app.

Have you tried any other JUCE apps to see whether they report the correct version? It might be worth opening the DemoRunner and navigating to Utilities -> SystemInfoDemo. If this also shows the incorrect version, this might point to a system-level configuration issue. If the DemoRunner displays the correct version, the issue is more likely to be a build configuration issue with your specific app.

It’s a VST3 plugin.

DemoRunner show the correct OS version. But a default plugin freshly created with the ProJucer shows 10.16.

I only changed “Hello World!” into juce::SystemStats::getOperatingSystemName()

Perhaps the SDK version used for the hosting app is the deciding factor here.

It might be worth testing in a host with a known SDK version. For example, you could build the AudioPluginHost with Xcode 12.4 + the macOS 11 SDK, and test your plugin there.

That’s probably the problem. I tried the latest version of Reaper and Steinberg VST3PluginTestHost, both show the wrong version. But AudioPluginHost shows the correct version.

Nothing much to do about it I guess?

It doesn’t sound like there’s much we can do, no.

Perhaps it’d be possible to run a new process which sets SYSTEM_VERSION_COMPAT=0 and then cats the contents of SystemVersion.plist into a temporary file which is then queried by the plugin - however this isn’t a particularly great solution, as it would introduce quite a lot of additional overhead and may not interact well with sandboxed plugins. As a result, I’d be reluctant to add this to JUCE itself.

That’s totally understandable! Thanks for your help.