What's the best solution for products with special platform requirements?

I've got a product in a package. This works for me organizationally, but while the package is cross-platform, nothing in this product will compile for watchOS.

As far as I know, I've got two options, neither of which is good:

  1. Separate the product into another package.
  2. Use conditional compilation on the entirety of every file in the product.

What do people do?

Edit: I had mentioned here that platforms operates at the package level, not the product level—but it turns out to be irrelevant here.

I use a build time error for unsupported platforms or Swift versions.

#if os(watchOS)
#error("This package does not support watchOS."
#endif
1 Like

Is that a match for what I'm talking about?

Most of the other products in the package support watchOS. Using that code, the package seems unusable for a watchOS target, which is no different than not marking it with conditional compilation, other than a clearer error message.

It doesn't go in the package, it goes in one of the target's source files. Really there's nothing you can do here but make the error better, hence the direct condition. That way you don't conditionalize everything, just the one place.

I don't know what other option there would be. I'm not trying to use it in the manifest file, if that's what you're thinking.

#if !os(watchOS)

allows the package to be used for a watchOS target. (This is solution 2 in my original post.)

As far as I can tell, what you're suggesting doesn't make the rest of the package usable for a watchOS target.

You said nothing in the product will compile for watchOS. Naturally I assumed that meant you were looking for a nicer way to present that fact. If that's not the case, what's your goal? Let the target compile with no functionality on watchOS?

Yes, or at least, I can't think of better. This is functionally equivalent to having a separate package, and not importing that package.

Not that it would affect the solution I'm asking about, but I currently think that products which are not added to a target shouldn't need to compile. But things don't work that way, so I'm probably wrong.

To my knowledge, John’s suggestion is the only way to express platform incompatibility. It’s what we’ve advised authors to use to express it in the Swift Package Index in the past.

The confusing bit about the platform stanza is that it can only express a minimum required version for a platform and a platform’s absence simply means it has no such minimum version requirement.

2 Likes

We've talked about "submodule"-level code here so far. It seems that the two of you favor separation into packages, for those, rather than not compiling them when unsupported.

What about type-level code, or even finer grained? Do you also advocate avoiding…

@available(whateverOS, unavailable)

…and always extract such code into "micro frameworks"?