Can SwiftPM not default to low macOS versions?

Edit: previous title of tis post was: “Can SwiftPM not support low macOS versions?“

This whole issue occurred to me when I was investigating this GitHub issue of mine in swift-nio:

I think it’d be nice for SwiftPM to not support macOS versions lower than 10.15 altogether.
This would enable those “back-deployed“ stuff like Span to be actually used by default without needing to do use availability macros or set platform requirements in Package.swift.

I’m assuming this also enables the future back-deployed stuff to be used in SwiftPM libraries as well without usage of availability annotations.

The issue is, right now a package like swift-nio which simply aims to match availability of SwiftPM where possible, is unable to actually use any language features / APIs that are not supported in macOS 10.12, in the main APIs.

The actual APIs need to be implemented using macOS 10.12 compatible features / APIs, and then they can provide other APIs that expose the new shiny Swift advancements to users.
This is suboptimal as the actual swift-nio development might need to be done using those worse features / APIs. For example no Spans.

I’d think this also downgrades the swift-nio team’s library maintenance experience. Possibly opening doors for bugs.

I think that’s not actually true. NIO and any other package can offer APIs that use APIs with higher availability than the package’s minimum deployment target (called platform in manifest).

The problem that you ran into here is that packages cannot depend on other packages with higher minimum deployment targets. This could be solved by Swift PM considering minimum deployment targets during resolution so that NIO could bump its minimum deployment targets to enable adding dependencies with higher minimums.

If you’re talking about the `platforms` array in Package.swift, I’m not using that, so no, that’s not the issue :sweat_smile:. I’m only using @/#available annotations.

For the case of that issue, it doesn’t make a difference if the APIs are in that package or not, based on what I mentioned above.

Right now If I really want to support swift versions as low as what SwiftPM does, I’m forced to downgrade my main underlying APIs in GitHub - swift-dns/swift-endpoint: a high-performance library containing types representing an endpoint, such as DomainName and IPv4/v6Address to directly use pointers, and then provide Span APIs guarded by availability macros.

So essentially SwiftPM is playing a big role in forcing me to use worse / less-safe APIs.

1 Like

I'm not seeing the problem then. It looks like your package:

  1. Doesn't define minimum platform versions
  2. Guards all the APIs behind @available

There should be no reason NIO or any other package can't adopt your packages then. Any other package can:

  1. Add a dependency to your package
  2. Add new APIs that have the same @available constraints as your API.

Maybe I'm missing the problem here though so if you can point me to a concrete API then I can take a look.

1 Like

So, I made a point up there about why SwiftPM should raise the minimum, and that's besides this (related) discussion.

About that specific GitHub issue, something like a socket address implementation in swift-endpoint somewhat needs to be supported without any avilability macros because a ton of other APIs will rely on it. If such a base API requires macOS 10.15, then swift-nio may as well just not claim or aim for supporting whatever SwiftPM has decided on, which is currently the case.

These are all besides the fact that by that issue what I'm thinking of is updating the current SocketAdress APIs that swift-nio provides. The new APIs need to be available as much as the current API is if it's going to replace the guts of SocketAddress.

Completely counter, I'd like to build software for macOS 10.0 (and earlier) using embedded swift and would like the minimum removed.

4 Likes

Hmm alright, but then perhaps SwiftPM can raise the default to something higher which I think would be more appropriate, and require explicit availability annotations for anything lower?

Supporting down to macOS 0 is fine by me. Defaulting to it doesn’t sound great though.

Edit: I do realize this only sounds simple and might require a decent amount of work.

Ridiculously low macOS versions? We’re still serving users on macOS 10.11 ;)

1 Like

Using SwiftPM? :sweat_smile: SwiftPM doesn’t support lower than 10.12 I think?

Anyway, it appears y’all do have use-cases for lower macOS versions? I’d still say macOS 10.12 should not be the default. That just causes issues.

macOS 10.15 and below are still a few percent of the user base, but it’s true that 10.11 are very few holdouts and we will increase the minimum deployment target soonish.

I use SwiftPM for some plug-ins that are macOS 10.13+.

2 Likes

Was playing around with my iPhone 4S w/ iOS 6 the other day and wished that I can use Embedded Swift for some nostalgic iOS 6 development too. :sweat_smile:

2 Likes

Alright I edited the title of the post to reflect my change of stance that SwiftPM should not default to low macOS versions, not “not support“.

I think the issue there is twofold:

  • You would need agreement what constitutes as old enough and re-evaluate that agreement on a regular basis. I suspect different platforms would have different intervals, as iOS developers tend to drop old versions much faster than Mac developers, for example.
  • Currently, the platforms property only defines a lower limit for the platforms explicitly listed. Introducing a default minimum version would complicate understanding a given platforms value as you now also need to know the SwiftPM version and its minimum default platforms to know the effective platforms.

For the first point, that's already what's happening although I havent seen any special communications about this. Could be that I've missed such posts, or it's possibly that the current minimum macOS version is simply the lowest possible to support, and the SwiftPM folks simply haven't put it into discussion that “we have this vision if we can increase the minimum version, and you'll gain this and that. Should we proceed or does the community think the tradeoff should not be made?”.

So to be clear the minimum supported macOS version increments already happen once in a while.

For the second point, I don’t see an issue as “platforms” should simply override the default. Just like it currently does.

The differences will be that SwiftPM will by default assume a higher macOS version, but still have a minimum supported version that it can possibly handle. So the default could be macOS 10.15, the minimum could be 10.12.

That’s a more technical discussion, I assume. It needs to happen depending on what SwiftPM can support.

The default minimum version on the other hand would be more up to personal preference and thus more difficult to find agreement on. This would need to happen in addition to the first discussion.

There is a "Deployment targets" column on the Xcode support page, which is actually the recommended minimum, you can set lower (presumably the same as in SPM), so no need to have a different agreement on the recommended value for minimum deployment target.

1 Like

The minimum deployment version can also found in the SDKSettings.plist/json file in Apple's SDKs, so Swift Package Manager could theoretically pull it from there as a source of truth.

Unfortunately, those values sometimes differ compared to what's on the Xcode support page linked above, so I'm not sure which are meant to be the "more accurate" ones. For example, the SDKSettings.json file in my copy of Xcode 26 says that macOS 10.13 is the oldest supported deployment target, but the web page says it's macOS 11. And choosing macOS 10.13 wouldn't be much help to the original poster, who wanted to cut it off later than that.

1 Like

I'm in support of bumping the minimum, or at least the default, to macOS 10.15, since you can't use Swift Concurrency prior to that. So unless you put platform requirements into your Package.swift (which cuts you off from being used by packages without platform requirements), you're stuck with a very old non-async flavor of Swift, or you need to litter your entire codebase with availability annotations.

So yeah, the current state is quite unergonomic and doesn't appear to follow progressive disclosure of complexity - it drops the whole complexity on newcomers right away.

We should make the defaults better, and make customizing it possible. But right now we're optimizing for extremely niche use cases, and everyone who needs the common configuration is having to pay the usability cost.

1 Like

@dschaefer2 Can I know what you, or someone else qualified, thinks about this?

I can create a GitHub issue if we can come to a conclusion here.

This is the best “plan“ I can come up with:

We somehow need to decide on what macOS version is appropriate to default to nowadays.
I’d say 10.15 since not only it has a lot of the important features like concurrency and Spans, but it can also continue to receive back-deployed stuff in the future.
I’ll call this macOS version the “decided“ macOS version.
We can also later come up with a plan about when and how to decide on increasing this version in the future.
Getting some help from the SDKSettings.json sounds fine to me personally but a Linux user will still need to be able to tell that version. Or if someone is using "swiftly" toolchains.
10.13 is still practically a bad version to default to.

Knowing the "decided" version, then:

  • SwiftPM will change the default assumed macOS version to the “decided“ macOS version at some point.
  • SwiftPM will still accept any macOS version down to the current minimum (10.12 IIUC).
  • platforms array will continue to override the default SwiftPM macOS version.
  • If you are using a @available(macOS myVer, *) somewhere where myVer is lower than the new "decided" aka default SwiftPM macOS version, the Swift compiler should still continue to compile that code just fine although it'll now require you to add myVer to the platforms array if you want your library to work on that macOS version too.
    Basically the compiler will assume myVer is the same as "decided".

I'm not sure how easy this'll be to implement. In theory it might just be a number to change in SwiftPM? Likely not, but I wonder how harder it gets.