How to specify requirements for versions of dependencies for ocaml dune projects? - ocaml

Say I run dune init proj hello_world, then modify the bin/dune and bin/main.ml files so that a new dependency foobar is in use.
The bin/dune file now:
(executable
(public_name hello_world)
(name main)
(libraries hello_world foobar))
1. How can I specify that the foobar library should have a certain exact version?
2. If we know that the foobar library uses semantic versioning, how could I specify that any version with the major version as 3 is required?
ocaml version 4.14.0
dune version 3.6.1

Package dependencies for a project are specified in the dune-project file, see https://dune.readthedocs.io/en/stable/dune-files.html#package
A default dune-project file is generated by dune init proj ....
You will and with a line in the depends field like
(depends
(foobar (>= 3))
Note that this is needed in addition to specifying which libraries the executable depends on.

Related

Using an executable as library in dune

I'm building a project using dune and I'm facing the following situation. Essentially, my project depends on another project, not developed by me, from which I want to use some parts of the source code.
Here is more or less my project tree
my_project/
|---dune-project
|---src/
|---dune
|---extrenal-project/
|---dune-project
|---dune
|---src/
|---dune
|---src-file.ml
The problem is that external-project has a dune file that builds it as an executable, instead of a library. Therefore, I cannot include it as a library in my dune file. Ideally, I don't want to modify the dune file inside of external-project.
I've tried a series of combinations. Here is the current status of my dune file:
(dirs external-project)
(executable
(name myexec)
(libraries containers)
(modules Myexec)
(promote (until-clean) (into ".."))
)
(env (dev (flags (:standard -warn-error -A))))
Which allows me to compile external-project correctly, but then does not allow me to reference any of its files. I also tried (dirs external-project external-project/src) but to no success.
So, my question is: is there a way for me to reference external-project as a library, even though it is build as an executable?
Thanks for your help!

Building "hello world" with ocaml dune

Following the tutorial at https://dune.readthedocs.io/en/stable/quick-start.html, I created a file hello_world.ml containing
print_endline "Hello, world!"
and a file dune containing
(executable
(name hello_world))
and then typed
dune build hello_world.exe
but it complains about errors in other (completely unrelated) files.
Is it possible that dune looks at other files even though they are not mentioned in the dune file (even recursively) ? And how to prevent it ?
Yes, dune will search for all files that have *.ml or *.re files in the current folder. To disable this behavior use the modules stanza and explicitly specify which modules comprise your executable. For example, if it is made of hello_world.ml and utilities.ml compilation units, then the following specification will work for you,
(executable
(name hello_world)
(modules hello_world utilities))

generating OCaml documentation with dune

I'm in an internal package of my project and I ran dune build #doc. It does not complain and runs to completion. I then check the /_build/default directory and no _doc directory exists.
Am I missing something?
You should simply be able to generate docs by running dune build #doc if you have foo.ml, foo.opam, and a dune file containing simple contents. For example,
(library
(name foo))
To answer the question, the package name should be related to the library name or public name (if added as a stanza to the dune file).

Dune: build library and access it in another project and hide or make inaccessible private or implementation modules

I am using Dune for building OCaml projects and I'd like to build a standalone library for reusing it in other projects.
The root folder of the library is mylib and the library was initialized with dune init lib mylib src (after cd mylib).
The directory tree of mylib, the root of the project, is the following:
mylib
+---dune-project
│
+---src
dune
priv.ml
mymodule.ml
mymodule.mli
Here follows the content of the files.
mylib/dune-project:
(lang dune 2.7)
mylib/src/dune:
(library
(name mylib))
mylib/src/priv.ml:
let rec loop a accu i =
let n = Array.length a in
if i = n then
accu
else
loop a (accu + Array.unsafe_get a i) (succ i)
mylib/src/mymodule.mli:
val sum : int array -> int
mylib/src/mymodule.ml:
let sum a =
Priv.loop a 0 0
After giving context and showing the content of each file of this toy example, the question follows:
How can I build the library mylib and use it in another, separate project?
(For example, in another project, I'd consume the library with the following:
Open Mylib
let () =
print_int (Mymodule.sum [1;2;3])
OR
let () =
print_int (Mylib.Mymodule.sum [1;2;3])
)
With Dune, given the executable main, you would write the following dune file to use library mylib if it was published on Opam.
dune:
(executable
(name main)
(libraries mylib))
After successfully building the library and linking it in another project, how can I hide or not expose some modules? For example, given the toy library of before, mylib, I would like to not expose and make inaccessible the module Priv (such that Priv would only be usable inside modules of mylib - like a protected/internal class in Java/C#).
​
I tried searching on Real World OCaml, Cornell CS3110 textbook, Dune documentation, OCaml Learn but, unless deeply nested, I found nothing.
Thank you very much for your help, if I didn't explain something in a clear way, please ask and I will try to explain better.
In the root directory, these should be a file called mylib.opam with content similar to this one. Then, the (public_name mylib) s-expression should be added to library in mylib/src/dune. Finally, making sure to be in the root of the project, the library shall be built with dune build and installed with opam install ..
For actually using the library in another project, even in a different dune workspace, all it's needed is to add (libraries mylib) to the dune file of project that will use the library.
The (private_modules priv) s-expression should be added to library in mylib/src/dune. Then, mylib.ml needs to be created with the following content: module Mymodule = Mymodule: this will make sure that only Mymodule will be exposed under the package Mylib.

OCaml - Is it possible to define external (system) dependencies in dune?

I made an OCaml library that relies on an external/system package (namely libnauty2-dev).
Since I would like my library to be installed via opam I looked for a way to specify the external lib as a dependency.
So far I have found that .opam files can specify such dependencies with
depexts: [ "libnauty2" ]
And here is my question:
Is there a way to specify my dependency in a dune-project file so that generated .opam file will contain the same dependency ?
The dune language doesn't directly support this part of opam file generation, but you can create a <packagename>.opam.template file with your depexts rules and dune will paste the contents of that file at the end of the generated .opam file.