66

I have a Package.swift in my project like:

import PackageDescription

let package = Package(
    name: "ProjectName",
        dependencies: [
           .Package(url: "https://github.com/example/repo.git", majorVersion: 0)
        ]
 )

When I run swift build I get errors like…

/project/Packages/WebViewController.swift:1:8: error: no such module 'UIKit'
import UIKit
       ^

Where should I tell the swift package manager where to find UIKit?

Onato
  • 9,916
  • 5
  • 46
  • 54

7 Answers7

53

You have to change some swiftc options to build the project against proper sdk and target

swift build -Xswiftc "-sdk" -Xswiftc "`xcrun --sdk iphonesimulator --show-sdk-path`" -Xswiftc "-target" -Xswiftc "x86_64-apple-ios13.0-simulator"
AbdelAli
  • 796
  • 1
  • 6
  • 6
  • 8
    This should be the accepted answer! I can confirm it works with iOS 14 using the following too: `swift build -Xswiftc "-sdk" -Xswiftc "\`xcrun --sdk iphonesimulator --show-sdk-path\`" -Xswiftc "-target" -Xswiftc "x86_64-apple-ios14.0-simulator"` – blackjacx Sep 01 '20 at 12:23
  • For the tvOS: `swift build -Xswiftc "-sdk" -Xswiftc "\`xcrun --sdk appletvsimulator --show-sdk-path\`" -Xswiftc "-target" -Xswiftc "x86_64-apple-tvos14.3-simulator"` – Anton Plebanovich Apr 07 '21 at 11:17
  • This worked for me, but then Xcode doesn't recognize the binary inside the project that I want to use the library dependency for that was specified in the Package.swift. I think I'm missing an obvious step...? – user3773048 Jan 11 '22 at 17:29
  • 1
    I'm trying to build for `watchOS` and `macCatalyst`. I've figured out I can use `watchsimulator` and `macosx` in place of `iphonesimulator`, but I can't figure out the list of available `-target` values. How did you find `x86_64-apple-ios13.0-simulator`? – AdamPro13 May 12 '22 at 18:07
  • 1
    UPD: Still works with Xcode 14.2 and iOS 16.2: `swift build -Xswiftc "-sdk" -Xswiftc "`xcrun --sdk iphonesimulator --show-sdk-path`" -Xswiftc "-target" -Xswiftc "arm64-apple-ios16.2-simulator"` – Legonaftik Mar 27 '23 at 07:41
37

Make it work without limit the platforms:

You should select an iOS-based target to make it available:

Demo

If you leave it selecting macOS (by default), you will get the error.


Limit to a specific platform

if you want your package to be available only for specific platforms (for example only for iOS), you should specify the platform in the package.swift file:

let package = Package(
    name: "MyLibrary",
    platforms: [
        .iOS(.v10)
    ],
    products: [
,,,

Support Multiplatform

If you need your framework to be available on multiple platforms, don't forget to check the availability of the imported framework like:

#if canImport(UIKit)

import UIKit

#endif
Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
  • 6
    Thats the answer! – MGY Aug 27 '21 at 12:34
  • 1
    LMAO I spent like 1h without realizing I was trying to build for macOS... ridiculous – Rob Apr 09 '22 at 20:06
  • 1
    actually, you can't limit for what platform the package is compiled for, but you can say the minimum version. So having `platforms: [.iOS(.v10)]` means all macOS, tvOS etc... and iOS 10 and above – Stoyan Jun 07 '22 at 06:45
  • 1
    “Limit to a specific platform” doesn't seem to work (current latest: Xcode 14.2, Swift 5.7.2). When opening the package in Xcode, it still displays the My Mac and Any Mac devices, and when building from command line with `swift build` it still assume macOS and will fail with errors like “error: no such module 'UIKit'”. – Slipp D. Thompson Dec 29 '22 at 16:39
25

Currently Swift Package Manager has full Xcode support. I was able to get around this error by specifying in my Package.swift manifest that the platform was iOS.

let package = Package(
    name: "MyPackage",
    platforms: [
        .iOS(.v8)
    ],

Then you can open the Package.swift file in Xcode and it will just work.

Joe Susnick
  • 6,544
  • 5
  • 44
  • 50
13

The Swift Package Manager builds executables to run on OS X (or Linux); UIKit is a framework in iOS and won't be accessible.

It may be iOS, tvOS and others become accessible as Swift Package Manager evolves.

On Dec 4, 2015, at 5:39 PM, Daniel Dunbar (@apple.com) wrote:

...

Right, now we only compile for the host platform (OS X or Linux, currently). Among other things, we currently have no knowledge (or options to choose) what SDK or architecture you are targeting. We also have no mechanisms for specifying what platforms targets are compatible with in the manifest.

GoZoner
  • 67,920
  • 20
  • 95
  • 145
  • Can you point to documentation that Swift Package Manager is only meant for MacOS and Linux? – Onato Jan 13 '16 at 23:53
  • Well, even if you could build an iOS executable, how would you ever get it onto and running on an iOS device? `swift build --help` shows no architecture option. Documentation at https://swift.org/package-manager/#conceptual-overview does only mention Darwin and Linux. – GoZoner Jan 13 '16 at 23:56
  • I was expecting it to build a framework like Carthage does. – Onato Jan 13 '16 at 23:59
  • 4
    The Swift Package Manager is not only meant for OS X and Linux; those are just the current platforms it supports. Support for other platforms is planned. – Rick Ballard Feb 19 '16 at 02:48
  • Nice! Thanks for that. – GoZoner Feb 19 '16 at 16:06
  • [Depending on Apple Modules](https://github.com/apple/swift-package-manager/blob/master/Documentation/Reference.md#depending-on-apple-modules): "At this time there is no explicit support for depending on UIKit, AppKit, etc, though importing these modules should work if they are present in the proper system location. We will add explicit support for system dependencies in the future. Note that at this time the Package Manager has no support for iOS, watchOS, or tvOS platforms." – Winter Mar 09 '17 at 01:59
  • 9
    This answer seems thoroughly outdated now, since [SPM supports macOS, iOS, tvOS, watchOS, and Linux, with Windows and Android coming soon](https://github.com/apple/swift-package-manager/blob/master/Sources/PackageDescription/SupportedPlatforms.swift), and [macOS now has UIKit](https://developer.apple.com/mac-catalyst/). – Ky - Jan 15 '20 at 04:05
  • This is what happens over time. No? It clearly has numerous dates. Worth a downvote? Really? – GoZoner Jan 17 '20 at 16:18
6

enter image description here

Make sure you select an iPhone as a simulator target. a Mac target is the default and that won't work...It would be awesome if Xcode could look at the manifest and choose a default simulator based on that...

ScottyBlades
  • 12,189
  • 5
  • 77
  • 85
2

Use conditional compilation blocks:

#if canImport(UIKit)

// Code specific to platforms where UIKit is available

#endif

Source: https://developer.apple.com/documentation/xcode/creating_a_swift_package_with_xcode

Lachtan
  • 4,803
  • 6
  • 28
  • 34
-2

SPM error

no such module 'UIKit'

I run on this problem when used umbrella header(<module_name.h>)[About] which contained

#import <UIKit/UIKit.h>

it means that you can skip specifying import UIKit in every file. But it seems that SPM doesn't support it. Also I am not a supporter of using @_exported attribute

You can use next approach

#if canImport(UIKit)

import UIKit

#endif
yoAlex5
  • 29,217
  • 8
  • 193
  • 205