HOME -> Swift on Linux

Trying to Build Swift on CentOS 7.1 from Source

December 14, 2015

After experimenting with Apple-provided Swift binaries on Ubuntu, I decided to use the instructions at https://github.com/apple/swift/blob/master/README.md to try and build Swift on a Linux distro where pre-build binaries are not available. As of this writing they are only provided for Ubuntu 14.04 and 15.10. I picked CentOS 7.1 in an Azure virtual machine (VM). The VM instance was a standard DS3 (4 cores, 14 GB memory).

My attempts have been only partially successful. Please see the summary.

Caution: A Lot of Memory is Needed

The build process is a memory hog! At first I used the build script as suggested in the instructions: utils/build-script -t and ran out of memory when an executable was buing built. Reading the help dumped by the script when given the -h option, I figured that the memory footprint could be reduced by doing a release build; the default is debug. So, after adding the -R option, I saw the build process complete without starving the box out of memory.

Install Prerequisites

The build instructions at swift.org provide a list of required dependencies for Ubuntu. I had to experiment a little to find the corresponding list for CentOS 7.1: Also please note:

Get the Sources

Then I created the following directory structure. You may, of course, adjust this to your liking. mkdir swift_2.2 cd swift_2.2 Then I obtained the sources from GitHub: git clone --branch swift-2.2-SNAPSHOT-2015-12-01-b https://github.com/apple/swift.git swift git clone --branch swift-2.2-SNAPSHOT-2015-12-01-b https://github.com/apple/swift-llvm.git llvm git clone --branch swift-2.2-SNAPSHOT-2015-12-01-b https://github.com/apple/swift-clang.git clang git clone --branch swift-2.2-SNAPSHOT-2015-12-01-b https://github.com/apple/swift-lldb.git lldb git clone https://github.com/apple/swift-cmark.git cmark git clone --branch swift-2.2-SNAPSHOT-2015-12-01-b https://github.com/apple/swift-llbuild.git llbuild git clone --branch swift-2.2-SNAPSHOT-2015-12-01-b https://github.com/apple/swift-package-manager.git swiftpm git clone --branch swift-2.2-SNAPSHOT-2015-12-01-b https://github.com/apple/swift-corelibs-xctest.git git clone --branch swift-2.2-SNAPSHOT-2015-12-01-b https://github.com/apple/swift-corelibs-foundation.git git clone --branch release https://github.com/ninja-build/ninja.git A few things to note:

The Build Process

The swift.org documentation mentioned earlier suggests using at least Clang 3.6 for building the software. The most recent version available from the repository was 3.4.2, so I did the following:
  1. Built just Swift and LLVM, which includes Clang 3.8, using the repo-provided Clang 3.4.2.
  2. Used the new Clang 3.8, built as part of LLVM, to re-build Swift and LLVM and also build LLDB, llbuild, Swift Package Manager (failed), and Foundation.
Alternatively we can build a more recent Clang from source that can be obtained from http://www.llvm.org, but there may be some surprises there, see http://www.omniprog.info/cpp.html

You can do utils/build-script -h to find out about the various options the build script supports.

Build Clang 3.8

From the swift_2.2 directory, I did: cd swift utils/build-script -t -R This will build LLVM, Clang, and Swift. The -t option will cause tests to be built and run. Unless your box has a lot of memory, make sure you use the -R flag to do a release build. Otherwise debug will be built (the default), and the build may run out of memory. I was unable to do this even on a box with 14 GB. Watching the memory with the -R flag showed that at least 6 GB of RAM is needed for a release build.

At one point the build failed, complaining about the missing /usr/include/x86_64-linux-gnu/sys/ioctl.h header. This was fixed by ln -s /usr/include /usr/include/x86_64-linux-gnu and the build completed successfully.

Build LLDB, LLBUILD, Swift Package Manager, and Foundation

Now that Clang 3.8 is available, LLVM, Clang, and Swift can be re-build using the new Clang. In addition, LLDB, LLBUILD, Swift Package Manager, and Foundation can be built. The build script by default places the build in the "build" sub-directory of (in our case) swift_2.2, so we rename the "build" directory to something else and adjust the path so that Clang, LLVM, and related binaries from that directory are used. Then: # This is from the swift_2.2 directory cd swift utils/build-script -l -b -p --foundation -R Note that tests are not built here. You can add -t to build and run them if desired.

After awhile the build stops with this error: :0: error: unable to attach DB: unable to initialize database (near "WITHOUT": syntax error) bootstrap: error: build failed with exit status 1 utils/build-script: command terminated with a non-zero exit status 1, aborting This happens while swiftpm is being built. So, we'll go straight to building Foundation: utils/build-script --foundation -R The Foundation build completes, but I can't see how to use it yet.

Let's Try It!

swiftc and swift commands can be used with a trivial Swift file to compile it to a native executable or to run it in interpreter mode.

However, swift REPL does not work: [root@centos71 ~]# swift LLVM ERROR: Compiler-internal integrated REPL unimplemented for this platform Trying to use the Swift build system the way it is described in the swift.org instructions mentioned earlier gives: [root@centos71 Hello]# swift build error: unable to invoke subcommand: /root/swift_2.2/build/Ninja-ReleaseAssert/swift-linux-x86_64/bin/swift-build (No such file or directory) Indeed, the file swift-build does not exist in that directory. This works fine on Ubuntu with the Apple-provided binaries.

Now try to use Foundation. Suppose the file junk.swift contains: import Foundation print ("Hey swift on Centos7.1!") Trying to run it: [root@centos71 ~]# swift junk.swift junk.swift:1:8: error: no such module 'Foundation' import Foundation ^ [root@centos71 ~]# swift --help OVERVIEW: Swift compiler USAGE: swift [options] OPTIONS: ... -framework Specifies a framework which should be linked against -F Add directory to framework search path ... -I Add directory to the import search path [root@centos71 ~]# ls /root/swift_2.2/build/Ninja-ReleaseAssert/foundation-linux-x86_64 2ZK9JHZ46ETPO Foundation modules.timestamp [root@centos71 ~]# ls /root/swift_2.2/build/Ninja-ReleaseAssert/foundation-linux-x86_64/Foundation/ closure CoreFoundation Foundation Foundation.swiftdoc Foundation.swiftmodule libFoundation.so usr uuid [root@centos71 ~]# ls /root/swift_2.2/build/Ninja-ReleaseAssert/foundation-linux-x86_64/Foundation/CoreFoundation/ Base.subproj Locale.subproj PlugIn.subproj String.subproj Collections.subproj NumberDate.subproj Preferences.subproj URL.subproj Error.subproj Parsing.subproj StringEncodings.subproj So, let's try a few things: [root@centos71 ~]# swift -I /root/swift_2.2/build/Ninja-ReleaseAssert/foundation-linux-x86_64/Foundation junk.swift junk.swift:1:8: error: missing required module 'CoreFoundation' import Foundation ^ [root@centos71 ~]# swift -I /root/swift_2.2/build/Ninja-ReleaseAssert/foundation-linux-x86_64/Foundation -F /root/swift_2.2/build/Ninja-ReleaseAssert/foundation-linux-x86_64/Foundation -framework CoreFoundation junk.swift junk.swift:1:8: error: missing required module 'CoreFoundation' import Foundation ^ [root@centos71 ~]# swift -I /root/swift_2.2/build/Ninja-ReleaseAssert/foundation-linux-x86_64/Foundation -F /root/swift_2.2/build/Ninja-ReleaseAssert/foundation-linux-x86_64/Foundation/CoreFoundation -framework CoreFoundation junk.swift junk.swift:1:8: error: missing required module 'CoreFoundation' import Foundation ^ As one can see, using the -I flag with the location of the Foundation framework lets swift find Foundation, but I still need to figure out how to make it see CoreFoundation. More documentation reading is needed... If you have any ideas, please let me know.

Summary

So, the attempts to build a usable Swift on CentOS 7.1 have been partially successful: the swift command could be run as an interpreter on a trivial source file, swiftc could be used to compile the file into a native binary, but the Swift build system and Swift REPL didn't work.

In addition to building the source tagged with swift-2.2-SNAPSHOT-2015-12-01-b, I also tried the current head of the repository, i.e. cloning without a --branch option, as well as the most recent tag, which is swift-2.2-SNAPSHOT-2015-12-10-a as of this writing. The results were almost the same, except that when the untagged code or the code with the most recent tag was used, things were slightly different:

Building the tag swift-2.2-SNAPSHOT-2015-12-10-a on Ubuntu 14.04 took me a step further: the build system actually worked with trivial code. The binary used for this was built as part of swiftpm, which failed to build on CentOS 7.1. See http://www.swiftprogrammer.info/swift_ubuntu_2.html.

Thus it looks like the newly-open-sourced Swift is in its infancy, and there is a lot of homework to be done, but its a great baby and will hopefully grow into a mature open source language!

Please feel free to contact me with questions or comments.

© 2015 swiftprogrammer.infoAnatoli Peredera