This manual shows how to deal with b0 actions and how to create your own.
TODO. Not super clear yet.
Build artefacts are meant to be executed, displayed, tested, benchmarked, deployed etc. As such b0 treats building as a mere side effect and associates to each build unit an action. The action of a unit u
can simply be run with:
b0 -- UNIT ARG…
This builds the unit named UNIT
like b0 -u UNIT
would do and execute UNIT
's action with arguments ARG…
.
Note that an action:
.ocaml
library unit is an action that has a few subcommand whose outcomes.B0_unit.Action.store
).A lot of domain specific build unit constructors will define a default action for you. Here are a few examples:
B0_ocaml.exe
units simply execute the built executableB0_ocaml.lib
units load the build library in the ocaml
REPL, etc.B0_jsoo.html_page
units reload the webpage in your browserXXX Needs more words.
An action has to be part of a unit, that's the way you can operate on it. However that unit may be empty build-wise. The B0_unit.of_action
constructors do this.
The following action takes a sript located in scripts/hello.sh
in the B0.ml
scope directory and runs it with the cwd
set to the scope directory.
let hello =
B0_unit.of_action' "hello" ~doc:"Run hello script" @@ fun env _ ~args ->
let cwd = B0_env.scope_dir env in
let hello = B0_env.in_scope_dir env ~/"scripts/hello.sh" in
Ok (Os.Exit.execv ~cwd Cmd.(path hello %% args))
Even though you should rewrite all these scripts as OCaml actions a direct shortcut for the above boilerplate is provided by B0_unit.Action.scope_exec
:
let hello =
B0_unit.of_action' "hello" ~doc:"Run hello script" @@
B0_unit.Action.scope_exec (Cmd.path ~/"scripts/hello.sh")
The two last examples actually perform B0_std.Os.Exit.execv
so the b0 invocation becomes these executables. You can also simply run cmds without becoming them, so rather than shell scripting around you can write OCaml scripts.
let hello =
B0_unit.of_action "hello" @@ fun env _ ~args ->
let* () = Os.Cmd.run Cmd.(tool "echo" % "hey" ) in
let* () = Os.Cmd.run Cmd.(tool "echo" % "ho" ) in
Ok ()
For those units that build an executable and mention it in their metadata as B0_unit.exe_file
and are in your scope the following shows how to run it in another unit. The key step is to look them up with B0_env.unit_exe_file_cmd
and make sure that unit is actually built by specifying it in ~units
of B0_unit.of_action
.
let tool = … (* This unit should have the B0_unit.exe_file set. *)
let action
let doc = "Do stuff with tool" in
B0_unit.of_action "my-exec" ~units:[tool] ~doc @@ fun env _ ~args ->
let* cmd = B0_env.unit_exe_file_cmd env download_data in
Os.Cmd.run Cmd.(cmd % "--help")
let download_test_data =
let doc = "Download test data" in
B0_unit.of_action "download-test-data" ~doc @@ fun env _ ~args:_ ->
let file = "data.json" in
let url = Fmt.str "https://example.org/%s" file in
let dst = Fmt.str "test/%s" file in
B0_action_kit.fetch_url env url (B0_env.in_scope_dir env ~/dst)