There are a number of people working to bring Swift 3.0 to as many ARM-based systems as possible. This article is specifically about getting Swift 3.0 for your Raspberry Pi 2 or Raspberry Pi 3 that is running Ubuntu 16 (Xenial Xerus). It has not been tested for Raspbian variants (and likely doesn’t work).
A fair warning: support for Swift 3.0 on the Raspberry Pi (and all ARM devices) is still beta. Use it for prototyping and proof-on-concept work rather than building a product with it. Also, if you’re interested in joining the community of folks working on getting Swift 3.0 for ARM devices, come join us on Slack!
Xenial on a Raspberry Pi
You might not have even known Xenial for the Raspberry Pi existed; I didn’t! To grab it head over to the Ubuntu Wiki and get the distribution for your Pi. You will want to use at least an 8G SD card.
Install Swift 3.0
The team working on Swift for ARM is using Jenkins to build the Raspberry Pi binaries natively on a Raspberry Pi 3. As in, this is the build machine!

For the curious check out the Jenkins build project. Quite frankly, I’m amazed that it only took 6 hours to compile Swift.
Now, on your Raspberry Pi, grab and extract the Swift 3.0 build artifact into a directory and set your PATH
with something like:
1 2 3 4 5 |
cd $HOME wget http://swift-arm.ddns.net/job/Swift-3.0-Pi3-ARM-Incremental/16/artifact/swift-3.0-2016-07-19-RPi23-ubuntu16.04.tar.gz mkdir swift-3.0 cd swift-3.0 && tar -xzf ../swift-3.0.tgz export PATH=$HOME/swift-3.0/usr/bin:$PATH |
Note: You aren’t tied to putting Swift 3.0 in $HOME
, I typically use /opt/swift/swift-3.0
.
Now, let’s give it a spin!
Create a file called helloWorld.swift
:
1 |
print("Hello, world!") |
You can use swift helloWorld.swift
to execute the file like a script:
# swift helloWorld.swift Hello, world!
Or, you can compile the file into an executable with swiftc
if you have clang
installed and configured properly:
# swiftc helloWorld.swift # ./helloWorld Hello world!
If swiftc
failed with error: link command failed with exit code 127
there’s a good chance you don’t have clang
installed and configured properly:
sudo apt-get update sudo apt-get install -y libicu-dev sudo apt-get install -y clang-3.6 sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-3.6 100 sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-3.6 100
Let’s look at a few other tidbits:
Importing Glibc
works!
swiftcat.swift
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import Glibc guard CommandLine.arguments.count == 2 else { print("Usage: swiftcat FILENAME") exit(-1) } let filename = CommandLine.arguments[1] let BUFSIZE = 1024 var pp = popen("cat " + filename, "r") var buf = [CChar](repeating:0, count:BUFSIZE) while fgets(&buf, Int32(BUFSIZE), pp) != nil { print(String(cString:buf), terminator:"") } exit(0) |
Compile (swiftc swiftcat.swift
) and run (swiftcat
)!
Bridging to C routines
Linking against compiled object files works!
escapetext.c
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <string.h> #include <stdlib.h> #include <curl/curl.h> int escapeText(const char* text, char** output) { int rc = -1; CURL* curl = curl_easy_init(); if (curl) { char* escaped = curl_easy_escape(curl, text, strlen(text)); if (escaped) { *output = (char*)malloc(strlen(escaped) + 1); strcpy(*output, escaped); curl_free(escaped); rc = strlen(*output); } } return rc; } |
escapetext.h
:
1 |
int escapeText(const char* text, char** output); |
escapeswift.swift
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import Glibc guard CommandLine.arguments.count == 2 else { print("Usage: escapeswift STRING") exit(-1) } let string = CommandLine.arguments[1] var buffer:UnsafeMutablePointer<Int8>? = nil let rc = escapeText(string, &buffer) guard rc > 0 else { print("Error escaping text") exit(-1) } if let escaped = buffer { let escapedString = String(cString:escaped) print("Escaped text: " + escapedString) } exit(0) |
Compile and link everything together:
# clang -c escapetext.c # swiftc -c escapeswift.swift -import-objc-header escapetext.h # swiftc escapeswift.o escapetext.o -o escapeswift -lcurl
And run:
# ./escapeswift "foo > bar" Escaped text: foo%20%3E%20bar
Swift Package Manager
Unless you enjoy writing makefiles and build scripts (and trust me, some do), the Swift Package Manager is here to help manage software package dependencies. We’ll be writing more about the SwiftPM available in Swift 3.0, but are excited to provide a version that works on armv7 devices. Try this out:
# mkdir finalCountdown && cd finalCountdown # swift package init --type executable Creating executable package: finalCountdown Creating Package.swift Creating .gitignore Creating Sources/ Creating Sources/main.swift Creating Tests/
Replace the contents of Sources/main.swift
with
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import Foundation import Glibc let thread = Thread(){ print("Entering thread") for i in (1...10).reversed() { print("\(i)...", terminator:"") fflush(stdout) sleep(1) } print("\nExiting thread") print("Done") exit(0) } thread.start() select(0, nil, nil, nil, nil) |
Now, run swift build
to build your finalCountdown
application:
# swift build Compile Swift Module 'finalCountdown' (1 sources) Linking .build/debug/finalCountdown # .build/debug/finalCountdown Entering thread 10...9...8...7...6...5...4...3...2...1... Exiting thread Done
moreswift
For a random smattering of Swift 3.0 applications that have been run on both x86 and armv7 systems, check out the moreswift swift-3.0 branch.
What Version Is This?
The current builds available are not tracking the Swift 3.0 preview builds. To determine the Git hashes associated with the swift
binary, type swift --version
:
# swift --version Swift version 3.0-dev (LLVM eb140647a6, Clang a9f2183da4, Swift bb43874ba1)
You can then, if you so choose go directly to the Swift repository commit with something like https://github.com/apple/swift/tree/bb43874ba1 to see the history beginning with the last commit incorporated into the build.
Acknowledgements
A lot of people have been apart of the effort to bring Swift to Linux ARM devices. This list is just a few of those individuals. Please do visit their blogs; there is a wealth of information and learnings therein.
- William Dillon (@hpux735) http://www.housedillon.com
- Ryan Lovelett (@rlovelett) http://stackoverflow.com/users/247730/ryan
- Brian Gesiak (@modocache) http://modocache.io
- Karl Wagner http://www.springsup.com/
- @tienex tienex
- PJ Gray (@pj4533) Say Goodnight Software
- Cameron Perry (@mistercameron) http://mistercameron.com
Hi,
I followed your instructions and I get the following error at trying “Hello, world!”
I have tried the
sudo apt-get install libstdc++6
and it said that I had the newest version.Not sure where to go from here. Any help would be appreciated.
Thanks for the article and your work.
Dave
David: were you using Ubuntu Xenial or Raspbian Jessie (
lsb_release -a
will tell you)? The binary is only compatible with Ubuntu Xenial.I’m getting same error on Raspbian.
Out of curiosity: what makes it harder to compile and run Swift on Raspbian in comparison to Ubuntu Xenial?
Howdy Victor – I don’t recall the technical reasons why Raspbian caused issues – if you take a look at our post http://dev.iachieved.it/iachievedit/building-swift-3-0-on-a-raspberry-pi-3/ you can use these instructions to try building on Raspbian. If you get it to succeed I’d be interested in knowing!
Thanks for the link, Joe. I’ll give it a try.
To get it work you need replace “jessie” by “stretch” at /etc/apt/sources.list file.
then “sudo apt-get update”
and the last step is: “sudo apt-get install gcc-5”
Hi Joe,
In my exuberance, I somehow totally missed that minor detail! That’s the problem.
Thanks.
Thank you for porting swift 3.0 to Raspberry Pi. Swift PM works. However, it seems that the “Dispatch” module is missing in the package.
That’s correct; as of June 21, 2016
libdispatch
has not been delivered as a part of the Swift 3.0 release on Linux (it is present on OS X). This is irrespective of architecture. If you take a look at the libdispatch note on Swift.org there is a reference to the porting project on Github. It appears the Linux port of GCD is moving a little slower than the rest of the components.For what it’s worth myself and some other individuals are about to start looking more into this to see how we can help move GCD on Linux along.
There is instruction to build libdispatch on Linux, but the steps are for 15.04 only. I have tried them and did not make successfully on 16.04 Raspberry Pi.
https://github.com/apple/swift-corelibs-libdispatch/blob/master/INSTALL
Indeed, and unfortunately I haven’t been able to build it for 15.04 either! I will be hopping on the mailing lists shortly to ascertain what the status of the project is.
wget Link is 404
Matt, thanks for bringing that to our attention, we’ve been moving stuff around and the link was out of date. Try again!
Great guide, thanks a lot!
In the bridging example, before compiling, don’t forget to
sudo apt-get install libcurl4-gnutls-dev
For the package manager example: NSThread is now just called Thread
You’re welcome Michael! Yes, the Great Renaming effort is in full swing for Swift and a number of APIs are changing. I expect it to continue to churn daily as they rush to meet the goals of releasing Swift 3.0 later this year.
I’m currently getting “use of unresolved identifier ‘Process'” trying to get process arguments, anyone has any idea?
Yes! Swift 3 has changed this to
CommandLine
. I need to update the tutorials to reflect this!Does somebody use OperationQueue?
When i add Operation object declaration to code i get linker error
How to fix it?
to build libdispath try
it will install swiftCore missing libs
Is it possible download swift3 stable release for raspberry pi 2?
Yes, it is! Just use the
lastSuccessfulBuild
of the Pi3 build, like this http://swift-arm.ddns.net/job/Swift-3.0-Pi3-ARM-Incremental/lastSuccessfulBuild/artifact/swift-3.0-2016-10-04-RPi23-ubuntu16.04.tar.gzTried to build swift on my own, failed after several hours. Followed your instructions, had swift running in minutes. Thanks very much!
You’re very welcome!!
It’s also possible to run swift-3 on raspian ….
-) install gcc-6
-) install cmake 3.6.2
-) check for https://github.com/apple/swift/pull/5296/commits/09cbffb3e4ed5c4ef8069d273e2d34309abcd2e4
lldb and the Swift REPL seem to fail with Illegal Instruction with the current build/current Xenial
swift package init –type executable
/usr/bin/swift-package: error while loading shared libraries: libicuuc.so.55: cannot open shared object file: No such file or directory
Where to get libicuuc.so.55 file?
/usr/bin/swift-package: error while loading shared libraries: libicuuc.so.55: cannot open shared object file: No such file or directory
Where to get libicuuc.so.55 file?
Found it! Just download and install it!
https://packages.debian.org/sid/armhf/libicu55/download
The DNS address for the download is missing. When I run wget I get this result:
wget: unable to resolve host address ‘swift-arm.ddns.net’
wget http://swift-arm.ddns.net/job/Swift-3.0-Pi3-ARM-Incremental/lastSuccessfulBuild/artifact/swift-3.0-2016-10-21-RPi23-ubuntu16.04.tar.gz
Above link is not working. Getting the below error :-
Resolving swift-arm.ddns.net (swift-arm.ddns.net)… failed: Name or service not known.
wget: unable to resolve host address ‘swift-arm.ddns.net’
Thanks Yogesh. Unfortunately from time-to-time I forget to renew the domain. It should be up now.
Joe looks like it is offline now (((
yes its offline now.
Just hope there is some other mirror or repo somewhere.
Thanks
Should be online now.
It works again! GREAT!
Just in case anybody stumbles upon this and has issues. I was able to successfully install swift 3.1 on my Raspberry Pi 3 through this guide as well. https://www.uraimo.com/2017/05/01/An-update-on-Swift-3-1-1-for-raspberry-pi-zero-1-2-3/
Installation have been flawless.
Add to path variable.
But i am getting cannot execute binary file: Exec format error
I have downloaded and extracted http://swift-arm.ddns.net/job/Swift-3.0-Pi3-ARM-Incremental/lastSuccessfulBuild/artifact/swift-3.0-2016-12-21-RPi23-ubuntu16.04.tar.gz
Is there any thing that can be done to take care of this issue.
The command wget http://swift-arm.ddns.net/job/Swift-3.0-Pi3-ARM-Incremental/16/artifact/swift-3.0-2016-07-19-RPi23-ubuntu16.04.tar.gz gives a failed message “No route to host”.
I check my iptables rules for inbound port 80 and the network settings and everything seems fine.
Can I download it from somewhere else?
its offline again((
Is this still a viable option? The download link is dead.