function Bootstrap {
  parameter bootFile, init, programs, debug.

  // create a list of libraries that we need to compile
  local libs is UniqueSet().
  if init <> "" {
    addLibs(libs, init).
  }
  for program in programs {
    addLibs(libs, program).
  }

  // compile the main program files
  if init <> "" {
    compileFile(init, "/init", debug).
  }
  for program in programs {
    compileFile(program, program:Replace("/prog", ""), debug).
  }

  // compile the libraries
  for lib in libs {
    compileFile(lib, lib, debug).
  }

  // Either run init with a terminal open...
  if debug {
    // Open a terminal and run init.
    CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Open Terminal").
    if init <> "" {
      run "/init".
    }
  // ... or delete the bootstrapping file, set init to the bootfile,
  // and reboot.
  } else {
    DeletePath("1:" + bootfile).
    // Set OS to boot and restart.
    if init = "" {
      set CORE:BOOTFILENAME to "".
    } else {
      set CORE:BOOTFILENAME to "/init".
    }
    reboot.
  }
}

// compile the target ('src') file on volume 0, compare compiled size with source size,
// copy the smaller file to 'dest' on volume 1.
// if debug is true, instead just copies src (volume 0) to dest (volume 1).
function compileFile {
  parameter src, dest, debug is false.

  if debug {
    CopyPath("0:" + src + ".ks", "1:" + dest + ".ks").
    return.
  }

  compile "0:" + src.
  local srcVF is Open("0:" + src + ".ks").
  local compiledVF is Open("0:" + src + ".ksm").

  if srcVF:SIZE < compiledVF:SIZE {
    CopyPath("0:" + src + ".ks", "1:" + dest + ".ks").
  } else {
    CopyPath("0:" + src + ".ksm", "1:" + dest + ".ksm").
  }

  DeletePath(compiledVF).
}

function addLibs {
  parameter libs, src.

  local srcVF is Open("0:" + src).
  local contents is srcVF:ReadAll().
  for line in contents {
    if line:Contains("RunOncePath") {
      local start is line:Find(char(34)).
      local end is line:FindLast(char(34)).
      local libFile is line:Substring(start + 1, end - start - 1).
      libs:Add(libFile).
      addLibs(libs, libFile).
    }
  }
}