How to use a pre-release Swift version with command-line tools
Table of Contents
In the previous article, How to use a pre-release Swift version in Xcode, we learn how to use different Swift toolchain in Xcode. In the end, we learn that changing the Swift version in Xcode doesn't affect any command-line tools.
Selecting a Swift toolchain in Xcode will affect the Xcode IDE only. It won't affect any command-line tools.
In this article, we will learn how to change the Swift toolchain for command-line tools.
Why
The new release of Xcode always ships with the latest stable version of Swift, e.g., Xcode 12.5 shipped with Swift 5.4, but since Swift is open-sourced, it doesn't need to wait for Xcode to release a new version.
If you want to prepare your app for new Swift's features, you can test it with your current Xcode version with the method in How to use a pre-release Swift version in Xcode. But if you also want to make it work with CI, you want to make your tools, e.g., Fastlane and xcodebuild know about the new toolchain too. And that's what you are going to learn in this article.
You can easily support sarunw.com by checking out this sponsor.
Translate your app In 1 click: Simplifies app localization and helps you reach more users.
Checking current Swift version
Most Xcode command-line tools use Swift toolchains based on the current active Xcode.
You can check the currently selected toolchain like this.
xcrun swift -version
You would get the version that ships with your current active Xcode. In my case, it is Swift 5.4 from Xcode 12.5.
Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)
Target: arm64-apple-darwin20.5.0
Example
For demonstration, I have created a new project with new Swift 5.5 features.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let first: CGFloat = 42
let second: Double = 19
let result = first + second // 1
print(result)
}
func usingNewSwiftFeatures() async -> Date { // 2
return Date();
}
}
<1> [SE-0307] Allow interchangeable use of CGFloat
and Double types
.
<2> [SE-0296] Async/await.
Trying to build the above code with the Swift 5.4 toolchain will get you compiling errors.
Run xcodebuild
, which uses the default toolchain from the current active developer directory (Swift 5.4 for Xcode 12.5), will produce the same errors.
error: consecutive declarations on a line must be separated by ';'
func usingNewSwiftFeatures() async -> Date {
^
;
/Users/sarunw/Documents/sarunw-example/example-swift5.5/example-swift5.5/ViewController.swift:21:34: error: 'async' modifier is only valid when experimental concurrency is enabled
func usingNewSwiftFeatures() async -> Date {
^
/Users/sarunw/Documents/sarunw-example/example-swift5.5/example-swift5.5/ViewController.swift:21:40: error: expected declaration
func usingNewSwiftFeatures() async -> Date {
^
/Users/sarunw/Documents/sarunw-example/example-swift5.5/example-swift5.5/ViewController.swift:10:7: note: in declaration of 'ViewController'
class ViewController: UIViewController {
^
/Users/sarunw/Documents/sarunw-example/example-swift5.5/example-swift5.5/ViewController.swift:21:10: error: expected '{' in body of function declaration
func usingNewSwiftFeatures() async -> Date {
^
/Users/sarunw/Documents/sarunw-example/example-swift5.5/example-swift5.5/ViewController.swift:17:28: error: binary operator '+' cannot be applied to operands of type 'CGFloat' and 'Double'
let result = first + second
~~~~~ ^ ~~~~~~
/Users/sarunw/Documents/sarunw-example/example-swift5.5/example-swift5.5/ViewController.swift:17:28: note: overloads for '+' exist with these partially matching parameter lists: (CGFloat, CGFloat), (Date, TimeInterval), (DispatchTime, Double), (DispatchWallTime, Double), (Double, Double)
let result = first + second
^
** BUILD FAILED **
Solutions
There are two ways to change the Swift toolchain for command-line tools.
Toolchain parameter
Every Xcode-related command-line tools come with a toolchain
parameter.
xcrun -toolchain NAME|IDENTIFIER
xcodebuild -toolchain NAME|IDENTIFIER
Fastlane which uses xcrun
and xcodebuild
under the hood also has a toolchain
parameter.
fastlane gym --toolchain NAME|IDENTIFIER
TOOLCHAINS environment
If you plan to run multiple commands with the same Swift toolchain, you can set the toolchain
argument via environment variable instead. You can do this with the export
command. This will only affect the current terminal session.
export TOOLCHAINS=NAME|IDENTIFIER
After export, you can run a command without -toolchain
.
xcodebuild -toolchain swift
fastlane gym --toolchain swift
// or
export TOOLCHAINS=swift
xcodebuild
fastlane gym
These two methods are actually the same thing but a different way to inject the toolchain
argument.
--toolchain
: Specifies which toolchain to use to perform the lookup. If no--toolchain
argument is provided, then the toolchain to use will be taken from theTOOLCHAINS
environment variable, if present.
Where can I find toolchain name and identifier
In the solutions above, you need to specified NAME
or IDENTIFIER
of the toolchain. You can find this by opening up the Info.plist
file of toolchains you want to reference.
In my case, the toolchain is located at /Library/Developer/Toolchains
.
-
Open up
/Library/Developer/Toolchains
, and you will see your toolchain sitting there. Mine isswift-5.5-DEVELOPMENT-SNAPSHOT-2021-06-02-a.xctoolchain
. -
Right-click and select "Show Package Contents".
-
You will see the
Info.plist
file. Open it up.
-
You can find
name
under theAliases
key andidentifier
under theBundle identifier
key.
In this case, you can use both swift
and org.swift.55202106021a
as a toolchain name.
xcodebuild -toolchain swift
xcodebuild -toolchain org.swift.55202106021a
Working with CI
Self-hosted CI
If you have control over the CI server, you need to install the Swift toolchain you want and set the environment variable pointing to that toolchain with the export
command.
export TOOLCHAINS=NAME|IDENTIFIER
// All commands will use the toolchain specified.
fastlane gym
...
CI with pre-installed Swift toolchain
If your CI server with the pre-installed Swift toolchain, just add the export
command, and you are good to go.
Cloud-based CI
If you use cloud-based CI services with no control over the infrastructure, you have to download the Swift toolchain programmatically before the building starts.
Your script might look something like this.
curl -O https://swift.org/builds/swift-5.5-branch/xcode/swift-5.5-DEVELOPMENT-SNAPSHOT-2021-06-02-a/swift-5.5-DEVELOPMENT-SNAPSHOT-2021-06-02-a-osx.pkg
sudo installer -pkg swift-5.5-DEVELOPMENT-SNAPSHOT-2021-06-02-a-osx.pkg -target /
export TOOLCHAINS=swift
You can easily support sarunw.com by checking out this sponsor.
Translate your app In 1 click: Simplifies app localization and helps you reach more users.
Caveat
To submit to the App Store, you must build your app using the version of Swift included within Xcode. So, what we learned today is for testing and prepare your app for the new features only.
Read more article about Xcode or see all available topic
Enjoy the read?
If you enjoy this article, you can subscribe to the weekly newsletter.
Every Friday, you'll get a quick recap of all articles and tips posted on this site. No strings attached. Unsubscribe anytime.
Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading and see you next time.
If you enjoy my writing, please check out my Patreon https://www.patreon.com/sarunw and become my supporter. Sharing the article is also greatly appreciated.
Become a patron Buy me a coffee Tweet ShareA new way to style UIButton with UIButton.Configuration in iOS 15
The first part in the series "What's new in UIKit button". An introduction to a new button configuration, a struct that is shaping and styling your button. You no longer need to subclass UIButton ever again with button configuration.
Preview a device in landscape orientation with previewInterfaceOrientation
New in iOS 15, SwiftUI has finally support preview in landscape orientation. Let's find out how to do it.