'Build error for macOS in Swift Package for iOS platform

I am trying to add support for Swift Package Manager to one of my frameworks. The framework is iOS specific (I make use of UIKit on it), so I added the platforms configuration to my Package.swift file which now looks like this:

import PackageDescription


let package = Package(
    name: "MyLibrary",
    platforms: [
        .iOS(.v11)
    ],
    products: [
        .library(
            name: "MyLibrary",
            targets: ["MyLibrary"]),
    ],
    targets: [
        .target(
            name: "MyLibrary",
            path: "Sources"),
        .testTarget(
            name: "MyLibraryTests",
            dependencies: ["MyLibrary"]),
    ]
)

Even though the package builds correctly on Xcode. When running swift build in the console I get the following error.

error: no such module 'UIKit'

Adding the -v flag to make the compilation more verbose I see that it is trying to build the package for macOS and that's why it fails.

Why is it building the framework for macOS if it is not listed in platforms? is this not the way to make an iOS specific swift package?



Solution 1:[1]

I've hit this myself, and the key is that the list of supported platforms you define in platforms doesn't exclude any platforms you don't list, it only sets a minimum for those that you do.

This isn't clear in the docs for SupportedPlatform. However, in the Creating a Standalone Swift Package with Xcode page, there's a comment at the bottom that tackles the issue (my emphasis):

Note how the package manifest below declares minimum deployment targets by passing them in as a value to the platforms parameter of the Package initializer. However, passing minimum deployment targets to the initializer doesn’t restrict the package to the listed platforms.

Instead, what you might be able to do is use conditional compilation blocks around your code. So instead of just

import UIKit

extension UIColor {
  // or whatever UIKit dependency you're using
}

you can wrap your code in a check so that it skips everything if you're building for macOS:

#if !os(macOS)
import UIKit

// your code
#endif

Or maybe even, to be a little cleverer about it, check for the existence of UIKit so that you're building based on a feature set, rather than a platform:

#if canImport(UIKit)
import UIKit

// your code
#endif

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Scott Matthewman