b0 driver manual

A b0 driver like b0 is an executable that provides a service on the definitions of a b0 file. This manual shows how to develop a custom driver for b0 files.

Note that it is unlikely you will need to create your own custom driver. A lot can be achieved by simply devising actions, read the action manual. But if you are interested in understanding the b0 tool machinery in more details, read on.

Overview

The b0 file needs to be compiled and made accessible to the driver executable. The deriver machinery does not use OCaml's Dynlink module. Instead the driver executable relinks its objects with a compilation of the b0 file to produce another executable that is executed to run the driver on the definitions.

With the help of the B0_driver module this all happens transparently in the .drivers directory of the _b0 directory.

The driver's library

For your driver to access a b0 file you need to create an OCaml library which has all the objects of your driver and registers its main function by calling B0_driver.set.

Source wise a typical driver source structure is:

src/mydriver_main.ml
src/mydriver_main_run.ml

The mydriver_main.ml file implements and registers the driver. Its compiled object should be part of your driver library. Here's a minimal example :

open B0_std
open Cmdliner

let my_driver conf = Fmt.pr "Running!@."; Os.Exit.ok

let driver =
  let name = "mydriver" and version = "%%VERSION%%" in
  let self = B0_ocaml.libname name in
  let libs = [self (* other needed libraries can be added here *) ] in
  B0_driver.make ~name ~version ~libs

let main () =
  let cmd =
    let doc = "My driver" in
    let exits = B0_driver.Exit.infos in
    let man = [ `S Manpage.s_description; `P "$(iname) does not much." ] in
    let name = B0_driver.name driver and version = B0_driver.version driver in
    Cmd.v (Cmd.info name ~version ~doc ~exits ~man) @@
    B0_driver.with_b0_file ~driver (Term.const my_driver)
  in
  Cmd.eval_value cmd

let () = B0_driver.set ~driver ~main

The mydriver_main_run.ml file defines your driver executable when it has no b0 file linked in. It's the program that runs your driver without the b0 file linked in. It should simply be:

let () =
  let module D = Mydriver_main (* make sure we link it *) in
  if !Sys.interactive then () else B0_driver.run ~has_b0_file:false

A few things to note:

FIXME

The driver dance seems to be a bit slow for now. Even for the up-to-date dance we get into the 18-30ms b0 unit list. But there's room for improvement. Here are different things to consider that could be done.