package b0
Install
Dune Dependency
Authors
Maintainers
Sources
sha512=78fd9e53b84cf5d6bf497adaf4b6d7d974134044318639cdfe5e01c7faaa8d987d04769abe3b3b1cbdb937132e21d8723dc185cd3c68433a793278907a8e757e
doc/driver_dev.html
B0 driver development manual
A B0 driver like b0
or d0
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.
Overview
The B0 file needs to be compiled and made accessible to the driver executable. At the moment the OCaml Dynlink
API is not being used. 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 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. It's compiled object should be part of your driver library. Here's a minimal example :
open B0_std
open Cmdliner
let driver =
let name = "mydriver" and version = "v0.0.2" in
let libs = ["mydriver" (* other needed libraries can be added here *) ] in
B0_driver.create ~name ~version ~libs
let my_driver conf = Fmt.pr "Running %s!@."; B0_driver.Exit.ok
let my_driver =
let doc = "My driver" in
let sdocs = Manpage.s_common_options in
let exits = B0_driver.Exit.Info.base_cmd in
let man = [ `S Manpage.s_description; "$(mname) does not much." ] in
B0_driver.with_b0_file ~driver (Term.const unit_cmd),
Term.info "mydriver" ~version:"v0.0.2" ~doc ~sdocs ~exits ~man
let main () = Term.eval mydriver
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:
- Your driver library must be installed and available in the
OCAMLPATH
under the name you gave in toB0_driver
. - The driver library's directory is not added to the includes for compiling the B0 file. This prevents drivers from adding declarations to the compilation environment since using them in a B0 file would then break other drivers. New declarations must always be explicitely imported in the B0 file by using the
#require
directive.
FIXME
The driver dance seems to be a bit slow for now. Even for the up-to-date dance we get into the 43ms b0 unit list
. But there's room for improvement. Here are different things to consider that could be done.
- Cold driver compilation. I think we get hit a bit by the executable link phase (globally 500ms, but the compilation spawn takes 480ms). Investigate what makes OCaml linking faster. Maybe a mono cmo ? Alternatively consider using
Dylink
once it gets lib support, but then what about platforms that don't support it. - The various timing obtained with
b0 file log --stats
andb0 -v -v
don't add up to whattime b0
reports. Investigate, is it the execv ? June 2020: maybe it is/was that. Also see how much toplevel init takes (how ?). - Try to jump directly into the compiled driver executable and let it auto verify and auto recompile if needed ? This could allow to share part of the hash cache in the future.
- Maybe go back to use an ad-hoc stamp for driver compilation rather than use B00 itself.