# Instructions to augment the \`install:\` field of the \`opam\` file of a \`dune\` project

**URL:** <https://discuss.ocaml.org/t/instructions-to-augment-the-install-field-of-the-opam-file-of-a-dune-project/16955>\
**Category:** Learning\
**Tags:** cmdliner, dune\
**Created:** [July 11, 2025, 12:05am UTC](https://discuss.ocaml.org/t/instructions-to-augment-the-install-field-of-the-opam-file-of-a-dune-project/16955 "2025-07-11T00:05:26Z")\
**Posts on this page:** 9\
**Page:** 1

<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:** [July 11, 2025, 12:05am UTC](https://discuss.ocaml.org/t/instructions-to-augment-the-install-field-of-the-opam-file-of-a-dune-project/16955/1 "2025-07-11T00:05:26Z")

</div>

Hello,

Could a charitable `dune` user help me in providing off-the-shelf instructions for installing the completion scripts and manpages of a cmdliner 2.0.0 based tool that uses `dune` for building.

[Here](https://erratique.ch/software/cmdliner/doc/cookbook.html#tip_tool_support) is what the instructions look like if you were to write this directly in an `opam` file ([example](https://github.com/b0-system/odig/blob/90eb4d6bfbdb47a20ce9c8756bc4655433f2225e/opam#L34-L44) for an `ocamlbuild`-based build).

I want to provide a cookbook entry that has direct instructions for `dune` users.

Thanks.

---

<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:** [July 11, 2025, 12:26am UTC](https://discuss.ocaml.org/t/instructions-to-augment-the-install-field-of-the-opam-file-of-a-dune-project/16955/2 "2025-07-11T00:26:48Z")

</div>

Note, I’m also open to have that as direct build rules, if that remains short – despite what the advertisement says, `dune` is not a very composable build system :–)

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [July 11, 2025, 3:29am UTC](https://discuss.ocaml.org/t/instructions-to-augment-the-install-field-of-the-opam-file-of-a-dune-project/16955/3 "2025-07-11T03:29:46Z")

</div>

OPAM files generated by Dune do not contain an `install:` field by default as `.install` files are used instead. However, you can inject arbitrary fields into the generated OPAM file by putting them in a file called `$PKGNAME.opam.template` at the root of the Dune project. So something like

```auto
# dune-project
(lang dune 3.18)
(package (name mypkg))
(generate_opam_files)

# mypkg.opam.template
install: [
  "cmdliner" "install" "tool-support"
  "--sharedir=%{share}%" "--mandir=%{man}%"
  "_build/install/default/bin/thetool" "%{prefix}%"
]

```

could be a starting point (here `mypkg` is the name of the package). Note that you need to write the path to the built tool by hand (here, `_build/install/default/thetool`). (Also, you may have some issues on Windows if `cmdliner install tool-support` does not handle the `.exe` extension automatically.)

I’m assuming here that OPAM is able to work with packages that have both an `.install` file and an `install:` field in their OPAM file.

Sorry I can’t give more precise instructions, but am not really an OPAM user. cc @Alizter or @maiste who may be able to give you more details.

Cheers,  
Nicolas

---

<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:** [July 11, 2025, 7:39am UTC](https://discuss.ocaml.org/t/instructions-to-augment-the-install-field-of-the-opam-file-of-a-dune-project/16955/4 "2025-07-11T07:39:36Z")

</div>

> [@nojb](#):
>
> Note that you need to write the path to the built tool by hand (here, `_build/install/default/thetool`).

Wouldn’t that be `_build/install/default/thetool.exe` ?  
Doesn’t `dune` always add an `.exe` extension ? That’s what the page [here](https://dune.build/) proudly says.

> [@nojb](#):
>
> (Also, you may have some issues on Windows if `cmdliner install tool-support` does not handle the `.exe` extension automatically.)

[`.exe` extensions](https://github.com/dbuenzli/cmdliner/blob/0992a88fa0cc3d1d535b36f24a893c80f3c3bd79/src/tool/cmdliner_main.ml#L69) are taken into account.

---

<div class="post-metadata">

**Author:** ![mbarbin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mbarbin/32/4421_2.png) [@mbarbin](https://discuss.ocaml.org/u/mbarbin)\
**Post date:** [July 11, 2025, 7:51am UTC](https://discuss.ocaml.org/t/instructions-to-augment-the-install-field-of-the-opam-file-of-a-dune-project/16955/5 "2025-07-11T07:51:02Z")

</div>

> [@dbuenzli](#):
>
> installing the completion scripts and manpages of a cmdliner 2.0.0 based tool that uses `dune` for building

Given that the tool itself is built with dune, it would be worth looking into `dune-site` and the builtin [install](https://dune.readthedocs.io/en/stable/reference/dune/install.html) capability. You’d need to turn your generating instructions from the opam file into a dune rule to let dune know how to generate the artifacts you want install. I think this would feel more “dune-like” to a dune user (opinions?).

If you have an example repo with a dune built app candidate, I’m happy to contribute to trying to find the right dune rule magic (re: off-the-shelf). Maybe using one actual useful app that uses dune & cmdliner as an example - like we can look into creating such PR for [dune-release](https://github.com/tarides/dune-release)?

Caveat: I don’t know what the share or man and bin sections of the dune-sites mean when not using opam (e.g. dune-pkg). I haven’t tried this yet (maybe they’re just global instead of being tied to particular opam switch?)

I’m excited about the command completion feature. Thanks a lot for your work on this!

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [July 11, 2025, 8:08am UTC](https://discuss.ocaml.org/t/instructions-to-augment-the-install-field-of-the-opam-file-of-a-dune-project/16955/6 "2025-07-11T08:08:08Z")

</div>

> [@dbuenzli](#):
>
> Wouldn’t that be `_build/install/default/thetool.exe` ?  
> Doesn’t `dune` always add an `.exe` extension ? That’s what the page [here](https://dune.build/) proudly says.

Dune uses an `.exe` extension uniformly when building executables in its build directory (eg `_build/default`). This simplifies writing rules that work uniformly on Windows and Linux.

However, when _installing_ executables, Dune actually removes the `.exe` extension on Unix, to follow system conventions. In other words, you can work within the build system as if all the executables had `.exe` extensions, but when dealing with installation artifacts, `.exe` is only used on Windows.

To give a bit more detail: `_build/default/thetool.exe` refers to the artifact in the _build directory_, which is always suffixed with `.exe`. However, `_build/install/default/bin/thetool` (yes, there was a missing `bin/` in my previous message), refers to the installation artifact (which is actually copied by OPAM), and so it does not have an `.exe` extension on Unix.

Hope that clarifies things.

Cheers,  
Nicolas

---

<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:** [July 11, 2025, 8:45am UTC](https://discuss.ocaml.org/t/instructions-to-augment-the-install-field-of-the-opam-file-of-a-dune-project/16955/7 "2025-07-11T08:45:08Z")

</div>

@mbarbin if you are able to find the _magic_ I’m all for it. You can pin `cmdliner` to try things. However note that the `cmdliner` tool does not generate `opam` instructions in any way and it wouldn’t generate `dune` files either. If that is needed then I think it should be done in another project (but I’m willing to add more build-system agnostic modes in the `cmdliner` tool if that’s needed).

Meanwhile what @nojb proposes seems more tractable (to me). So if I understand well I can choose between peeking into the install directory or the build directory of `dune`.

I checked on a build of `odoc` that would be in the build dir (you then need to use the [`:NAME` renaming syntax](https://github.com/dbuenzli/cmdliner/blob/0992a88fa0cc3d1d535b36f24a893c80f3c3bd79/src/tool/cmdliner_main.ml#L348-L354))

```auto
install: [
  "cmdliner" "install" "tool-support"
  "--sharedir=%{share}%" 
  "--mandir=%{man}%"
  "_build/default/src/odoc/bin/main.exe:odoc" 
  "%{prefix}%" ]

```

But I’m a bit nervous in suggesting that. Couldn’t `dune` decide to reshuffle its build directory structure from one version to another ?

While in the install directory it would rather be:

```auto
install: [
  "cmdliner" "install" "tool-support"
  "--sharedir=%{share}%" 
  "--mandir=%{man}%"
  "_build/default/install/bin/odoc" "{os != "win32"}"
  "_build/default/install/bin/odoc.exe" "{os = "win32"}"
  "%{prefix}%" ]

```

A bit more verbose but more stable ?

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [July 11, 2025, 9:16am UTC](https://discuss.ocaml.org/t/instructions-to-augment-the-install-field-of-the-opam-file-of-a-dune-project/16955/8 "2025-07-11T09:16:20Z")

</div>

> [@dbuenzli](#):
>
> A bit more verbose but more stable ?

Yes, I would recommend going via the install directory, which is what OPAM does as well.

Cheers,  
Nicolas

---

<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:** [July 20, 2025, 4:50pm UTC](https://discuss.ocaml.org/t/instructions-to-augment-the-install-field-of-the-opam-file-of-a-dune-project/16955/9 "2025-07-20T16:50:46Z")

</div>

Just FTR, I moved to do that in the `build:` section by writing the files in the build directory and updating (or creating) the `pkg.install` file.

This avoids to use the `install:` section which I’m being told may slow down builds on Windows as with these packages the install prefix needs to be diffed to see what gets installed (and in turn seems a [bit buggy](https://github.com/ocaml/opam/issues/6574) for running byte code at the moment).

The trade off is a [hopefully not too brittle patching](https://github.com/dbuenzli/cmdliner/commit/d23d146f9f21f0f74b5194502a9e00ecf2d2a38e) of the `pkg.install` file that your build system produces. AFAIU this also means that you will have to manually write your `dune` invocation in the `build:` field.

I settled down on [these instructions](https://erratique.ch/software/cmdliner/doc/cookbook.html#tip_tool_support_with_opam_dune). I’m a bit averse to add too much details that may change in the future. If there’s a better link on the `dune` docs than the one I provided, tell me.
