# How to install Sail using opam

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](https://opam.ocaml.org/doc/Install.html).
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 5.2 or newer, that's fine (older versions may still work), otherwise you can use `opam switch` to install a newer version:
```
opam switch create 5.4.1
```
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](https://brew.sh/):
```
xcode-select --install # if you haven't already
brew install gmp z3 pkgconf
```
Finally, install sail from the opam package [https://opam.ocaml.org/packages/sail/](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.

### Note for WSL (Windows subsystem for Linux) users

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.

### Installing development versions of Sail

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
cd sail
opam pin add .
```
will install from a local checkout of the Sail sources.

You can update with new changes as they are committed by pulling and reinstalling in the `sail` directory:
```
git pull
opam reinstall .
```

To remove the pin and revert to the latest released opam package type in the `sail` directory:
```
opam pin remove .
```

### Building from source (without opam)

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
```

### Some opam information

For full information see the
[opam documentation here](https://opam.ocaml.org/doc/Usage.html). 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](https://opam.ocaml.org/doc/Usage.html#opam-pin).
