A Minimal Working Example demonstrating the use of rules_ocaml and tools_opam.
Install Bazel, minimum version 8.0.0. Then:
demo_hello
$ git clone https://github.com/obazl/demo_hello.git $ cd demo_hello $ bazel run bin:greetings $ bazel run bin:greetings --tc=ocamlc (0) $ bazel test test $ bazel run @opam (1) $ bazel clean (2) $ bazel build //... (3) $ bazel test //... (4) $ bazel test //... --build_tests_only (5) $ bazel build lib/hello:Hello --config=modinfo (6) $ bazel build lib/hello:Hello --config=modinfo --tc=ocamlc $ bazel build lib/hello:Hello --config=siginfo (7) $ bazel build lib/hello:Hello --config=cmtinfo (8) $ bazel build lib/hello:Hello --config=cmtiinfo (9) $ bazel build lib/goodbye:Goodbye --config=gensig (10) $ bazel run @ocaml $ bazel run @utop $ bazel run @dbg --pgm=bin:greetings (11) $ dune build (12) $ dune run bin/main.exe (13) $ dune test
-
Uses
ocamlc.opt
compiler.--tc=<compiler>
can be used with all cmds here. -
Runs opam; shows location of switch.
-
Forces rebuild. Rarely needed in practice.
-
Builds all targets
-
Builds all targets and runs all tests
-
Runs all tests but only builds targets required by the tests
-
Runs
ocamlobjinfo
against hello.cmx (see .bazelrc) -
Runs
ocamlobjinfo
against hello.cmi (see .bazelrc) -
Runs
ocamlcmt
against hello.cmt (see .bazelrc) -
Runs
ocamlcmt
against hello.cmti (see .bazelrc) -
Generate interface for goodbye.ml (
ocamlc -i
) (see .bazelrc) -
Runs
ocamldebug
. See .bazelrc -
Dune and Bazel play nice together.
-
Dune requires that the executable name match a module name.
You can build targets individually:
bazel test lib/hello:Hello bazel test lib/goodbye:Goodbye
For more information on targets, see Building one target and Building multiple targets.
You’ll see some messages the first time you build, while the extension configures a local opam switch; for example:
Fetching module extension @@tools_opam+//extensions:opam.bzl%opam; Building @tools_opam//extensions/config Fetching ... @@tools_opam+//extensions:opam.bzl%opam; Creating local switch for compiler 5.3.0 at /path/to/obazl_hello 54s Fetching module extension @@tools_opam+//extensions:opam.bzl%opam; Installing pkg ounit2 (1 of 1) 15s
By default, OBazl will create a new switch in your XDG_DATA_HOME
directory (default: $HOME/.local/share
) and install your
dependencies (in this demo, just ounit2
). This takes a relatively
long time, but it should only happen once. You also have the option of
using a global or local switch; see MODULE.bazel in
this demo, and see
tools_opam for more
information and instructions on how to use them.
To see the commands generated, add --subcommands=pretty_print
, or
put the following in your bazelrc file:
build:showpp --subcommands=pretty_print
Then you can pass --config=showpp
. Alternatively, run:
$ bazel aquery //<pkg>:<tgt>
E.g. $ bazel aquery //lib/hello:Hello
This will show you the command
line Bazel constructs, without actually running it.
Bazel also logs all commands. To print the location of the log file:
bazel info command_log
. The command log is overwritten by each
succeeding command (including bazel info
), so you need to store the
path somehow. A simple way to do that is to create a shell alias; see
tools/source.me as an example.
The standard OCaml distribution comes with four basic compilers
(ocamlopt.opt
, ocamlc.byte
, ocamlopt.byte
, and
ocamlc.opt
) plus a profiling frontend (ocamlcp
). Furthermore,
the compilers may be configured in a variety of ways: with a
debug-runtime
, or the flambda optimizer, and so forth.
The OBazl rules (rules_ocaml
) support the four basic compilers out
of the box. You can choose one by passing
--@rules_ocaml//toolchain=<tc>
, where <tc>
is one of
ocamlopt.opt
, ocamlopt
(=ocamlopt.opt
), ocamlc.opt
, ocamlc
(=ocamlc.opt
), ocamlc.byte
, and ocamlopt.byte
. For
example,
$ bazel test test --@rules_ocaml//toolchain=ocamlc
You can shorten this by defining a flag alias. Put this in a bazelrc file (see .bazelrc)
common --flag_alias=tc=@rules_ocaml//toolchain
Then you can run:
$ bazel test test --tc=ocamlc
By default, Bazel reads a variety of bazelrc
files, such as
$HOME/.bazelrc
and <projroot>/.bazelrc
. (See
Write bazelrc configuration
files for more information.) This may induce a dependency on the
local system, so to prepare a project for release you need to build
and test everything without depending on such files. That is the
purpose of such start-up options as --nohome_rc
,
--nosystem_rc
, etc. (Run $ bazel startup_options help
to see a
list of all startup options.)
As an example of one way to do this, see tools/release_build and tools/release_test.