Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/tutorials/dune-package-management/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ setup
dependencies
pinning
repos
oxcaml
:::
116 changes: 116 additions & 0 deletions doc/tutorials/dune-package-management/oxcaml.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Setting up an OxCaml project

As an example of how to add custom repositories and pin dependencies in projects
using Dune Package Management, let's look at setting up a basic OxCaml project.
[OxCaml](https://oxcaml.org/) is a compiler branch with fast moving set of
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would put the link on the mention of OxCaml just before.

extensions to OCaml. Some tweaks are required to set up a project that compiles
with OxCaml when using dune package management.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick but we should be consistent about how we capitalize Dune (and Dune package management).


## Setting up the `dune-workspace`

OxCaml has a custom `opam-repository` that provides compatible dependencies.
This is specified in the `dune-workspace`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds like the opam repository is configured in dune-workspace. I would probably say something like: Dune can use packages from this repositories by configuring it in the dune-workspace file using the repository (link) and lock_dir (link) stanzas.


```{code-block} dune
(lang dune 3.20)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make this 3.21


(pkg enabled)

(repository
(name oxcaml)
(url git+https://github.com/oxcaml/opam-repository))

(lock_dir
(repositories overlay oxcaml upstream))
```

In the `dune-project`, we also need to add a constraint to depend on the OxCaml
compiler. Otherwise, the solver may pick up the latest upstream compiler, which
does not support the OxCaml extensions.
Comment on lines +27 to +29
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"We would like dune to pick the oxcaml compiler rather than the latest upstream one. This can be achieved by manually adding a constraint on the compiler that is picked in the package stanza (link) in the dune-project.


```{code-block} dune
(lang dune 3.20)

(package
(name hello-oxcaml)
(depends
(ocaml-variants
(= 5.2.0+ox))))
```

Let's add a test program that uses OxCaml syntax.

::::{dropdown} `main.ml`
:icon: file-code

:::{literalinclude} oxcaml/main.ml
:language: dune
:::

::::

And to build it, we add a `dune` file.

```{code-block} dune
(executable
(public_name main))
```

## Building the project

As usual, let's build the project with:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not assume users are used to the usual way of doing things here. Let's instead say, we can now build and execute our binary compiled with OxCaml. We use the dune exec command which will first build all the packages we need, including the OxCaml compiler and then builds our binary and runs it.

You should probably mention the passage of time here, since this step takes a while and dune atm doesn't give too much feedback.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Unfortunately at the moment the compilation of OxCaml is glacial, partly because of limited concurrency but possibly also due to flambda being enabled. The former we can fix with #12737, the latter is outside of our control.


```
$ dune exec ./main.exe
...
43
```
We have successfully built the project with the OxCaml compiler and run the executable.

## Developer tools

Note that OxCaml provides its own forks of the developer tools
`ocaml-lsp-server`, `ocamlformat`, etc. Make sure to include constraints for the
tools in the `dune-workspace` if you intend to use them for your development
workflows.

For `ocamlformat` it would look something like this:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should add a warning that this configuration is likely to change in the future as our method for achieving this settles. Especially once the patches themselves are upstreamed. I think some prose explaining and linking the stanzas would also be a good idea.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be nice to document configuring dev-tools in general as part of #12756, then the resulting document could be linked here.


```{code-block} dune

(lang dune 3.20)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lang 3.21


(pkg enabled)

(repository
(name oxcaml)
(url "git+https://github.com/oxcaml/opam-repository"))

(pin
(name ocamlbuild)
(url "git+https://github.com/Sudha247/ocamlbuild#oxcaml+dune")
(package
(name ocamlbuild)
(version 0.15.0+ox)))

(pin
(name odoc-parser)
(url "git+https://github.com/Sudha247/odoc#replace-symlinks")
(package
(name odoc-parser)
(version 3.1.0+ox)))

(lock_dir
(path "dune.lock")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This path is probably optional.

(repositories :standard oxcaml))

(lock_dir
(path "dev-tools.locks/ocamlformat")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This path needs to be adjusted now that #12671 is merged, it should be "_build/.dev-tools.locks/ocamlformat"

(pins ocamlbuild)
(constraints
(ocaml-lsp-server (= 1.19.0+ox))
(ocaml-variants (= 5.2.0+ox)))
(repositories overlay oxcaml upstream))
```

Observe that this includes pins to dependencies `ocamlbuild` and `odoc-parser` as they are required by the OxCaml version of `ocamlformat`.
6 changes: 6 additions & 0 deletions doc/tutorials/dune-package-management/oxcaml/main.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
let () =
(* The `local_` keyword requires OxCaml *)
let local_ i = 42 in
let j = i + 1 in
print_endline (Printf.sprintf "%d" j)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
print_endline (Printf.sprintf "%d" j)
Printf.printf "%d\n" j


Copy link
Collaborator

@Leonidas-from-XIV Leonidas-from-XIV Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some newline issue here.

Loading