# Learning OCaml - a few tooling questions

**URL:** <https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849>\
**Category:** Learning\
**Tags:** opam, dune\
**Created:** [April 1, 2023, 12:26am UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849 "2023-04-01T00:26:20Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![toriblk](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/toriblk/32/6503_2.png) [@toriblk](https://discuss.ocaml.org/u/toriblk)\
**Post date:** [April 1, 2023, 12:26am UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849/1 "2023-04-01T00:26:20Z")

</div>

I’ve created a new dune project (with `dune init project <proj_name>`) for the sake of solving all learning exercises with the hoped-for comfort of automated build system. So far I had no need to tinker with initial dune-project settings, only manual interventions in respective dune files for executable, lib and test.

Now I’d like to play with some 3rd party libraries, so I  
ve added manually a new dependency like `tsdl` in `dune-project` file at project’s root, expecting particular `<package_name>.opam` will be re-generated to reflect the changes, while meeting criteria by [opam Integration — Dune documentation](https://dune.readthedocs.io/en/stable/opam.html#generating-opam-files) . Unfortunately this is not the case, `.opam` remains untouched, ie. out of sync with dune-project changes, after `dune build`. After an hour reading man-pages for dune and readthedocs documentation, I’ve found no answer how to keep opam in sync. Out of despair I’ve deleted the `.opam` and `dune build` finally generated an updated version. Like, really?

Now straight to questions:

- what is the correct way to keep in sync dune-project and project.opam files?
- what is the correct/idiomatic way to add/remove project’s dependencies?
- is there a more idiomatic way to install dependencies then googled-out `opam install . --deps-only` trick?
- is there or is planned an option to install dependencies not globally but per-project?
- what are motives to not keep and manage all declarations, recipes and options in a single place like `dune-project` file but scatter them around the whole project tree and in different formats?

---

<div class="post-metadata">

**Author:** ![beajeanm](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/beajeanm/32/189_2.png) [@beajeanm](https://discuss.ocaml.org/u/beajeanm)\
**Post date:** [April 1, 2023, 12:51am UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849/2 "2023-04-01T00:51:27Z")

</div>

> [@toriblk](#):
>
> what is the correct way to keep in sync dune-project and project.opam files?

Not sure what happened with your project, but it seems to me you describe the recommanded way of doing it. That’s what I do, and I don’t have to delete the .opam file. If it happens again, maybe posting a repo with the problematic dune-project/opam file would help us to undertand?

> is there or is planned an option to install dependencies not globally but per-project?

Local switches are the solution here: [opam - new opam features: local switches](https://opam.ocaml.org/blog/opam-local-switches/)

> - what is the correct/idiomatic way to add/remove project’s dependencies?
> - is there a more idiomatic way to install dependencies then googled-out `opam install . --deps-only` trick?

I think you already found something close to the current optimal solution.

> what are motives to not keep and manage all declarations, recipes and options in a single place like `dune-project` file but scatter them around the whole project tree and in different formats?

Mostly historical, I guess if ocaml tooling was created today it would have a single tool for packaging and building ocaml code.  
But OCaml had (and still has) a lot of different build tools used by different people, opam took the view of being build tool agnostic so the whole community was able to switch to it.  
Dune generating the opam file automatically is an (good in my opinion) attempt to bridge that gap, but it doesn’t remove the need of an .opam file of the usage of the opam command.

Tooling in ocaml is still evolving, maybe you would be interested in [Drom](https://ocamlpro.github.io/drom) which tries to unify dune and opam a bit more and give a cargo like experience.

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [April 1, 2023, 12:58am UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849/3 "2023-04-01T00:58:09Z")

</div>

> [@toriblk](#):
>
> added manually a new dependency like `tsdl` in `dune-project` file at project’s root, expecting particular `<package_name>.opam` will be re-generated to reflect the changes,

I don’t understand what this means. Can you explain further what you expected to happen? What specific package are you referring to when you say `<package_name>.opam`? What is the contents of your `dune-project` file?

By the way, I agree with you that these build configs are needlessly complicated and should be simplified.

---

<div class="post-metadata">

**Author:** ![toriblk](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/toriblk/32/6503_2.png) [@toriblk](https://discuss.ocaml.org/u/toriblk)\
**Post date:** [April 1, 2023, 2:39am UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849/4 "2023-04-01T02:39:34Z")

</div>

From `dune-project`

```auto
(lang dune 3.7)
(name playground)
(generate_opam_files true)
(package
 (name playground)
 (depends ocaml dune tsdl)
                     ^^^ here added a new dependency

```

From `playground.opam`

```auto
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
depends: [
  "ocaml"
  "dune" {>= "3.7"}
  "odoc" {with-doc}
]
build: [
  ["dune" "subst"] {dev}
  [
    "dune"
    "build"
    "-p"
    name
    "-j"
    jobs
    "@install"
    "@runtest" {with-test}
    "@doc" {with-doc}
  ]
]

```

See no `tsdl` between .opam file dependencies.

Attempt to invoke `dune build` or `dune build @install` to update .opam file, as a side-effect, but it was not changed. No errors. Not found in documentation other dune’s command how to achieve this synchronization.

E: fixed formatting

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [April 1, 2023, 3:24am UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849/5 "2023-04-01T03:24:14Z")

</div>

Did you also add the library dependency to your `dune` file and try using it in your application?

---

<div class="post-metadata">

**Author:** ![toriblk](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/toriblk/32/6503_2.png) [@toriblk](https://discuss.ocaml.org/u/toriblk)\
**Post date:** [April 1, 2023, 9:00am UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849/6 "2023-04-01T09:00:02Z")

</div>

Why it should matter? I’ve placed `open Tsdl` in bin/main.ml and got _Unbound module_ error.

Now when I try to replay the case, playground.opam got suddenly updated without its removal. I’ve uninstalled tsdl and other dependencies, removed tsdl from playground.opam, bin/dune and bin/main.ml and `dune build` now surprisingly put the dependency back in .opam file. Weird.

---

<div class="post-metadata">

**Author:** ![toriblk](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/toriblk/32/6503_2.png) [@toriblk](https://discuss.ocaml.org/u/toriblk)\
**Post date:** [April 1, 2023, 9:21am UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849/7 "2023-04-01T09:21:17Z")

</div>

Oh, I have forgot to thank you for a comprehensive answer.

It _“somehow”_ did fixed itself, at least the dune\<=\>opam sync issue. Maybe opam’s database or some package was updated/upgraded in-between.

---

<div class="post-metadata">

**Author:** ![Frederic\_Loyer](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/frederic_loyer/32/3472_2.png) [@Frederic\_Loyer](https://discuss.ocaml.org/u/Frederic_Loyer)\
**Post date:** [April 1, 2023, 11:06am UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849/8 "2023-04-01T11:06:04Z")

</div>

I guess that if you need an extra library, you should change the `dune` file with:

```auto
(libraries ...)

```

where the … are replaced by the list of libraries you use.

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [April 1, 2023, 2:03pm UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849/9 "2023-04-01T14:03:44Z")

</div>

> [@toriblk](#):
>
> Why it should matter?

That’s how dune works. It needs the library dependencies specified in the `dune` files.

---

<div class="post-metadata">

**Author:** ![girzel](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/girzel/32/4349_2.png) [@girzel](https://discuss.ocaml.org/u/girzel)\
**Post date:** [April 1, 2023, 4:20pm UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849/10 "2023-04-01T16:20:46Z")

</div>

> [@yawaramin](#):
>
> That’s how dune works. It needs the library dependencies specified in the `dune` files.

I’m following along here because I went through this exact same thing a few weeks ago, and I still don’t really get it. What I ended up doing was:

1. dune install \<new\_pkg\>
2. opam install \<new\_pkg\>
3. opam lock
4. [add new pkg to lib/dune, write code using pkg, commit and push]
5. [pull updates on different machine]
6. opam install . --locked

This seems dumb, but it works. I am highly motivated to _not_ have merlin yell at me about unbound modules.

I understand that dune install can add a new package to my top-level project opam file, but then I’m not sure what the “right” opam command to run after that is; meanwhile “opam install \<the\_same\_package\_over\_again\>” is easy to remember and seems to do exactly what I need.

It was very surprising not to be able to find clear guidance on this anywhere. A simple six-bullet-point list like the one above is all I would have needed. I don’t even care what the details are, just tell me what to do!

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [April 1, 2023, 11:26pm UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849/11 "2023-04-01T23:26:39Z")

</div>

Yeah, the problem is that opam and dune try to claim they are covering different parts of the developer toolchain to provide flexibility, but in reality package management and build management have quite a lot of overlap, which makes for many sharp edges at the interaction points between the two.

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [April 1, 2023, 11:51pm UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849/12 "2023-04-01T23:51:17Z")

</div>

> [@yawaramin](#):
>
> but in reality package management and build management have quite a lot of overlap

I don’t think they overlap, but one definitively has the knowledge to drive the other to setup the build environment.

---

<div class="post-metadata">

**Author:** ![girzel](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/girzel/32/4349_2.png) [@girzel](https://discuss.ocaml.org/u/girzel)\
**Post date:** [April 2, 2023, 12:19am UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849/13 "2023-04-02T00:19:42Z")

</div>

> [@dbuenzli](#):
>
> I don’t think they overlap, but one definitively has the knowledge to drive the other to setup the build environment.

In my silly recipe above, should I/could I be doing anything differently?

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [April 2, 2023, 6:05pm UTC](https://discuss.ocaml.org/t/learning-ocaml-a-few-tooling-questions/11849/14 "2023-04-02T18:05:23Z")

</div>

There’s technically not an overlap from the perspective of the two tools doing different tasks, but there is an overlap from the perspective of the user having to give similar information to both the tools separately. As you said, one should drive the other. To that end, I think it would be helpful for dune to infer library dependencies and get them through opam: [Automatically add opam dependencies to dune-project file · Issue #7449 · ocaml/dune · GitHub](https://github.com/ocaml/dune/issues/7449)

Basically, dune should treat opam as a service (OpaaS?) to get the build dependencies it needs.
