package b0

  1. Overview
  2. Docs
Software construction and deployment kit

Install

dune-project
 Dependency

Authors

Maintainers

Sources

b0-0.0.6.tbz
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:

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)