ocaml_module(name = "Module1", struct = "module1.ml")
OCaml Modules Last updated May 4, 2022
Bazel also has modules, which must not be confused with OCaml modules. Bazel modules were introduced after work on OBazl version 2 was well underway so they are not used. The next version will use Bazel modules. |
OCaml Modules
An OCaml module is a composite formed by pairing a [signature](#signatures) and a [structure](#structures).
Orphans and Dyads
In OBazl terminology, an orphan module is one whose signature is
inferred from its structure. For example, a module explicitly defined
within a file module M = struct …end
counts as an orphan module.
Similarly, a structfile without a matching sigfile is termed an
orphaned structfile, from which an orphan module may be compiled.
A module built from a paired structure and an explicit signature is
called a dyadic module. For example, definitions of the following
form define a dyadic module: module M : sig … end = struct …
end
. A structfile and a sigfile with the same principal name
(filename excluding extension, normalized as a module name) together
determine a dyadic file-system module.
There is no substantive difference between an orphan module and a dyadic module. The terms are intended for convenience, solely to capture the the two ways that module code can be organized. |
Compilation
Compilation of module files always involves separate
compilation of interface and implementation; but as a convenience, the
OCaml compilers support compilation of stand-alone implementation
files. An implicit interface can always be inferred from any
implementation file; when passed a .ml file without a corresponding
interface, the compilers will extract the implicity defined interface and
compile it separately before proceding with the implementation
compile. The output of such a compile will thus include a .cmi file
in addition to the .cm[ox] output.
|
Compiling modules - that is, compiling and then binding their interface and implementation files - is straightforward with OBazl. A stand-alone implementation:
With both parts:
ocaml_signature(name = "Module1_cmi", src = "module1.mli")
ocaml_module(name = "Module1", struct = "module1.ml", sig=":Module1_cmi")
In this example, the sig
attribute makes the ocaml_signature
target a dependency of the ocaml_module
target, which ensures that
it will be compiled first, producing module1.cmi
. The ocaml_module
target will use that .cmi
file to govern compilation of module.ml
-
in effect creating a "module binding" of interface to implementation;
its output will include the compiled implementation file(s) (either
module1.cmo
or the pair module1.cmx
and module1.o
for native
compilation) plus the .cmi
file.
This design affords great flexibility in module construction. In
particular, it makes it easy to configure module bindings based on
user-defined constraints. A typical use case is the need to select a
platform-specific implementation file for binding to a
platform-independent interface file. No special features or concepts
(e.g. "virtual library") are needed for this; the built-in select
function suffices. Here is an example based on code in the OCaml
compiler sources (with some detail omitted):
ocaml_signature(
name = "Proc_cmi",
src = "proc.mli"
)
ocaml_module(
name = "Proc",
struct = select({
"//config/arch:x86_64": "//asmcomp/amd64:proc.ml",
... etc. ...
"//config/arch:s390x" : "//asmcomp/s390x:proc.ml",
}, no_match_error = "unknown arch"),
sig = "Proc_cmi"
)
The selection constraints are defined in a separate file:
config_setting(name = "x86_64",
constraint_values = ["@platforms//cpu:x86_64"])
... other conf_setting targets omitted ...
config_setting(name = "s390x",
constraint_values = ["@platforms//cpu:s390x"])
In this example, the implementation file will be selected based on the
platform (e.g. @platforms//cpu:x86_64
); the ocaml_module
rule will
ensure that the selected file will be compiled using proc.cmi
as its
interface.
-
[Overview](#overview) module binding
sec 2
ocaml_signature(name = "Hello_cmi", src = "hello.mli")
ocaml_module(name = "Hello", struct = "hello.ml", sig = ":Hello_cmi")
sec 3
Module types
Module Type Definitions (Cornell book)
Bazel Modules
Expected for version 3
test images