I am building a package that contains a lot of classes, extensions and modules I have been building since I started developing for iOS in 2008.
Because I also develop for macOS, watchOS, iPadOS, and tvOS, this package has code for every flavor or Apple device.
In this package in particular, I have stuff for iOS and tvOS.
The package is declared like:
import PackageDescription
let package = Package(
name: "MyPackage",
platforms: [.iOS(.v16), .tvOS(.v13)],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "MyPackage",
targets: ["MyPackage"]),
],
targets: [
.target(name: "MyPackage"),
.testTarget(name: "MyPackageTests", dependencies: ["MyPackage"])
]
)
I have imported this package into a project that has two targets, one for iOS and another for watchOS because I want to use the stuff it contains for iOS in the iOS target.
I am now debugging the iOS target. Even so, Xcode gives a lot of errors, because it is trying to compile the package against the watchOS target.
This forces me to add #if !os("watchOS)
and #endif
in every file the package has to isolate the code and prevent it from being compiled by Xcode for the watchOS target. This is pretty stupid because the package is declared like this:
platforms: [.iOS(.v16), .tvOS(.v13)],
And because the package was just added for the iOS target.
Is there any way to do Xcode work as expected and not compile a package for a target it is not declared for?
Failing to include a platform means that the package supports the default version for that platform:
By default, the Swift Package Manager assigns a predefined minimum deployment version for each supported platforms unless you configure supported platforms using the platforms API. This predefined deployment version is the oldest deployment target version that the installed SDK supports for a given platform. One exception to this rule is macOS, for which the minimum deployment target version starts from 10.10. Packages can choose to configure the minimum deployment target version for a platform by using the APIs defined in this struct. The Swift Package Manager emits appropriate errors when an invalid value is provided for supported platforms, such as an empty array, multiple declarations for the same platform, or an invalid version specification.
There is no way to express "does not support an Apple platform" in SPM. You can express "not available for a platform" with @available
, but the code still has to compile, which generally means adding #if
tests.
Note that #if !os(watchOS)
means it does compile for visionOS. Any time a new platform comes along, it is automatically supported by all packages.