Module B0.Build

module Build: sig .. end

This module is all you need to define your own build functions. It allows to access directories and files, consult the build configuration, submit build operations and read and write file path metadata.


type t = 
The type for builds. A build gathers the build environment, configuration, cache and schedules the build operations.
type run 
The type for tool runs.
type 'a fiber = ('a -> unit) -> unit 
The type for build operation fibers.

Directories and files

val build_dir : -> B0.Fpath.t
build_dir b is the path to b's current, unit-specific, build directory. This is where you should produce your build artefacts.
val build_file : -> string -> B0.Fpath.t
build_file b f is Fpath.(build_dir b / f).
val src_dir : -> B0.Fpath.t
src_dir b is the path to b's current source root, where non-built (source) files are expected too be looked up. If you are using b0's description files this is the directory of the file in which the unit is described.
val unit_build_dir : -> B0.Unit.t -> B0.Fpath.t
unit_build_dir b u is the build directory of unit u. This should only be used to lookup files in other build units.

FIXME. Do the build unit request API.

Tool and configuration lookup

val conf : -> 'a B0.Conf.key -> 'a
conf b k is k's effective value for the build.
val tool : -> B0.Tool.t -> B0.Cmd.t -> run
tool b t args is t's tool for the build is a run for the tool t with args.

Warning. The resulting run must only be used to B0.Build.spawn with b.

val conf_tool : -> B0.Tool.t B0.Conf.key -> B0.Cmd.t -> run
conf_tool b k is tool b (conf b k).

Build operations

TODO Explain that basically build operations read and write files. For an operation to be executed all the files it reads need to be ready. A file becomes ready either if it has been declared as such or if it has been written by a build operation.

Build roots

Build roots are non-built files, typically sources or external libraries. In order to read them in a build operation (i.e. introduce a dependency on them) you need to declare them as being B0.Build.ready, otherwise the operation waits for it to be produced and fails if that doesn't eventually happen.

val ready : -> B0.Fpath.t -> unit
ready b p declares path p to be ready in b. This is typically used with sources files and files external to the build (e.g. intalled libraries). See also B0.Build.src.
val src : -> B0.Fpath.t -> B0.Fpath.t
src b src is:
let src = Fpath.(src_dir b // src) in
ready b src; src

Tool spawns

Tool spawns are asynchronous and can be issued in any order. Actual execution occurs once the all files the files that are declared to be read by the spawn are ready. Produce spawn operations as soon as possible to maximize parallelism.

type stdo = [ `File of B0.Fpath.t | `Tee of B0.Fpath.t | `Ui ] 
The type for standard output redirections.
val spawn : ->
?reads:B0.Fpath.t list ->
?writes:B0.Fpath.t list ->
?exits:int list ->
?env:B0.OS.Env.t ->
?cwd:B0.Fpath.t ->
?stdin:B0.Fpath.t ->
?stdout:stdo -> ?stderr:stdo -> run -> unit
spawn b ~reads ~writes ~success ~env ~cwd ~stdin ~stdout ~stderr run spawns run once reads files are ready and makes files writes ready if the spawn succeeds and the file exists. The rest of the arguments are:

TODO This is already quite complete, however the following could be added (maybe through another primitive):

  1. Support to refine the read and write set after the operation returns.
  2. Support to write a stamp if the tool spawn doesn't write any file but needs to be synchronized with another op.
  3. Support to call a fiber once the operation as completed.

File operations

val read : -> B0.Fpath.t -> string fiber
read b file k reads the contents of file when it becomes ready and invokes k s.
val write : -> ?reads:B0.Fpath.t list -> B0.Fpath.t -> (unit -> string) -> unit
write b ~reads f gen once reads are ready writes gen () to f assuming the result depends only on reads. This means that if reads do not change and f was already computed k is not invoked. If reads is empty (default) gen is invoked on every run.

FIXME Not implemented.

val copy_file : ?linenum:int -> -> B0.Fpath.t -> B0.Fpath.t -> unit
copy_file ?linenum src dst, copies src to dst. If linenum is specified the following line number directive is prepended to the contents of src in dst:
#line $(linenum) "$(src)"
with $(linenum) and $(src) substituted with the values of linenum and src.
val mkdir : -> B0.Fpath.t -> unit fiber
mkdir b d k creates dir and proceeds with k. Note. No file is being made ready.

Unit synchronisation

val await_units : -> B0.Unit.t list -> unit fiber
await_units b us k waits for the build of us to be finished before proceeding with k us.

TODO. request_unit API.

Failing operations

val fail : ((('a, Format.formatter, unit, unit) Pervasives.format4 -> 'a) -> unit) -> 'b
fail (fun m -> m fmt ...) fails the current build unit with the formatted message m.
val fail_on_error_msg : 'a B0.result -> 'a
fail_on_error_msg r is:

File path metadata

val find_path_meta : -> B0.Fpath.t -> 'a B0.Meta.Fpath.key -> 'a option
find_path_meta b f k is f's meta binding for k in build b (if any).
val add_path_meta : ?force:bool -> -> B0.Fpath.t -> 'a B0.Meta.Fpath.key -> 'a -> unit
add_path_meta ~force b f k v sets f's meta binding for k to v. Unless force is true (defaults to false) the built unit fails if k is already bound for f.


val unit : -> B0.Unit.t
unit b is the unit being built.
val units : -> B0.Unit.t list
units b are the unit that are being built.

Creating and running builds

Note. Unless you are using B0 as a library or creating your own driver you need not be concered by this. TODO maybe move that to a private sub-module.

type ctrl 
The type for build controls. Controls how the build is performed.
val ctrl : ?tty_cap:B0.Tty.cap -> ?max_spawn:int -> unit -> ctrl
ctrl ~max_spawn controls a build as follows:
val create : B0.Cache.t ->
ctrl ->
B0.Env.t ->
B0.Conf.t ->
B0.Meta.Fpath.Map.t ->
dir:B0.Fpath.t ->
universe:B0.Unit.t list -> B0.Unit.t list -> B0.result
init cache ctrl ~dir initializes a new build using dir as the build directory.

WARNING. Anything can happen in that directory do not use a dir that contains data you might want to keep.

val env : -> B0.Env.t
env b is b's environment.
val dir : -> B0.Fpath.t
dir b is the absolute path to b's build directory. It is unlikely you will have to use this.
val cache : -> B0.Cache.t
val stored_conf : -> B0.Conf.t
val cpu_dur : -> B0.Time.cpu
cpu_dur d is the current cpu duration. The value freezes after B0.Build.finish.
val total_dur : -> B0.Time.span
total_dur b is the current total wall-time duration. The value frezzes after B0.Build.finish.
val finished : -> bool

Running the build

val start : -> unit
start b starts the build.
val finish : -> unit B0.result
finish b finishes the build b.