What are the versions of macOS on which programs built with each version of Swift can run?

What are the versions of macOS on which programs built with each version of Swift can run?

Are there any caveats to any pairs of macOS/Swift? (like certain features don't work on certain combos, extra runtimes must be installed for certain combos, etc.)

Can you provide a definitive source for the compatibility info? I've seen differing claims of compatibility, so I don't know exactly what to believe.

Does swift-tools-version in Package.swift specifically define what language version is used by by the package? Or are there other settings that influence that, too? Will Swift Package Manager give an error or warning if platforms includes an OS that's too old for the swift-tools-version?

Note that I'm not asking about what versions of macOS or Xcode can build programs written in a version of Swift. This is about what versions of macOS can run a program.

Additional info about iOS, iPadOS, watchOS, tvOS, etc. version & Swift version support would also be welcome.

This is about what versions of macOS can run a program.

In Apple parlance that’s the deployment target.

My go-to doc for this sort of thing is Developer > Support > Articles > Xcode. It doesn’t exactly answer your question, but it largely answers it in practice. For example, if you want Swift 6 you need Xcode 16 or later which has a minimum deployment target of macOS 10.13.

Are there any caveats to any pairs of macOS/Swift?

Yes. The big one is that Swift concurrency will only deploy back to macOS 10.15. However, there are lots and lots of other limitations. Most of these come under the aegis of the macOS SDK. For example, the ScreenCaptureKit framework was introduced in macOS 12.3 and you can’t use it on older systems.

Swift has availability attributes to manage this process. Each API is decorated with attributes that tell you when it was introduced. The compiler processes these, fails if you call an API that’s prior to your deployment target, and gives you options to manage how you call those APIs in a conditional way.

There are also back deployment issues that are more closely related to the language. For example, regular expressions are a language feature but they don’t back deploy prior to macOS 13. There’s no single source for all of that info but, generally, the Swift Evolution proposal that introduced the feature has information about whether it’ll back deploy or not.

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

6 Likes

@eskimo Thanks for the info.

If platforms specifies a macOS release like .v10_11, will the Xcode build system / Swift compiler warn or error if anything requires a newer version of macOS?

If so, are those warnings/errors solely from Apple code (Swift itself, core Swift APIs, any Apple API (including open source GitHub repos)), or can third-party code also provide such helpful warnings/errors?

I assume that Xcode / the Swift compiler would read various Swift availability keywords in code to provide that info, but I'd prefer to hear from you rather than just making my own assumptions.

Thanks again.

If platforms specifies a macOS release like .v10_11, will
the Xcode build system / Swift compiler warn or error if
anything requires a newer version of macOS?

Yes. This is what I meant when I said “Swift has availability attributes to manage this process.” I was kinda hoping you’d use that as a search term to discover more independently. Anyway:

  • The core info is in the docs.

  • As to how this pans out in practice, there are lots of great blog posts about that. I’m not gonna post a link to a specific one because, on searching the ’net for Swift availability attributes, the first page of results includes articles from three of my favourite Swift blogs, and choosing between them is like choosing between my children (-:

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

2 Likes

The compatibility matrix that you shared leaves me with many questions.

Each row is for a version of Xcode.

The lower bound of the macOS deployment targets for each version of Xcode 14 or newer is 10.13. My Swift Package specifies macOS 10.11 & Swift 5.6.1, but Xcode 14.2 doesn’t give me any warnings or errors about 10.11 being less than 10.13.

Are the deployment target lower bounds due to the Xcode version, or due to the version of Swift? e.g., in the matrix, Xcode 14 shows Swift 5.7. Swift 5.6 is listed for Xcode 13.3 & 13.4, along with a macOS deployment target lower bound of 10.9. So, could using Swift 5.6 on Xcode 14.2 allow me to deploy back to 10.9?

Is the swift command-line executable considered part of Xcode, specifically for the the versions of macOS supported as deployment targets? Or does that have a different compatibility matrix?

Thanks.

My Swift Package specifies macOS 10.11 & Swift 5.6.1, but
Xcode 14.2 doesn’t give me any warnings or errors about 10.11
being less than 10.13.

Let’s start with a basic test case. That chart lists the minimum deployment target for Xcode 16.0 as macOS 10.13. Using Xcode 16.0 I created a test project from the macOS > Command Line Tool template. I set the deployment target to 10.13 and the program compiled without problems. I then lowered it to 10.12, and the build started raising this warning:

The macOS deployment target 'MACOSX_DEPLOYMENT_TARGET' is set to 10.12, but the range of supported deployment target versions is 10.13 to 15.0.99.

I then repeated that process for a new package, created from the macOS Command-Line Tool template. There were a couple of things to note. The first is that, in the absence of any platform constraints, Xcode applies its default constraint. That is, out of the box the Command-Line Tool template builds for macOS 10.13. Consider this:

% vtool -show-build Test75120B
Test75120B (architecture x86_64):
Load command 9
      cmd LC_VERSION_MIN_MACOSX
  cmdsize 16
  version 10.13
      sdk 15.0
Test75120B (architecture arm64):
Load command 10
      cmd LC_BUILD_VERSION
  cmdsize 32
 platform MACOS
    minos 11.0
      sdk 15.0
        …

Note how the Intel architecture targets 10.13 and the Apple silicon architecture targets 11.0, the initial macOS release for Apple silicon [1].

If I add a platform constraint for 10.12, I get this warning:

platforms: [.macOS(.v10_12)],
                 // ^ 'v10_12' is deprecated: macOS 10.13 is the oldest supported version

I haven’t tested this on older versions of Xcode; it’s possible that those are less fastidious. Regardless, the rules here are clear: Xcode has a minimum deployment target for each platform, and targeting releases earlier than that is not supported.

Moreover, not following these rules can lead to weird problems, like the ones discussed in this thread.

So, could using Swift 5.6 on Xcode 14.2 allow me to deploy back to 10.9?

No. The Swift language version is not the deciding factor here. The entire toolchain is built with a minimum deployment target. IME the most critical components in this calculus are the SDK and linker.

Is the swift command-line executable considered part of
Xcode, specifically for the the versions of macOS supported as
deployment targets?

Yes.

And not just the Swift compiler. Each version of Xcode includes a toolchain, comprising the tools, SDK, and so on. That toolchain has the same deployment constraints as the Xcode in which it’s contained.

Likewise for the Command Line Tools package, where each package has the same deployment constraints as it ‘parent’ Xcode.

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

[1] Annoyingly, macOS does not currently enforce the constraints expressed in LC_VERSION_MIN_MACOSX and LC_BUILD_VERSION. That is, macOS 10.12 won’t fail early if you run this tool. It might work or it might not, depending on a variety of factors. (When things fail, they typically fail because of a dynamic linking error.)

IMO this is a bug. macOS should use this build commands to fail early. However, changing this is a compatibility challenge.

3 Likes