Thursday, April 30, 2020

Compile Swift for Linux with its Toolchain and Package Manager

If you are unable to install Swift with pre-built binaries, you can compile it instead.  Compiling is a lot more complex and confusing than simply installing prebuilt binaries and I found that a lot of instructions do not build the Swift package manager which I consider to be a necessity when build anything more complex than a simple hello world application.  In this post we look at how we can build Swift with its full toolchain and package manager.

Install Dependencies

The first thing we need to do is to make sure we have all of the dependencies required installed.  The following command includes all dependencies I have needed to install on different flavors of Linux.  You will find that your distribution probably already has a lot of these preinstalled but to make sure you have everything, run this command.

sudo apt-get install git cmake ninja-build clang python uuid-dev libicu-dev icu-devtools libedit-dev libxml2-dev libsqlite3-dev swig libpython-dev libncurses5-dev pkg-config libcurl4-openssl-dev systemtap-sdt-dev tzdata rsync python-pip

If you want to build the documentation, you will need to install Sphinx as well.  This can be done with the following command:

 pip install Sphinx

Now that we have all of the dependencies installed, we need to get the swift source code.

Swift Source

To download the Swift source code, we will want to create a directory to download it too, change to that directory and then run the git command to get the source.  The following commands will download the swift source to a directory name swift-source.

mkdir swift-source
cd swift-source
./swift/utils/update-checkout --clone

Now that we have the source and cloned everything we need, lets build swift.

Build Swift 

Before you begin building Swift, know that it is going to take hours to build.  The exact time will depend on the type of system you are building it on.  The following command will build Swift, its toolchain and the package manager:

./swift/utils/build-script --preset=buildbot_swiftpm_linux_platform,tools=RA,stdlib=RA

Once this has built everything, which could take several hours, we will want to install it similar to what we did with the pre-built binaries in this post:  

Installing Swift

Now that we have built Swift from source, we are ready to install it and put it in our path so we can execute them easily.  I like to install the under the /opt directory, others prefer installing it under the /usr/local/sharedirectory.  What directory you put it under is totally up to you.  I will walk you through installing it under the /optdirectory, if you would like to put it someplace else simply replace the “/opt” in the paths with your install directory.  

Now let’s change to the /opt directory and create a directory named swift.  Once the swift directory is created, we will also need to change the permissions for the directory so we can read, write and execute files.  The following commands will do this:

cd /opt
sudo mkdir swift
sudo chmod 777 swift

The command chmod 777 swift will add read, write and execute permissions for all users of this computer.  I like to use this mode because then any user on the system can use it, however this can be considered a security issue because it also means anyone can modify the files.  Use this at your own risk and for production systems I would really look at who needs permissions for this directly and lock it down more.

Now we will need to move the Swift binaries that we downloaded to the swift directory.  To do this we will change to the swift directory, create a new directory for our build, change to the directory and copy the files over.  For this article I am building the 5.3-dev version of swift therefore I am using that for my directory name.  The following commands will do this:

cd swift
mkdir swift-5.3-dev
cd swift-5.3-dev
cp -R ~/swift-source/build/buildbot_incremental/toolchain-linux-x86_64/* ./

Now we will want to make a symlink to this directory called swift-current.  The reason for this is we will want to add an entry to our PATH environmental variable so the operating system can find the Swift executables without us needing to enter the full path.  If we set up this entry using the swift-current path rather than the swift.5.3-dev path.  This will allow us, when we install new versions of Swift, to simply change where the swift-current symlink points to and have everything work.   We will do this with the following command:

sudo ln -s /opt/swift/ swift-5.3-dev swift-current

Now we will need to create the entry in our PATH variable.  To do this you will want add the add /opt/swift/swift-current/usr/bin/ directory to the PATH variable in our .profile file located in your home directory.  Then update the environment The following commands will do this:

cd ~
echo 'export PATH=$PATH:/opt/swift/swift-current/usr/bin'  >> .profile
source ~/.profile

The last thing we need to do is to verify swift has been successfully installed. To do this, we can run the following command:

swift –version

The output should look something like this but with the version of swift that you installed

Swift version 5.2.2 (swift-5.2.2-RELEASE)
Target: x86_64-unknown-linux-gnu

Congratulations, you have now successfully installed Swift.


Installing Swift for Linux with Pre-built Binaries

The easiest and quickest way to install Swift for Linux is by installing pre-built binaries.  If you are using a LTS branch for Ubuntu, you can find links to download these binaries by going to the following page: https://swift.org/download/.  In this post we will look at how we can install Swift using these binaries however before we do that lets look at the possibility of installing Swift with pre-built packages on non-Ubuntu systems.

Install using a Linux package manger

If you are not using Ubuntu, you may still be able to install pre-built binaries through the package manager that comes with your system.  As an example, with CentOS you can very easily install swift with the following command:

sudo yum install swift-lang swift-lang-runtime.


Installing with the binaries from these package managers will be the easiest way to install Swift however what version is installed and if they stay up to date is dependent on the person that build these binaries.  To find out if your flavor of Linux has a Swift package, you will first have to determine which package manager is used by your system.  You will probably have either apt or yum as your package manager.  The easy way to determine which package manager you have installed is to run both the apt and the yum command.  After you run the command, you will see either the help message for the command if it is installed or a command not found error if the command is not installed.

Once you determine which package manager is installed, you can run one of the following commands to see if there are Swift packages for you flavor of Linux:

apt search swift-lang
yum search swift-lang

If no results are found, you could try searching for swift rather than swift-lang however you will find numerous results that are not the Swift language.  If you do have results from your search, you can install the package by using one of the following commands (Note: replace {package name} with the name of the package returned from the search):

sudo apt install {package name}
sudo yum install {package name}

To verify that Swift is properly installed once the packages are installed, look at the verifying installations section at the end of this chapter.

If swift is properly installed, then you should see the version number of the installed version of Swift.  I wish I could make these instructions were more specific however there is no way we could cover all flavors of Linux here and even if we were able to, there would be no guarantee that packages would not change tomorrow.  

Now let’s look at how we can download and install the Ubuntu binaries from the swift.org site.  

Installing using the swift.org binaries


If you ae using an LTS version of Ubuntu, the easiest way to install Swift is to install the pre-built binary, for your version of Ubuntu, from the swift.org site.  These are official release binaries built by the Swift community itself.  They release pre-binaries for Ubuntu with all official releases of Swift and also for the latest development branch if you want to try the latest and greatest. 

To install Swift with these binaries, the first thing we need to do is to download them from the swift.org site.  In your favorite browser go to the following URL,  https://swift.org/download/ and you should see a screen similar to this:


As you can see from this screenshot, that the latest official released version of Swift, at the time this book was written, is 5.2.2.  To download the pre-built binaries for Swift, you simply need to click on the version of Ubuntu that you are using and it will start the download. In this case I would download a file named swift-5.2.2-RELEASE-ubuntu18.04.tar.gz.  

The name starts off with the word swift because it contains the pre-built binaries for the Swift language, followed by the version number.  Next we see the word RELEASE because this is an official release version of Swift.  If it wasn’t an official release version, we would see the word DEVELOPMENT instead.  The end of the name tells us what platform the pre-built binaries are built for.  In this case they are built for Ubuntu 18.04.

Now we will need to unzip and untar the file.  To do this we need to run the following command:

tar -xzf swift-5.2.2-RELEASE-ubuntu18.04.tar.gz

You will want to substitute the file name in the previous command with the name of the file that you downloaded.  Once this command has finished, you should have a directory with the same name as the original file except it will not have the .tar.gz suffix. 

Before we install these binaries and set up our path, we will want to install the dependencies.  The following command will install the required dependencies:

sudo apt-get install clang libicu-dev

The required dependencies may change with future releases of Swift.  The same page that you downloaded Swift from also contains the list of dependencies.  You can verify that no additional dependencies are needed by referring to that page.

Now that the dependencies are installed, we are ready to install the Swift binaries and put them in our path so we can execute them easily.  I like to install the under the /opt directory, others prefer installing it under the /usr/local/share directory.  What directory you put it under is totally up to you.  I will walk you through installing it under the /opt directory, if you would like to put it someplace else simply replace the “/opt” in the paths with your install directory.  

Now let’s change to the /opt directory and create a directory named swift.  Once the swift directory is created, we will also need to change the permissions for the directory so we can read, write and execute files.  The following commands will do this:

cd /opt
sudo mkdir swift
sudo chmod 777 swift

The command chmod 777 swift will add read, write and execute permissions for all users of this computer.  I like to use this mode because then any user on the system can use it, however this can be considered a security issue because it also means anyone can modify the files.  Use this at your own risk and for production systems I would really look at who needs permissions for this directly and lock it down more.

Now we will need to move the Swift binaries that we downloaded to the swift directory.  To do this we will change to the swift directory and then move the untarred binaries, that should be located in the Downloadsdirectory, to the swift directory.  The following commands will do this:

cd swift
mv ~/Downloads/swift-5.2.2-RELEASE-ubuntu18.04 ./

Now we will want to make a symlink to this directory called swift-current.  The reason for this is we will want to add an entry to our PATH environmental variable so the operating system can find the Swift executables without us needing to enter the full path.  If we set up this entry using the swift-current path rather than the swift.5.2.2-RELEASE-ubuntu18.04 path.  This will allow us, when we install new versions of Swift, to simply change where the swift-current symlink points to and have everything work.   We will do this with the following command:

sudo ln -s /opt/swift/ swift-5.2.2-RELEASE-ubuntu18.04  swift-current

Now we will need to create the entry in our PATH variable.  To do this you will want add the add /opt/swift/swift-current/usr/bin/ directory to the PATH variable in our .profile file located in your home directory.  Then update the environment variables  The following commands will do this:

cd ~
echo 'export PATH=$PATH:/opt/swift/swift-current/usr/bin'  >> .profile
source ~/.profile

The last thing we need to do is to verify swift has been successfully installed. To do this, we can run the following command:

swift –version

The output should look something like this but with the version of swift that you installed

 Apple Swift version 5.3-dev (LLVM a60975d8a4, Swift afe134eb2e)
Target: x86_64-unknown-linux-gnu

Congratulations, you have now successfully built and installed Swift.  Now to verify that the package manager was successfully built and installed, run the following commands:

mkdir test
cd test
swift package init

If everything was successfully built you should see out similar to this:

Creating library package: test
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/test/test.swift
Creating Tests/
Creating Tests/LinuxMain.swift
Creating Tests/testTests/
Creating Tests/testTests/testTests.swift
Creating Tests/testTests/XCTestManifests.swift

You are now ready to go.