UPDATE: Swift 5.2.1 was released. This post has been updated to reflect these changes.

Swift 5.2 was released Tuesday, March 24, 2020. The release is focused on improving the developer experience. For details on what that means please see the previously linked blog post.

Here I want to focus on what it will take to get the tagged release of Swift 5.2.1 compiling on Ubuntu 20.04.

NOTE: I understand that Ubuntu 20.04 is not yet released. As the next long-term support (LTS) release of Ubuntu it is goint to be around for awhile and it is a good idea to start getting software ported to it during the distribution’s development cycle.

The challenge

Generally speaking compiling Swift for Ubuntu 20.04 is rather straight forward and is well supported. The challenge is Python support. Or more specifically, the lack of Python 2 support. According to PEP-0373 Python 2 support officially stopped on January 1, 2020.

Of more specific note is that Ubuntu 20.04 is removing Python 2 from the distribution. This is problematic because Swift’s official system requirements make it pretty clear Python 2 is required.

Please make sure you use Python 2.x. Python 3.x is not supported currently.

Hopefully there will be progress made towards making the build tooling work with Python 3 without patching. There are pull requests out there to cover exactly that (apple/swift#26296, apple/swift#30662, apple/swift-integration-tests#61).

Prerequisites

Before actually starting to get source code or patching anything the first thing that should be done is install these dependencies.

sudo apt-get install     \
    clang                \
    cmake                \
    curl                 \
    git                  \
    icu-devtools         \
    libcurl4-openssl-dev \
    libedit-dev          \
    libicu-dev           \
    libncurses5-dev      \
    libpython3-dev       \
    libsqlite3-dev       \
    libxml2-dev          \
    ninja-build          \
    pkg-config           \
    python3              \
    python3-distutils    \
    rsync                \
    swig                 \
    systemtap-sdt-dev    \
    tzdata               \
    uuid-dev

Python

The Swift build tools expect that /usr/bin/env python resolves to a Python 2 interpreter. The patches that follow are designed to make the build tools work with Python 3. One problem with that is that in a vanilla install of Ubuntu 20.04 /usr/bin/env python does not resolve anything. PEP-394 basically says that runtime distributors are not required to provide /usr/bin/env python and it seems that Ubuntu 20.04 has elected to not to provide /usr/bin/env python.

To work around that use update-alternatives to provide python.

sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 0

Getting Source Files and Patches

Now that the system has all the required dependencies and configuration, it is time to get the appropriate source files and patches.

Ultimately where you put the files is irrelevant. In this article $SWIFT_SOURCE_ROOT will be the variable that refers to the directory that contains all source files and patches.

NOTE: for me I’ve defined SWIFT_SOURCE_ROOT as SWIFT_SOURCE_ROOT=$(mktemp -d).

Gather Patches

The first thing to get are all of the necessary patches.

cd $SWIFT_SOURCE_ROOT
curl -LO https://ryan.lovelett.me/assets/0001-Updated-to-work-with-Python-3-swift-5.2.patch
curl -LO https://ryan.lovelett.me/assets/0002-Change-CMake-Python-detection-swift-5.2.patch
curl -LO https://ryan.lovelett.me/assets/0003-Potpourri-fixes-to-make-compilation-work.patch
## https://github.com/apple/swift-integration-tests/pull/61
curl -LO https://github.com/apple/swift-integration-tests/pull/61.patch
curl -LO https://ryan.lovelett.me/assets/0001-Update-SourceKit-LSP-to-use-Python-3.patch

Gather Sources

cd $SWIFT_SOURCE_ROOT
git clone https://github.com/apple/swift.git

## Get all the rest of the required Source files
$SWIFT_SOURCE_ROOT/swift/utils/update-checkout --clone --tag swift-5.2.1-RELEASE

Apply patches to swift

cd swift
git apply --check $SWIFT_SOURCE_ROOT/0001-Updated-to-work-with-Python-3-swift-5.2.patch
git apply $SWIFT_SOURCE_ROOT/0001-Updated-to-work-with-Python-3-swift-5.2.patch
git apply --check $SWIFT_SOURCE_ROOT/0002-Change-CMake-Python-detection-swift-5.2.patch
git apply $SWIFT_SOURCE_ROOT/0002-Change-CMake-Python-detection-swift-5.2.patch
git apply --check $SWIFT_SOURCE_ROOT/0003-Potpourri-fixes-to-make-compilation-work.patch
git apply $SWIFT_SOURCE_ROOT/0003-Potpourri-fixes-to-make-compilation-work.patch
cd $SWIFT_SOURCE_ROOT

Apply patches to swift-integration-tests

cd swift-integration-tests
git apply --check $SWIFT_SOURCE_ROOT/61.patch
git apply $SWIFT_SOURCE_ROOT/61.patch
git apply --check $SWIFT_SOURCE_ROOT/0001-Update-SourceKit-LSP-to-use-Python-3.patch
git apply $SWIFT_SOURCE_ROOT/0001-Update-SourceKit-LSP-to-use-Python-3.patch
cd $SWIFT_SOURCE_ROOT

Build

$SWIFT_SOURCE_ROOT/swift/utils/build-script \
    --preset=buildbot_linux,no_test \
    install_destdir="$SWIFT_SOURCE_ROOT/swift-5.2.1-RELEASE" \
    installable_package="$SWIFT_SOURCE_ROOT/swift-5.2.1-RELEASE-ubuntu-20.04.tar.gz"

Now wait awhile.

Conclusion

When all of this is finished there should be a Gzipped tar archive at $SWIFT_SOURCE_ROOT/swift-5.2.1-RELEASE-ubuntu-20.04.tar.gz. This archive should contain a toolchain suitable for working with Swift.

mkdir -p $HOME/swift/swift-5.2.1-RELEASE
tar xvf $SWIFT_SOURCE_ROOT/swift-5.2.1-RELEASE-ubuntu-20.04.tar.gz \
    --directory $HOME/swift/swift-5.2.1-RELEASE
ln -s $HOME/swift/swift-5.2.1-RELEASE $HOME/swift/active
export PATH="$HOME/swift/active/usr/bin:$PATH"
$ swift --version
Swift version 5.2.1 (swift-5.2.1-RELEASE)
Target: x86_64-unknown-linux-gnu