This tutorial will walk you through the process of compiling your own native programs for Windows using the Ubuntu on Windows. While the development environment and Swift compiler used here will be the standard toolchain for Linux, you'll also be able to cross-compile programs that run natively on Windows like any other executable.
This tutorial assumes a computer running an up-to-date 64-bit version of Windows 10 (at the time of writing, the Fall Creators' Update was the most recent build).
You'll also need Visual Studio 2017; the Community Edition is sufficient, since we'll only be using the SDKs that come with it and some command line tools.
In the Visual Studio Installer (which should itself be installed on your computer alongside Visual Studio), make sure that you select the tools for C++ development. In particular, this tutorial is tested against the 10.0.10586 Windows 10 SDK, although it may also work with more recent versions. Installing the SDKs can be done by modifying an existing Visual Studio install.
Microsoft provides instructions for installing the Linux subystem for Windows. This tutorial assumes that you're using Ubuntu, although other Linux variants may work; furthermore, it assumes that you are using Ubuntu 16.04 LTS, which, at the time of writing, is the version provided through the Microsoft Store.
If you're using a version of Ubuntu earlier than 16.04, you may need to update or amend these instructions as appropriate.
Once Ubuntu is installed and you have Bash
open, you can start installing the dependencies. We'll be using all of the same ones needed to build Swift normally along with a few extras.
Note that every command below that starts with sudo
will give root access to what comes after it. You'll need it for these commands, but if you're ever unsure, try the command without sudo
first and don't run as root if you don't trust the command.
Firstly, let's make sure that apt
is up to date. You'll need the password that you created when you installed Ubuntu.
sudo apt-get update
Then, let's install the Swift dependencies. At the time of writing, these are:
sudo apt-get install git cmake ninja-build clang python uuid-dev libicu-dev icu-devtools libbsd-dev libedit-dev libxml2-dev libsqlite3-dev swig libpython-dev libncurses5-dev pkg-config libblocksruntime-dev libcurl4-openssl-dev autoconf libtool systemtap-sdt-dev tzdata
However, always use the Swift README as the authoritative source.
We're going to have to install a few more dependencies such as a recent version of Clang; I used version 5.0.1. To do this, we'll need to add the LLVM apt repositories as sources.
To do this, you'll need to first edit the /etc/apt/sources.list
file with a text editor. I happen to use vim (sudo apt-get install vim
) for these purposes; as one alternative, nano is easier to use but had display issues at the time of writing. I'll be assuming you're using vim for the remainder of this section.
Open the file as root:
sudo vim /etc/apt/sources.list
and hit I
on the keyboard to enter insert mode. At the bottom of the file, paste in the deb
and deb-src
lines for your version of Ubuntu, which you can find at http://apt.llvm.org. For instance, to use Clang 5.0, add the following lines to the bottom of your file:
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-5.0 main
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-5.0 main
Exit out of insert mode by pressing the esc
key, and then save out the file and exit by typing :wq
.
Back in the terminal, you now need to add the keys for the LLVM repository. Scroll down to the Install
section of the LLVM apt page matching the version of Clang you chose and copy and paste the line starting with wget
into your terminal.
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
You can now run sudo apt-get update
again. Finally, we're ready to install recent versions of Clang and LLD.
sudo apt-get install clang-5.0 lld-5.0
To make it so that when you use clang
on the terminal it always uses this new version, we need to update the symlinks. First, remove the existing symlinks:
sudo rm /usr/bin/clang
sudo rm /usr/bin/clang++
sudo rm /usr/bin/clang-cl
And then create new links to point to the new versions of Clang and LLD.
sudo ln -s /usr/bin/clang-5.0 /usr/bin/clang
sudo ln -s /usr/bin/clang-5.0 /usr/bin/clang++
sudo ln -s /usr/bin/clang-5.0 /usr/bin/clang-cl
sudo ln -s /usr/bin/lld-5.0 /usr/bin/lld
sudo ln -s /usr/bin/lld-5.0 /usr/bin/lld-link
While we'll be working in Bash for most of this, I recommend cloning the Swift sources onto the Windows file system so you can easily access it. For instance, I cloned the sources to my C drive:
cd /mnt/c
Note that all your Windows files can be found under /mnt/{drive letter}
.
From there, follow the instructions in the Swift README under the section "Getting Sources for Swift and Related Projects". If you started in the root of the C drive, if you run ls /mnt/c/swift-source
you should see swift
, llvm
, clang
, and other assorted projects there.
We're going to leave Bash for a little while and set up some other dependencies. Firstly, Swift relies on ICU; I used version 59. We're going to need a Windows build; you can download one from http://site.icu-project.org/download/59; scroll down and select the "Windows (x86 64-bit) Visual Studio 2015" binaries. Once you've downloaded and extracted the zip, move the directory into your swift-source
directory. I renamed it to windows-icu
, which is how I'll refer to it from now on.
If you run ls /mnt/c/swift-source
from Bash again you should see windows-icu
in the list; if you ls /mnt/c/swift-source/windows-icu
you should see include
, bin64
, and lib64
subdirectories.
(tip: the Tab key should auto-complete the current directory or file name you're typing in Bash)
You'll also need to copy the visualc.modulemap
and ucrt.modulemap
files from swift/stdlib/public/Platform
(where swift
is the path you cloned the Swift repository into) into the include directories of their respective SDKs and then rename them to module.modulemap
.
For instance, depending on your versions, visualc.modulemap
might become:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.11.25503\include\module.modulemap
and ucrt.modulemap
might become:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.10586.0\ucrt\module.modulemap