Search code examples
linuxansibleswift3libdispatch

Install Swift 3 + libdispatch on Linux with Ansible


I'm struggling to get Swift 3.0 and GCD installed on a Ubuntu 16.04. This should be possible nowadays, right?

Below is an Ansible task for downloading Swift 3 from swift.org, cloning, building and installing swift-corelibs-libdispatch from GitHub.

Even though the installation of libdispatch completes without errors, it does not work. When I try to import Dispatch in Swift repl, it complains about missing feature "blocks". Checking Makefiles confirm, that at least flag -fblocks was provided to the compiler.

Here's the example output from the Swift repl:

vagrant@swift3:/tmp/swift-3.0-PREVIEW-3-ubuntu15.10/usr/bin$ ./swift
Welcome to Swift version 3.0 (swift-3.0-PREVIEW-3). Type :help for assistance.
  1> 6 * 7
$R0: Int = 42
  2> import Dispatch
error: module 'CDispatch' requires feature 'blocks'
error: could not build Objective-C module 'CDispatch'

  2>  

Vagrantfile for setting up a box:

# -*- mode: ruby -*-
# vi: set ft=ruby :


Vagrant.configure(2) do |config|
    config.ssh.forward_agent = true
    config.vm.box = "bento/ubuntu-16.04"

    config.vm.define "swift3" do |dev|
        dev.vm.hostname = "swift3.dev"
    end

    config.vm.network :private_network, ip: "10.0.0.10"

    config.vm.provider "virtualbox" do |vb|
        vb.memory = "2048"
    end

    config.vm.provision "ansible" do |ansible|
        ansible.playbook = "ansible/main.yml"
    end
end

Ansible task for installing Swift 3:

---

- name: Install Swift 3 requirements
  apt: name={{ item }} state=installed
  with_items:
  - autoconf
  - clang
  - git
  - libblocksruntime-dev
  - libbsd-dev
  - libcurl4-openssl-dev
  - libdispatch-dev
  - libkqueue-dev
  - libpython2.7-dev
  - libtool
  - pkg-config


- name: download Swift 3
  get_url: url=https://swift.org/builds/swift-3.0-preview-3/ubuntu1510/swift-3.0-PREVIEW-3/swift-3.0-PREVIEW-3-ubuntu15.10.tar.gz
           dest=/tmp/swift.tgz mode=0440

- name: unarchive Swift 3
  unarchive: dest=/tmp src=/tmp/swift.tgz copy=no creates=/tmp/swift-3.0-PREVIEW-3-ubuntu15.10

- name: clone Swift 3 libdispatch core library
  git: repo=https://github.com/apple/swift-corelibs-libdispatch dest=/tmp/swift-corelibs-libdispatch
       version=swift-3.0-preview-3-branch force=true

- name: generate Swift 3 libdispatch build files
  command: "sh ./autogen.sh"
  args:
    chdir: /tmp/swift-corelibs-libdispatch

- name: configure Swift 3 libdispatch
  command: "sh ./configure --with-blocks-runtime=/usr/lib/x86_64-linux-gnu --with-swift-toolchain=/tmp/swift-3.0-PREVIEW-3-ubuntu15.10/usr --prefix=/tmp/swift-3.0-PREVIEW-3-ubuntu15.10/usr"
  args:
    chdir: /tmp/swift-corelibs-libdispatch

- name: make Swift 3 libdispatch
  command: "make"
  args:
    chdir: /tmp/swift-corelibs-libdispatch

- name: install Swift 3 libdispatch
  command: "make install"
  args:
    chdir: /tmp/swift-corelibs-libdispatch

- name: grant permissions to use Swift 3
  file: dest=/tmp/swift-3.0-PREVIEW-3-ubuntu15.10 mode=a+rX recurse=true

Solution

  • As you've noted the -fblocks linker flag is appropriately set for libdispatch when it is compiled. Which is great because now you have a working version of libdispatch.

    Unfortunately anything that you make that includes Dispatch is also going to require the -fblocks linker flag too.

    The tl;dr solution work-around is to simply supply -Xcc -fblocks to swiftc whenever you compile.

    This is as I've said a work-around. The longer term solution is proposed "ClangImporter: enable -fblocks on non-Darwin platforms". Until that lands though the above work-around is the shortest distance from where you are to where you want to go.

    I'll add that myself, I'm just using the patch from the pull request above to patch my local build. YMMV.