Álvaro Ramírez
xcodebuild's SPM support (Xcode 11)
Had been a while since I looked into generating Xcode projects from a Swift package. On my latest use of the generate-xcodeproj subcommand, I was greeted by a nice warning surprise…
swift package generate-xcodeproj
warning: Xcode can open and build Swift Packages directly. 'generate-xcodeproj' is no longer needed and will be deprecated soon. generated: ./FooBar.xcodeproj
Xcode can handle Swift packages directly. Similarly, xcodebuild can handle them too. This isn't new. It's likely been available since Xcode 11. I just totally missed it.
Note: I've yet to dig into Xcode 13 beta, as Swift packages may already support the build/test features I was after in xcodebuild (like build/test on Catalyst).
In any case, on to xcodebuild… but let's first create a brand new Swift package.
Creating a Swift package library
mkdir FooBar && cd FooBar swift package init --type library
Creating library package: FooBar Creating Package.swift Creating README.md Creating .gitignore Creating Sources/ Creating Sources/FooBar/FooBar.swift Creating Tests/ Creating Tests/FooBarTests/ Creating Tests/FooBarTests/FooBarTests.swift
List package schemes
We can use xcodebuild to list the available schemes.
xcodebuild -list
Command line invocation: /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -list User defaults from command line: IDEPackageSupportUseBuiltinSCM = YES Resolve Package Graph Resolved source packages: FooBar: /tmp/FooBar Information about workspace "FooBar": Schemes: FooBar
Show supported platform, architecture, etc
Similarly, we can list destinations supported for the schemes.
xcodebuild -showdestinations -scheme FooBar
Command line invocation: /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -showdestinations -scheme FooBar User defaults from command line: IDEPackageSupportUseBuiltinSCM = YES Resolve Package Graph Resolved source packages: FooBar: /tmp/FooBar Available destinations for the "FooBar" scheme: { platform:macOS, arch:x86_64, id:... } { platform:macOS, arch:x86_64, variant:Mac Catalyst, id:... } ... { platform:iOS Simulator, id:..., OS:14.5, name:iPhone 12 Pro } Ineligible destinations for the "FooBar" scheme: ...
macOS builds
Let's build for macOS, though let's first import UIKit into FooBar.swift. This ensures we get an expected failure when building for macOS.
import UIKit struct FooBar { var text = "Hello, World!" }
Now let's attempt to build it…
xcodebuild build -quiet -scheme FooBar -destination 'platform=macOS'
--- xcodebuild: WARNING: Using the first of multiple matching destinations: { platform:macOS, arch:x86_64, id:3D097357-EB7D-565D-9058-CE7C3135927B } { platform:macOS, arch:x86_64, variant:Mac Catalyst, id:3D097357-EB7D-565D-9058-CE7C3135927B } /tmp/FooBar/Sources/FooBar/FooBar.swift:1:8: error: no such module 'UIKit' import UIKit ^ note: Using new build system note: Building targets in parallel note: Planning build note: Analyzing workspace note: Using build description from disk note: Build preparation complete ** BUILD FAILED **
The failure expected as UIKit isn't available on your typical macOS builds.
macOS Catalyst builds
We do, however, have Catalyst available, so we can use its variant to build for macOS with UIKit support, and.. voilà!
xcodebuild build -quiet -scheme FooBar -destination 'platform=macOS,variant=Mac Catalyst' && echo \\o/
\o/