What does Swift support in CMake mean for Swift's build?

I was thinking about this a little bit and I actually think that there are two additional motivating actions here we are not considering:

  1. We could use this to break the dependency of swift based tools (e.x. swift-syntax) that swift's cmake builds on building the stdlib.

  2. CMake for free will let us integrate swift code into swiftc itself trivially.

I go through both below since there are a few different implications of both.

Breaking the Dependency of Swift based tools on building the stdlib

By compiling these tools with the host swiftc, we break the dependency of tools on the just built stdlib. This will have a number of knock on effects:

  1. Build/test time will be reduce by allowing for these tools (and any large downstream work) to be compiled and tested without building the stdlib. This will massively reduce the time for building/testing such tools. Such timing/productivity improvements can result in the development of these tools to be more agile and save development time/money (insert xkcd sword fighting reference here).

  2. The last cmake dependency in between "tools" and the stdlib/runtime will be broken. This will finally let us split the stdlib cmake from the main swift cmake build and have swift's cmake invoke the stdlib cmake as a subproject. This would let us move swift's cmake to standard llvm cmake and leave the current crazy cmake badness just in the stdlib (for now).

One last thing to note is that with proper integration and ABI/Module stability we should be able to still install these tools into a snapshot and have them use the just built swift stdlib.

Using Swift Code in swiftc

The most exciting realization I had was that the newer cmake will make it easy for us to write parts of swift the compiler in swift:interrobang:. In fact, I was able to put together a proof of concept using the latest cmake nightly. If you want to try it out:

  1. Download the latest cmake nightly:
curl -LO https://github.com/Kitware/CMake/releases/download/v3.15.0-rc2/cmake-3.15.0-rc2-Darwin-x86_64.tar.gz
  1. Compile master with this branch from my fork: GitHub - gottesmm/swift at cmake-swift-support-proof-of-concept. You inject the cmake by passing it to build-script like so:
./swift/utils/build-script --release-debuginfo --assertions --distcc
--skip-build-benchmarks --build-subdir swift-cmake-asserts --cmake
$PATH_TO_TARBALL_CONTENTS/cmake-3.15.0-rc2-Darwin-x86_64/CMake.app/Contents/bin/cmake
--reconfigure

The branch injects into SILGen a small bit of swift code that every time swiftc compiles a function prints to stdout the representation of a local swift class and then additional prints to stdout "hello world".

One important caveat is that if we decide that we do not want to update to the newer cmake immediately, we can still write parts of swiftc in swift that would not be needed to bootstrap the compiler. As an elucidating example consider a SIL optimizer pass as a candidate:

  1. The interface by which a SIL optimizer pass exposes itself to the rest of the compiler is limited to a Transform class. We could wrap transform in a c struct that could be imported into swift. We can inject the transform back into swift by defining a swift @_cdecl public function with an appropriate name. Since all swift optimizer passes are defined in a .def file, we can be sure that the optimizer pass pipeline would be able to take in the unwrapped Transform class and inject it into the pass pipeline.

  2. SIL's instructions themselves are defined via a .def file. This means that we can generate swift c wrapper classes for the c++ instructions using the c preprocessor.

  3. Optimizer passes are optional, so if we are doing a bootstrap build of swiftc, we can just not enable those passes.

The only downside is that we have written a bunch of helpers for the optimizer in c++, so it may not make sense to do this before we have true c++ interop. But perhaps some simple passes/new subsystems of various passes, could be written in swift itself.

16 Likes