I report here errors in this article as well as my discovery of dune's behaviour. And open a discussion about dune. I apologize for the EDIT due to confusion (I'm learning dune).
1/ Consistency regarding jbuilder/dune
What about modifying the text of the following command
$ opam install merlin ocp-indent dune utop
accordingly to the text that follows:
- dune, the installable library of Dune. At the point of this writing, Dune’s latest version is 1.0.1.
In the original article we can see (today):
$ opam install merlin ocp-indent dune utop
2/ Is putting .ml files in a /bin directory a practice enforced by dune and recommended for OCaml coding?
To keep things tidy, let’s move the program to a subdirectory. We will name the directory bin, a convention I use as a place to put entry point modules for executables:
I don't believe main.ml is executable code. Sure that it's can be interpreted, but it looks like source (and dune file is configuration code).
Is it a convention to put source files in bin/ when using dune?
What about using a more natural and meaningful src/ directory?
3/ dune exec is doing more that I believed: first it builds then it executes.
The following instructions work:
$ dune clean
$ dune exec bin/main.exe
Hello, world!
But it reveals that dune exec
includes dune build
.
That should certainly be a command like dune build bin/main.exe ; dune exec bin/main.exe
While in the (nicely presented) dune documentation we can find the following ambiguous assertion:
The executable can ran with: $ dune exec ./hello_world.exe
It doesn't say that it doesn't build but it lets think that it only runs the .exe file.
https://jbuilder.readthedocs.io/en/latest/quick-start.html#building-a-hello-world-program
We also can see the same in the Libraries paragraph:
Now, open up bin/main.ml and replace the contents with the following:
$ dune exec bin/main.exe
5
2
It works but we see also that dune exec ...
does compile AND exec.
Additional test: just add an error somewhere in main.ml (Xopen instead of open) => main.exe is no more executable, so it has been modified.
4/ Librarie, paths, etc.
EDIT : For mental sanity of readers (especially beginners to whom I dedicate this post), why the original author and the Ocamlverse author are using here "lib" for the name of the library declared to dune AND for the name of the directory in which is located all the library stuff?? This is highly confusing when we should learn the language AND the toolings.
So I was first confused by that and believed that
DELETED :
(* "we can create a lib library by putting some .ml files in a directory if we declare that "lib" library in the dune file":
$ cat lib/dune
(library
(name lib))
So far, I've been using modules for that with nested modules inside. When I handle a .ml module file it has no adherence with the name of the place where I put it!
Is it specific to dune?
For me, this is not enforcing a "first-class modules policy" claimed in RWO or in other places. *)
Here is how it seems to me more simple and consistent to use modules declared to dune (in a lib/dune file) as a library that gathers, then made available for my main.ml program:
" To constitute a dune library with a set of .ml modules, I put them in a directory with a dune file where is declared the library name, then used for compilation and linking. " (this is a basic rule)
$ cat bin/dune
(executable
(name main)
(libraries foo))
$ cat lib/dune
(library
(name foo))
$ cat lib/math.ml
let add x y = x + y
let sub x y = x - y
$ cat lib/math2.ml
let mul x y = x * y
Then I can use in my main.ml program the functions offered by the Math and Math2 modules seen as modules nested in what appears as "Foo module" (in main.ml I use Foo.Math and Foo.Math2).
And this "Foo module" is declared to dune as a "Foo library".
$ cat bin/main.ml
open Foo.Math
open Foo.Math2
let () =
let result = add 2 3 in
print_endline (string_of_int result);
let result = sub 3 1 in
print_endline (string_of_int result);
let result = mul 2 3 in
print_endline (string_of_int result)
At last, regarding the naming and usage of directories (bin/ and lib/), which is one of my/our questions, I'll do as recommended by the dune team.
In this post, there are suggested corrections for improving the article, as well as key questions regarding dune which is becoming THE build system for OCaml.
I think that the dune team should (must!) expose clearly the complete and consistent rules that an OCaml coder must respect when using dune.
EDIT (I deleted what resulted from the lib directory/lib library confusion)
In fact I mean that writing dune files by hand is error prone (i tried to write opam files by hand and went into trouble because of package incompatibilities).
Is there a way for us and for dune to define the dependencies of a project with real-time consistency check, instead of letting people stuck with defining ocamlfind "library files" (META), "opam package files" (opam) and dune build files (dune) all over a tree of the file system?
Okay, you can say that I don't get the "whole story" about dune and ocamlfind and opam. Maybe, pls tell me.
And you can say that I should have read all the dune doc.
You are right (I will!), but the (recurrent) issue is that we find too many articles and event official (dune, OCaml) documentation (see dune Quick start) with incomplete or inconsistent information which result in confusion when trying to learn from it.
How do you want beginners to handle that? (fully beginners in coding, or coming from other programming languages).
This is the paradox I see with the Ocaml tooling/ecosystem: type safe "industrial strenght" language, but unsafe or poor documentation for tools.
But this is improving.