Dune, odoc and "failed to resolve reference"

Hi, I’m trying to write some documentation for a small tool (i.e. an executable) and I’m encountering an issue when trying to link a module that’s part of my tool’s library: I get the error message Failed to resolve reference unresolvedroot(mylib) Couldn't find "mylib". I’m using odoc and letting dune drive it, as suggested on odoc for authors or dune and odoc.

my source tree looks roughly like:

  • lib:
    • dune
    • mylib.ml
  • doc
    • dune
    • index.mld
  • bin
    • dune
    • main.ml

and I’m trying to have a link to some part of the documentation related to mylib in index.mld (the reference in that file is written like {!Mylib}). I tried:

  • having mylib be a package (by having a mylib.opam file in the project root)
  • running dune build @doc-private

I am a little confused, as I expected this to work without too much effort. I’m definitely doing something wrong, but I’m not sure what… any pointers greatly appreciated!

1 Like

Hello @louisono,

I’m not an expert on Dune + odoc, but here are a few checks I would suggest (note that I haven’t tried @doc-private, though I assume it behaves similarly to @doc):

Have you tried using {!module-Mylib} instead of {!Mylib}?
Depending on your setup, it may also be helpful to explicitly add the following to your doc/dune file:

(documentation
  (mld_files index))

If you have additional pages (.mld files), you can list them after index. For example, if you have an install.mld, you can link to it from index.mld like this:

{{!page-install} Installation}

That said, it’s generally good practice (from my point of view) to declare all your .mld files explicitly in doc/dune.

After adding the mld_files field to the documentation stanza, I have tried a few different combinations (for the reference) like:

  • {!module-Mylib}
  • {!/mylib/Mylib} or {!/mylib/module-Mylib} or {!/mylib/page-index}

which all yielded the same warning message. What seems really odd to me is that, all pages that I would expect are in the build directory containing odoc generated content (i.e. _build/default/_doc/_html):

  • an index.html page
  • two directories containing pages for my 2 packages (the executable and the library mylib)

In fact I can browse the html documentation with the only caveat being that this one link doesn’t work (other links work just fine). maybe something wrong happens just at the stage where odoc resolves references due to some misconfiguration with dune.

Which is the warning message? Still Failed to resolve reference unresolvedroot(mylib) Couldn’t find “mylib”?

It’s a bit difficult to understand the cause of the error without seeing your dune files. That said, one thing to check is whether you have something like:

(library
(name mylib))

This can be important so that dune/odoc can recognize that mylib refers to your library.

Notes:

  • Your mylib.opam file is probably being generated automatically each time you run dune build, based on your dune-project file (if it contains (generate_opam_files true)).
  • Is there a specific reason you are using dune build @doc-private? I don’t think that’s the cause of the issue, but it’s still worth trying dune build @doc.

Sorry, I failed to mention that I was invoking dune with dune build @doc for all the variations listed in my last message (I only tried dune build @doc-private a few times as it seemed to build the library’s documentation separately).

For the warning message, I guess I’m noticing now that it varies slightly depending on the way the reference is written in the index.mld file (for instance it becomes Failed to resolve reference unresolvedroot(Mylib) Parent_module: Lookup failure (root module): Mylib when the reference is written {!module-Mylib})

Regarding the dune configuration:

  • in the library stanza I put both fields name and public_name
  • my dune-project does have generate_opam_files true (along with 2 packages declared: one for the executable and one for the library), which lets dune take care of the .opam files. but I have also tried having a very minimal dune-project file and mere empty .opam files (as dune and odoc says the .opam files need just exist)

You can see my dune files on this repos (currently on branch “first-draft” @ commit 8e963b471889313b92c05832c92682f90312c75b)

Hello @louisono,

I didn’t check out any specific branch; I just took your main branch and added a few things to verify that everything is working.

From my side, it works fine. You can see my fork of your repository here:

https://codeberg.org/rchg/ocstatic-check

I added a library file in lib/ to “stress-test” dune-odoc a bit by defining a module that extends two default stdlib modules with additional functions, and including them in the documentation.

Everything is set up correctly, and odoc is even able to fetch the OCaml stdlib documentation and include it. Not many documentation systems can do this so smoothly.

As you will see, I also created specific .mld files for two binary tools and added the links into the index.mld (maybe this was the kind of things you were looking for?). In bin/dune, you will also find two examples of binary generation; one is set up to create statically linked binaries (although your “ocstatic” probably refers to a web static tool rather than this).

Note: if you think it solves the issue please tick as solution, so other people know that it is solved, if not solved please feel free to ask further questions. (as seems to be solved I deleted the repository indicated above)

The thing that’s going wrong in your first-draft branch is that the executable/docs and the library are in different packages. The library is in its own package called libocs and the exe and docs are both in the package ocstatic. The current dune rules aren’t terribly good at cross-package documentation, so the simplest fix here is to put them in the same package. In dune, libraries must start with the same name as the package, so you have to make the public_name of the package ocstatic (or ocstatic.lib or whatever). Then delete the rest of the references to libocs and it all works as expected.

1 Like

Thank you @jonludlam & @RChG, having the library and executable in the one and same package (instead of having two packages, one for the executable and one for the library) was the way to go. I had read somewhere that dune only generates documentation for public packages and misinterpreted that as needing a separate package for my library :sweat_smile: again, thanks a ton for your help and patience :slight_smile:

1 Like