21

In Xcode, I can select my destination as a "generic iOS device" or any iOS simulator, and my package will build platform-specific code for ios.

Via command line "swift build" only builds my target for macOS.

I want to build the target for iOS for CI purposes. The problem with building for macOS is that UIKit-specific code won't be built.

For example:

#if canImport(UIKit)
    // some invalid code
#endif

The invalid code will not be noticed and will pass the build phase.

Ideally, I could say something like swift build -platform iOS. Is there a way to do something like this?

Michael
  • 1,115
  • 9
  • 24

2 Answers2

29

At time of writing (Feb 16, 2019), a working solution is:

swift build -v \
    -Xswiftc "-sdk" \
    -Xswiftc "`xcrun --sdk iphonesimulator --show-sdk-path`" \
    -Xswiftc "-target" \
    -Xswiftc "x86_64-apple-ios13.0-simulator"

This command uses -Xswiftc to workaround the issue by overriding the sdk from macOS to iphonesimulator.

Strictly we add these flags so developers can work around issues, but they also should report a bug so that we can provide a proper solution for their needs.

Source

So I'm guessing there will be a more elegant solution in the future.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
Michael
  • 1,115
  • 9
  • 24
  • Interesting. Any idea how to make it work for mixed Swift/ObjC packages? The swift side of my library seems to build fine, but ObjC errors on importing UIKit – powerj1984 Apr 21 '20 at 21:16
  • @powerj1984 I am doing a project rn with Swift+C (not ObjC), and might be hitting a similar issue. I think it has to do with the Linker. e.g. you are linking to a macOS binary when you should be specifying a link to an iOS binary. Check out the `swift build -Xlinker -L/` command. I don't know the solution, but it's a starting point – Michael Apr 22 '20 at 15:51
  • 1
    Thanks Michael! If I get a chance I might look into it more. For now I just rewrote my ObjC code in Swift There was a trivial amount of ObjC in my library, so was pretty straight forward for me – powerj1984 Apr 22 '20 at 18:25
25

Starting with Xcode 11, xcodebuild supports SwiftPM packages out of the box.

An example invocation would look like this:

xcodebuild -scheme Foo \
  -destination 'platform=iOS Simulator,OS=13.5,name=iPhone 11 Pro'

where Foo would be the name of the library product you're trying to build. You can get the full list of available schemes for you SwiftPM package with xcodebuild -list. You can get the list of available destinations for a given scheme with this invocation:

xcodebuild -showdestinations -scheme Foo
Max Desiatov
  • 5,087
  • 3
  • 48
  • 56
  • 2
    does this require adding an Xcode project to the package? EDIT: Nevermind, just tested it and it works fine without an Xcode project file! – Xaxxus Oct 29 '20 at 16:22
  • This answer saved me a lot of headaches! Thanks. – NRitH May 06 '21 at 01:47
  • How would you go from a destination (from `-showdestinations`, e.g. `{ platform:iOS Simulator, id:FD90A730-A1D5-4BBC-B61A-0324400EE9EA, OS:15.0, name:iPhone 12 }`) to a value to pass to `-destination`? I've been getting `xcodebuild: error: Unable to find a destination matching the provided destination specifier` – Ben Butterworth Jun 17 '21 at 23:49
  • 1
    I think you pretty much have to remove braces and replace `:` between field names and field values with `=`. Then in your example it becomes `-destination 'platform=iOS Simulator,OS=15.0,name=iPhone 12'` – Max Desiatov Nov 18 '21 at 16:26
  • Just got this to work with the following format | `xcodebuild -scheme ProjectName -destination 'platform=iOS Simulator,id=204FA3AF-347C-494D-B612-A3D8FE2C9660'` – Andrew Zimmer May 02 '22 at 18:03