Platforms Stanza for Linux

Hello everyone,

Server developers, which are mainly focused on Linux, often bring up confusion around the meaning of the Platforms stanza.

Since the launch of swift-crypto which is cross-platform but has a requirement on recent Apple releases it is common to see in packages that are mainly targeted at Linux (e.g. vapor) the following stanza:

platforms: [
  .macOS(.v10_15),
],

Which explicitly says that macOS >= 10.15 is supported but implicitly suggests Linux is supported. This explicit/implicit gap confuses many folks that interpret the stanza to say that the package is only targeting macOS.

One idea to resolve this confusion could be to make the platform support more explicit, e.g

platforms: [
  .linux(*),
  .macOS(.v10_15),
],

What do folks think?

4 Likes

Sounds good to me, I don't think we need the ability to specify versions in there for linux (as it's quite a mixed bag anyway, what would such version be there really?).

You should never use platforms unless you know the exhaustive list of client packages (i.e. something internal to your company)

@available is always better, because then your clients aren’t forced to narrow their own requirements.

swift‐crypto should probably be fixed in that respect.

What’s the point of supporting integration into targets that can’t use any of the functionality provided by your library?

Because it breaks the entire package graph at resolution time even if the particular product for which it matters isn’t actually part of the build.

I’d rather see it replaced or supplemented by something that actually does what it looks like platforms does: declare an explicit list of supported platforms and versions. At the moment SPM has no way to declare a library solely for Linux, for example, just the far weaker requirement of a “deployment target”.

1 Like

That seems like an issue with the resolver, not something to burden every library with hundreds of availability annotations over.

At such time as the restriction no longer oversteps itself, that would be fine. But while conditional target dependencies are pending, conditional package dependencies aren’t even on the horizon. Another helpful tool for this would be moving the deployment versions down to the target level. Either of those would be a better immediate focus, because without them, @available is the only way to prevent stomping the entire graph.


As someone who uses Swift with Windows, Android, and Web, I do not want a world where the platforms have to be exhaustively declared. There is much that currently just works that would suddenly be pulled out of reach.

1 Like

I have real concerns about establishing the idea that Linux is a monolith. @ktoso is right to say that Linux does not have “versions” per-se, but a bunch of the Linux userspace is versioned, and in principle we can take a userspace-based approach to defining the Linux platform. I want to avoid us painting ourselves into a corner we can’t easily get out of again.

I’m also not sure whether this adds or removes confusion. There are at least three tools versions that have shipped already with the current interface: those tools versions cannot be changed to have this requirement (because it’s breaking), so instead we’ll be changing the interpretation of a pre-existing stanza across a tools version: the platforms directive used to have an implicit “accept all others”, now it has an implicit “reject all others”. This is going to surprise some folks!

Finally, note that changing to implicit reject makes adopting new platforms harder. For example, it means the entire Swift ecosystem now claims it doesn’t work on Windows, even though large swathes of it do. That’s a difficult case to justify: how do users opt out of this?

3 Likes

That crossed my mind and I don’t think “reject by default” is an option given the large amount of projects which simply happen to work today.

So the information would be more informational than enforcing — does that bring value to warrant it? I guess at least by looking at a package one could know if it was “intended to work on Linux” or “we have no idea if it works on linux”. Question is if we think that’s valuable.

I'm actively opposed to a do-nothing .linux directive: that invites even more confusion by adding something that people will reasonably expect has an effect, but that does nothing. I think it makes the situation today even worse.

1 Like

To clarify, I don't think this would work. As the flag is binary (we either added it or we didn't) it's impossible to tell the difference between "we have no idea if this works on Linux" or "we know it does not work on Linux". Both signals are the same. This is the same confusion we have today, but we've now formalised it in the system.

At least right now the system has an underlying logic. Sure, lots of people don't know it, but if you tell them the underlying logic they will understand. If we added a purely informational directive we've confused that underlying logic terribly, without addressing the original problem.

2 Likes

We previously discussed platform restrictions when we initially proposed the platforms API, the review thread is here for reference.

I think the main tension we have to solve is between the case where package authors know a certain platform isn't supported (e.g. if the package uses platform specific frameworks such as UIKit) vs. what happens if a new platform is supported by Swift. It is certainly not feasible for the entire package ecosystem to release new versions every time a new platform becomes officially supported and it also makes bringing up a platform harder. On the other hand, it is likely frustrating for developers to depend on a package only to find out that it doesn't build or work correctly on a platform they support.

Ideally, we could rephrase the problem by allowing package authors which frameworks and APIs they need instead of explicitly declaring platform support. For example, if there was the ability to depend on UIKit with a particular version, a package would have automatically be seen as supporting MacCatalyst when it became available. Similarly, if a package only requires Foundation, it would automatically support Windows when that becomes available. This is a pretty big leap from what we have today, though, and likely not feasible in the near term.

7 Likes

I don’t find the following to be a very exciting option, but perhaps barring more substantial reworking the argument platforms could be renamed (in future API versions, not as a breaking change to past versions) to something like platformRestrictions or platformMinimums. I don’t personally find it too confusing now that I’m used to it, but I don’t think I speak for the average first time user of SPM.

4 Likes

I find this idea compelling. The remaining question is what can be done in the more immediate time frame to either better convey the true intent of the platforms stanza (which is more of platformRestrictions as @mattpolzin points out) or how to make it close the implicit/explicit gap so its less confusing to use

My worry would be that renaming the API will make the situation even more confusing, because packages using a tools-version prior to the rename will of course continue to use the old name. It seems like that would reinforce the idea that platforms has a meaning that it does not.