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
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?).
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â.
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.
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?
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.
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.
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.
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.
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.