Swift on Ubuntu Server 18.04 & 20.04 LTS

I setup a Ubuntu Server 18.04 LTS VM earlier and this is why. I have some Swift code I want to try running on an Amazon Web Server and needed a playground to get it running.

The Swift Download page has a set of instructions on installing Swift on a Ubuntu install so we’ll run through these.

Updated 27th April 2020: A few days after writing this post Ubuntu released 20.04 LTS. I’ve gone through these instructions in a Ubuntu Server 20.04 LTS VM, and other than a couple of extra dependancies (see below) the install process is the same.

Setup

There a couple of things to complete the first time you install Swift on Ubuntu that you don’t need to do each time you update.

Swift has a couple of dependancies which need installing. Depending on your Ubuntu install you may already have these installed but apt-get won’t install anything unless it’s missing so it’s safe to run this even if these packages are already there.

$ sudo apt-get install clang libicu-dev libpython2.7-dev

If you’re installing Swift on Ubuntu Server 20.04 LTS there are a couple of extra dependancies required.

$ sudo apt-get install libtinfo5 libncurses5

This next step is optional. To ensure that we’re installing what was originally published by Swift.org we need the Swift.org PGP signing keys. This allows us to check the signature of the archive we download against the one Swift.org publishes for the release archive to make sure no-one has tampered with the Swift archive. It’s unlikley if you’re installing from the Swift.org downloads page, but worth running the step as a precaution.

To do this check we need to download and import the Swift PGP signing keys.

$ wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import -

Installing Swift

There are a couple of files to download, the Swift release archive (5.2.2 in this case) and the PGP Signature file for checking the archive file.

$ wget https://swift.org/builds/swift-5.2.2-release/ubuntu1804/swift-5.2.2-RELEASE/swift-5.2.2-RELEASE-ubuntu18.04.tar.gz
$ wget https://swift.org/builds/swift-5.2.2-release/ubuntu1804/swift-5.2.2-RELEASE/swift-5.2.2-RELEASE-ubuntu18.04.tar.gz.sig

If you want to verify the archive you’ve just downloaded first refresh the Swift PGP keys.

$ gpg --keyserver hkp://pool.sks-keyservers.net --refresh-keys Swift

Then use the signature file to verify the archive.

$ gpg --verify swift-5.2.2-RELEASE-ubuntu18.04.tar.gz.sig

If the archive was verified OK then output should contain a “Good Signature” line. If it doesn’t there was an issue with the archive you downloaded. Try downloading it again from another source.

gpg: Good signature from "Swift 5.x Release Signing Key <swift-infrastructure@swift.org>" [unknown]

Having verified the archive we can go ahead and extract it.

$ tar -xzvf swift-5.2.2-RELEASE-ubuntu18.04.tar.gz

I keep these releases in the /opt directory in Ubuntu so once this has finished I move the extracted directory there.

$ sudo mv swift-5.2.2-RELEASE-ubuntu18.04 /opt

And to make it easier to upgrade to later versions I link /opt/swift to the new Swift release. By recreating this link I can quickly switch between versions.

sudo rm /opt/swift
sudo ln -s /opt/swift-5.2.2-RELEASE-ubuntu10.04 /opt/swift

At this point we should be able to run the Swift interactive shell and get a prompt.

$ /opt/swift/usr/bin/swift
Welcome to Swift version 5.2.2 (swift-5.2.2-RELEASE).
Type :help for assistance.
  1> print("Hello World")
Hello World
  2> :quit 

One last step is to add the /opt/swift/usr/bin directory to your path. You’ll probably want to add this line to the bottom of your users .bashrc file, or equivalent depending on your shell, to save you having to run this each time you login.

$ export PATH=/opt/swift/usr/bin:${PATH}

Hello World!

Before we finish, having downloaded and installed Swift, let’s use it to compile something. To do this we will need to create a couple directories and files.

$ mkdir -p HelloWorld/Sources/HelloWorld
$ cd HelloWorld
$ echo "print(\"Hello World\")" > Sources/HelloWorld/main.swift

Next we need to create a Package.swift file to tell the compiler what to build. Put the following in the Package.swift in the HelloWorld directory using an editor of your chooising.

// swift-tools-version:5.2

import PackageDescription

let package = Package(
        name: "HelloWorld",
        products: [
                .executable(name: "HelloWorld", targets: ["HelloWorld"])
        ],
        targets: [
                .target(name: "HelloWorld")
        ]
)

You can then build the test app.

$ swift build
[4/4] Linking HelloWorld

If everything has worked out correctly you should now have a HelloWorld executable in the .build/debug directory we can run.

$ .build/debug/HelloWorld
Hello World