- Tuareg mode
- Setting up and developing a project
- Additional reading
- Example project
Note: OCaml is installed on the Linuxlab cluster.
Finding the right mix of tools to edit, compile, and debug programming
projects can be a frustrating challenge. I’m going to discuss the
setup I use and recommend for developing with OCaml.
Within the past few years, OCaml has become an especially appealing
language for functional programming because of its growing tooling
support. Its predecessor,
Standard ML, was a well
designed and useful research language, but developing large projects in
it was troublesome because there wasn’t a set of standard tools and
libraries within the community (e.g., SML/NJ
provided its own build system, mosml and
MLton were two separate optimizing compilers).
Additionally, the user community was relatively small and it lacked
the support of libraries and packages that have become essential
components of other communities.
However, with a larger open source community and more commercial
Jane Street Capital), OCaml
has acquired a mature set of tools to ease development.
The foundations of my toolchain are:
package manager, for managing different versions of OCaml and
associated sets of packages.
ocamlbuild) for compiling OCaml projects and greatly
taureg-modeas a mode for emacs, and associated mode for vim.
Merlin, which turns emacs and vim into tools closer to IDEs for
this git repo and
OPAM is a package manager for OCaml, similar to RVM.
It allows us to maintain multiple versions of OCaml compilers, along
with packages that work with them. It includes a large set of
libraries and makes them easy to install.
Installation instructions for OPAM can be found
here. OPAM supports many
package management systems, so you should be able to install it via
brew, or whichever you use. If you’re using a Mac, I
recommand using the Homebrew management system.
There are also options for MacPorts as well. If you’re not using
either of these systems, I’d recommend installing Homebrew first, but
there are other options listed on OPAM’s install page (including
installing from source). I agree that it’s a pain to install a
package manager to install another package manager, but it gets better
once its installed!
Once you’re up and running you should be able to use the command
init, which will initialize your opam installation.
This page gives some basic
uses for OPAM, but the big ones are:
opam switchfor switching between versions. I usually switch
into the main version I use and do all of my development with
that. The only real reason to switch between versions is if you
depend on a feature that exists in a certain version of OCaml.
You will rarely run into this unless you use very cutting edge
features of the type system.
The output of
opam switchwill list a set of compilers available
system I system System compiler (4.00.1) 4.03.0+trunk I 4.03.0+trunk latest trunk snapshot 4.02.1 C 4.02.1 Official 4.02.1 release 4.01.0 I 4.01.0 Official 4.01.0 release -- -- 3.11.2 Official 3.11.2 release -- -- 3.12.1 Official 3.12.1 release -- -- 4.00.0 Official 4.00.0 release -- -- 4.00.1 Official 4.00.1 release -- -- 4.02.0 Official 4.02.0 release
With your current one listed. You can switch to another compiler
(and the set of packages you’ve installed for it) by specifying
the version after the switch. Note that you’ll have to run
eval `opam config env`
After switching. This updates your environment variables so that
commands such as
ocamlopt(the compiler) point at
the versions you intend to use.
opam listlists the set of packages you have installed.
opam installallows you to install a package. As an example, if
I wanted to use Jane Street’s
corelibrary (which provides a
large set of utilities extending the standard library and useful
for day to day programming) I would do
Kristophers-MacBook-Pro-2:~ micinski$ opam install core The following actions will be performed: - install comparelib.109.60.00 [required by core] ... core_kernel.112.17.00 [required by core] - install core.112.17.00 === 14 to install === Do you want to continue ? [Y/n]
And then type
coreis very large and has a lot of
dependencies. OPAM grabs all of these and installs them. (For me
it took three minutes.)
I have a lot of luck with OPAM. No package management system is
perfect, but there are few times where packages fail to install. If
they do I usually look at the log files it leaves, and then ask for
help on a mailing list.
CMSC330, we will try to use a minimal amount of external
packages. So don’t worry too much if you are having trouble with
OPAM. It does help, however, in making sure that the ocaml compiler
you’re using matches the one on the submit server.
For the class, I suggest installing OPAM as a way to install OCaml.
is a build manager for OCaml. It should be bundled with your OCaml
installation. It provides a fairly pushbutton way to build OCaml
projects. I personally find the user manual confusing and hard to
read, so I’ll reiterate the main things you need to know:
To compile a file, type
ocamlbuild file.native. The
extension builds native code using the optimizing compiler
ocamlopt. You can also build bytecode versions.
To use packages and set up special parameters, you modify the
_tagsfile in your project’s directory. The
specifies package names, preprocessor options, etc…
Things get a little more complicated when you need to have a more
involved build process (e.g., linking to external libraries). In
these cases you can use OCamlBuild’s
--helpto figure out the
right options, or read through the documentation.
ocamlbuildwith the right parameters so
you can simply type
makein your project’s directory as
necessary (instead of remembering all of the options you need to
pass). You can also write separate Make targets for tests,
I’ve included an example use of OCamlBuild (and the
along with a Makefile which drives it, in the sample project below.
For CMSC 330, you won’t have to design build infrastructure: we will
provide boilerplate for each project. However, understanding how the
build process works may help demystify what’s going on.
Tuareg mode provides nice highlighting for emacs. Emacs modes
(libraries that extend emacs with extra behavior) are written in
[emacs lisp], a variant of the LISP family of programming
languages. Installing modes is fairly simple: you put them in a
directory (typically a subdirectory of
~/.emacs.d/) and modify your
~/.emacs file to point at the files.
Merlin provides two
features for developing OCaml that I find particularly helpful:
Intelligent type based completion
Error highlighting and feedback within an emacs buffer
Previously, my interaction method for working with OCaml was to write
some code, save all my files, run
make, and find syntax errors.
This worked well enough, but it required a back-and-forth process for
getting rid of trivial (mostly syntax related) errors. Instead,
Merlin allows you to see errors as you type: it will underline and
highlight them in red every time you save. There are still some
errors it will miss (relating to problems involving multiple files or
modules), but I find it saves me a lot of time.
The Github page lists instructions for installing Merlin, but I
installed it via
opam. You should be able to run
merlin. The installation will tell you how to modify your
file to set up merlin appropriately.
Note that to use Merlin, you need to tell it where your OCaml source
files are installed, along with what packages (libraries) you are
using. This will help it resolve references from other files. This
is easily specified in a
.merlin file with a set commands that is
simple to use. I’m sure there are cases where it might not work
perfectly, but I have not run into them yet.
Merlin has a few key combinations that it adds to emacs, but I find
the most helpful one (and the only real one I use) is
C-c C-x, which
jumps to the next error. There are also a few others relating to
completion, updating, etc… You can read about these in the
documentation. Merlin also has a very nice type sensitive code
completion facility (similar to IntelliSense) that may be worth the
time to set it up, if you so choose. For our projects in CMSC330, it
might be overkill: don’t stress about setting up your emacs
configuration if it is complicated.
make in emacs
If you’re using emacs, I suggest running
make from within emacs so
that errors can be cross referenced directly from within emacs (rather
than having to switch tabs, write down the line number, and go back
and forth looking for errors).
To run make from within
emacs, you can use the command
compile. Note that you’ll have to (or at least, I have to) switch
to the base directory to your project’s home. I simply set the
compile command to
cd /path/to/project; make, but this can
easily be customized
Setting up and developing a project
My typical workflow for developing projects is the following:
Make a new directory for the project.
Initialize a git repository within that directory and make an
initial commit (along with a
Set up a default
main.mlfile and put a function that does nothing
inside of it.
Set up a
ocamlbuildfor the binary (or
Set up a
.merlinfile that includes the set of places where my
code is and what libraries I’m using.
Now, when I want to edit my project I use emacs and use the Merlin
keybindings. When I want to test my project and compile / run it, I
do so by going to a new terminal running
make, and then running
main.native with the necessary parameters (or perhaps via a script).
is well written and should help fill any holes here.
I have set up
this example project
on Github that highlights the use of OCamlBuild, make, and Merlin.
For the projects in our class, I have given them boilerplate-structure
to work with Merlin. Let me know if projects aren’t working for you
and I will modify them as necessary.