Contributing to Swift — Part 1

Suyash Srijan
Kin + Carta Created
6 min readDec 13, 2018

If you’ve been writing Swift code for a while, then you probably know that Swift is open source and if you’re passionate about writing Swift code, then perhaps you already have some ideas on how to improve it or maybe you have identified a bug that needs to be patched.

So, why wait for someone else to do it when you can do it yourself, right? Well, the sheer size and complexity of the codebase (almost 1M lines of code) is enough to scare most people, but I am here to say that anyone can contribute to Swift. I won’t say that it’s easy, but it’s definitely achievable and it’s very rewarding when you contribute to an open-source project used by hundreds of thousands of people worldwide.

This blog post will be divided into two parts:

  • Part 1: Learn the basics of how to get started with contributing to Swift.
  • Part 2: Learn how I resolved several issues in the Swift compiler.

Steps

  1. Identify the problem
  2. Check out the source code
  3. Resolve the problem
  4. Test your code
  5. Submit a PR

Identify the problem

The first step to contributing is identifying the problem. If you haven’t identified a bug/improvement yourself, then a good place to start is the Swift JIRA, located at https://bugs.swift.org.

If you find an issue that you want to resolve and there’s no one assigned to it, then you can assign it to yourself and start working on it.

Tip: If you’re new to the Swift compiler, then look for the issues tagged with the “Starter Bug” label, which aren’t too complicated to resolve.

Check out the source code

This step is pretty straightforward — you need to install a few dependencies, clone the Swift repo and run a bunch of commands to set up the project. The basic system requirements are at least 2 GB of free space for the source code and up to 70 GB of free space for the build artifacts (with full debugging).

This can be done by following the steps below (macOS only — if you’re using Linux, then follow the instructions here):

  1. Install Homebrew: /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install"
  2. Install CMake and Ninja: brew install cmake ninja
  3. Make a directory to store the source code: mkdir swift-source and then switch to that directory: cd swift-source
  4. Make a fork of the repo and clone it: git clone https://github.com/<your username>/swift.git
  5. Download/update the source code for other Swift related projects (such as LLVM and swift-corelibs): ./swift/utils/update-checkout --clone
  6. Switch to the version of Xcode that the Swift CI uses (at the moment, it’s Xcode 10.1): sudo xcode-select -switch /Applications/Xcode<version_number>.app
  7. Invoke the build script: ./swift/utils/build-script -x (there are other options available, you can read about them here)

Depending on how fast your Mac is, a clean build can take a couple of hours (subsequent builds will require less time), but once it’s done, an Xcode project will be generated at ./swift-source/build/Xcode-DebugAssert/swift-macosx-x86_64 (note: the folder name might differ if you passed different arguments to the build script).

Swift Xcode project

There are over 700+ schemes (no kidding), but the important ones are:

  • swift (that’s the compiler front-end)
  • swift-stdlib (that’s the standard library)
  • ALL_BUILD (builds everything)
  • check-all-swift (runs primary tests)

Resolve the problem(s)

Now that you have the source code of the compiler (and related projects), it’s time to crack on and resolve the issues you’ve assigned yourself to. The issue might be really easy or extremely difficult to fix, but if you need help, then feel free to reach out to the compiler devs on the issue page, on Swift forums or on GitHub — they’re really friendly and helpful.

Read part 2 of this blog post if you want to learn how I resolved several issues on the compiler!

Test your code

You have written your code and resolved the issue, now it’s time to test! Here’s a document that goes in-depth about testing, but it’s rather long, so here’s a summary:

  1. You can invoke the test script — ./swift/utils/build-script --test and it will run all the tests for you. This will take a long time as the script will re-build all the targets before running the tests. If you’ve made a large, potentially breaking change, then you must pass the --validation-test parameter as well.
  2. If you only want to test just a particular file then you can use LLVM lit (🔥) — llvm/utils/lit.py -sv /path/to/swift/test/dir/ --filter=<test_file_name.swift>. If you want to know what other parameters you can pass to lit, then you can invoke lit.py -h.
  3. You can also run the tests via Xcode — just select one ofcheck-* targets and build the project.

Running tests is important, but you also need to add your own tests. It’s very simple — navigate to swift/test and create a new test file in the appropriate test sub-directory, or add it to an existing test file.

For example, here’s a test I wrote for one of the issues I resolved and the file is located at: test/SILGen/functions_uninhabited_param.swift.

The first line of the test file contains a RUN comment, where you specify the arguments passed to the compiler.

If you’re testing diagnostics messages, then you also need to add a comment at the end of each expression so the test runner can match the diagnostic emitted by the compiler with the one you specify. This is done by adding an expected-{diagnostic_type} {{diagnostic message}} comment. It also helps the person reading the test file know that this line of code is going to trigger a diagnostic.

Keep your tests simple and to the point. Avoid adding any unnecessary or irrelevant code as that could confuse the person reading it.

Submit a PR

There are a couple of minor things to do before you create a PR:

  1. The commit(s) title must include a tag mentioning the part of the compiler that was changed. For example, if you make changes to lib/SILGen, then commit must be prefixed with [silgen].
  2. Use spaces for indentation.
  3. Run git-clang-format (in clang/utils) to re-format your code.

Now, it’s time to create a PR!

It’s important to have a concise description of what’s changed and the issue number(s) being resolved (SR-XXXX).

When you first submit a PR, you may receive comments from other compiler devs asking to make further changes. This is okay, as we’re not Chris Lattner!

But once the PR gets approved and merged, it does feel really good.

There are many other amazing posts on our engineering blog — go have a read! If you enjoy solving challenging problems then we’d love you to be a part of our talented and amazing iOS team. Please send me a message if you are interested! 😄

Further Reading

Compilers are known to be some sort of magic black box that only wizards could understand, but that’s not true! If you have have no knowledge whatsoever about how compilers work or don’t know how to write C++ code, then fret not — there are some fantastic resources available that can help you get started with compiler development:

  • If you want to learn more about compiler theory, here’s two amazing books — Modern Compiler Implementation in C and Compilers: Principles, Techniques and Tools.
  • If you want to learn more about programming with LLVM, here the LLVM Programmer’s Manual and the LLVM Coding Standards.
  • If you want to learn more about C++, here’s a course on Udemy where you can learn how to write C++ code.
  • If you want to learn more about how the Swift compiler works, then the docs folder contains a lot of docs that provide a lot of information (although some of it is a little out of date) to help you understand various aspects of the compiler. The source code is fairly documented as well.

--

--

Suyash Srijan
Kin + Carta Created

iOS Engineer at @theappbusiness. Swift compiler collaborator.