First, install opam (the OCaml package manager) if you haven't
already. You can use your system's package manager e.g.
sudo apt-get install opam
(on Ubuntu 20.04) or follow the
instructions from the opam website.
The opam version must be >= 2.0; opam 1 versions are no longer
supported. On older Ubuntu versions such as 18.04 you will not be able
to use opam from the package manager, and will need to install it
following the instructions on the opam website.
Use ocaml -version
to check your OCaml version. If you have OCaml 4.08.1 or newer, that's fine, otherwise you can use opam switch
to install a newer version:
opam switch create 5.1.0
and set up the environment for that OCaml version (note that older versions of opam suggest backticks instead of $(...)
, but it makes no difference):
eval $(opam config env)
Install system dependencies, on Ubuntu (if using WSL see the note below):
sudo apt-get install build-essential libgmp-dev z3 pkg-config
or MacOS homebrew:
xcode-select --install # if you haven't already
brew install gmp z3 pkg-config
Finally, install sail from the opam package https://opam.ocaml.org/packages/sail/ and its dependencies:
opam install sail
If all goes well then you'll have sail in your path:
which sail
sail --help
Some source files that sail uses are found at opam config var sail:share
(e.g. for $include <foo.sail>
) but sail should find those when it needs them.
The version of z3 that ships in the ubuntu repositories can be quite old, and we've had reports that this can cause issues when using Sail on WSL. On WSL we recommend downloading a recent z3 release from https://github.com/Z3Prover/z3/releases rather than installing it via apt-get.
Released Sail packages lag behind the latest development in the repository. If you find you need a recently added feature or bug fix you can use opam pin to install the latest version of Sail from the repository. Assuming you have previously followed the above instructions (required to install dependencies):
git clone https://github.com/rems-project/sail.git
opam pin add sail
will install from a local checkout of the Sail sources.
You can update with new changes as they are committed by pulling and reinstalling:
git pull
opam reinstall sail
To remove the pin and revert to the latest released opam package type:
opam pin remove sail
Note that if you are just interested in using development versions of Sail, rather than working the Sail source yourself, the above instructions using opam pin are likely better suited to your needs.
opam can be used to just install Sail's dependencies. From within the Sail root directory run:
opam install . --deps-only
Then Sail can be build manually using dune, via
dune build --release
dune install
or using the provided Makefile that calls the above commands:
make install
For full information see the opam documentation here. This section just describes the high level details of what you might need to know about opam when working with Sail coming from another language ecosystem.
For the most part opam works like a standard Linux package manager,
such as apt-get (except for OCaml programs and libraries!). opam install <package>
installs packages, opam update
fetches up-to-date
package information from the online opam repository, and opam upgrade
upgrades any installed packages.
Where opam differs from some programming language package managers
like npm
or cargo
is that packages are installed neither globally
nor on a per-project basis, instead they are installed in
switches. A switch has its own OCaml compiler version and set of
libraries and executables. Earlier in this document we created a switch
opam switch create 5.1.0
but you can create your own switch
opam switch create <name> <compiler-version>
(if the compiler version is omitted the name is used as the compiler version).
When creating a new switch, or switching between them, use eval $(opam env)
to update the current shell environment.
opam pin
is a very flexible command that allows you to override an
existing package to use a git repository directly, or force a specific
version. It is best explained by the
documentation here.