Blog

Testing Swift on Linux

We’re currently rewriting the Swift Talk backend in Swift. When debugging, we had a strange crash processing an XMLDocument on Linux. Most of Foundation is implemented on Linux, but the implementation isn’t as battle-tested as Foundation on macOS and iOS. Whenever you write code that needs to run on Linux, it’s a good idea to test it.

Rather than spinning up a (virtual) server and SSH'ing into it, we created a quick workflow to test a simple Swift program on Linux.

We start by creating a new executable package using the Swift Package Manager:

mkdir test-linux
cd test-linux
swift package init --type executable
swift package generate-xcodeproj
open test-linux.xcodeproj

As with any other Swift project, we can use Xcode by itself to write, build and run our program. We’ll try to find a small sample app that runs on macOS, but crashes on Linux. First of all, we paste the following into main.swift:

import Foundation

let str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><p></p>"
let data = str.data(using: .utf8)!
func test() throws {
    let doc = try! XMLDocument(data: data, options: []).rootElement()!
    print(doc.name!)
}
try test()

When we run this from within Xcode, it prints “p” as expected. Now, to test it on Linux. To do that, we create a small Dockerfile:

FROM norionomura/swift:41
WORKDIR /app
COPY Package.swift ./
COPY Sources ./Sources
RUN swift build --product test-linux --configuration debug
RUN .build/debug/test-linux
CMD ["echo hello"]

In most Dockerfiles we’d write RUN .build/debug/test-linux as the last step, using CMD instead of RUN — using CMD would run it when the container is running; by writing it as RUN we automatically run it during Docker’s build step.

This makes testing very simple:

docker build .

We can now immediately see that this code crashes with a segmentation fault.

The first time you run the above command, Docker will pull in the necessary dependencies. Once those are cached, subsequent runs will be quite fast, only a matter of seconds.

As we continue our backend rewrite, we’ll be sharing more of what we learn. In Swift Talk 114 of we use Swift’s Mirror and Decodable APIs to generate SQL database queries, and in an the latest episode we build a custom XML decoder, also using Decodable.

To follow our progress, you can subscribe. 👍

Stay up-to-date with our newsletter or follow us on Twitter.

Back to the Blog

recent posts