logo

Bootstrap

Overview

The Fan compiler is written in Fan itself - which presents a chicken and the egg problem. How do you compile the compiler without having a compiler? To solve this problem, the bootstrap process requires two Fan installations:

  1. rel: known good Fan installation (typically the last build)
  2. dev: development environment to build

By convention we structure our development directory tree like this:

dev/
  rel/
    bin/
    lib/
    ...
  fan/
    bin/
    lib/
    src/
    ...

The "rel" directory always contains the last released build. The "fan" directory contains our main development code branch. We call our top level directory "dev", but for the purposes of this discussion "fan" is the development directory.

Substitutes

On a clean machine with only source code, we don't have any pods compiled such as sys, build, or compiler. In order to run the build scripts to compile these pods, we need to use our rel installation. To make this all work seamlessly, the Fan launcher will look in "sys.props" to see if a substitute runtime should be used. For example in our environment we map the following scripts to use the rel installation:

fan.runtime.substitutes=                             \
  /C:/dev/fan/src/buildall.fan       = C:\\dev\\rel  \
  /C:/dev/fan/src/buildboot.fan      = C:\\dev\\rel  \
  /C:/dev/fan/src/jfan/build.fan     = C:\\dev\\rel  \
  /C:/dev/fan/src/sys/build.fan      = C:\\dev\\rel  \
  /C:/dev/fan/src/compiler/build.fan = C:\\dev\\rel  \
  /C:/dev/fan/src/build/build.fan    = C:\\dev\\rel

The launcher will check if any script being run matches one of those files. If a match is made, then it will route to the alternate runtime specified. Turn on launcher debugging to see exactly what is happening under the covers.

Buildall

The "buildall.fan" script is the top level build script for compiling the Fan distribution. We commonly run this command to rebuild everything and run tests on every pod:

buildall full test

The "buildall" script is executed by the rel substitute runtime and in turn launches two sub-scripts. The "buildboot.fan" script manages rebuilding the core runtime modules:

sys/build.fan
jfan/build.fan
nfan/build.fan
compiler/build.fan
build/build.fan

Once the bootstrap modules are compiled, the development environment is self hosting and can be used to compile the remainder of itself. This is done via the "buildpods.fan" script.

Dependencies

The bootstrap issue can cause some confusing dependency issues which are summarized here:

  • The rel compiler will be generating the sys, compiler, and build pod files. This means that the rel compiler must be able to generate fcode that the dev runtime can read. It also means that the rel compiler must be able to read any new syntax used by dev versions of sys, compiler, and build.
  • The rel compiler will actually use the dev versions of the pods to resolve dependencies. For example dev compiler can reference new sys APIs defined in dev but not rel. Under the covers this works because the compiler and build pod's build scripts specify a non-default dependsDir.

Because of these restrictions, adding new language features and fcode changes require some careful planning.