package b0
Install
dune-project
Dependency
Authors
Maintainers
Sources
sha512=e9aa779e66c08fc763019f16d4706f465d16c05d6400b58fbd0313317ef33ddea51952e2b058db28e65f7ddb7012f328c8bf02d8f1da17bb543348541a2587f0
doc/action.html
The b0 action manual
This manual shows how to deal with b0 actions and how to create your own.
TODO. Not super clear yet.
Basics
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:
- Can be associated to an empty unit and not build anything. For example it can simply run a script or an OCaml function to download and refresh conformance tests or data from the web.
- May explicitely require other units or packs to be build in order to be run.
- May simply be the executable built by the unit.
- May simply be the public tool.
- Has access to what was part of the build. For example the
.ocaml
library unit is an action that has a few subcommand whose outcomes. - Can influence how the build is done (
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 theocaml
REPL, etc.B0_jsoo.html_page
units reload the webpage in your browser
Making your own action
XXX 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 ()
Howto
Run a built executable in (another) action
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")
Fetch an URL and write it in the scope
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)