Setting up a new OCaml environment in 2026 is not yet a fluid experience

utop is an improved REPL compared to ocaml, but I won’t program in/with it.

Who is using utop, and how ? And why ?

If I ask to evaluate an expression, says in VS code, ocaml is called in the terminal and values are evaluated. It’s the same in Emacs : a panel/window/frame.. is opened and the expression evaluated.

Then, I very rarely manually play in the REPL.
I prefer to write testing expressions and have it evaluated in the same environment.

In bin/, I can only see source files than can be evaluated (what you should mean with “shell executable”?), or loaded in the REPL or compiled (byte code or binary). But no binaries.

My concern is:
what is located in bin/ ? Is it source or binary?

By ‘small shell executable’ I mean the source code of a wrapper executable of the project. Try running dune init project my-project and look at the generated project structure, it should be pretty clear that the bin/ directory contains source code. The build outputs will be in subdirectories under _build/.

1 Like

I know what dune init proj foo does. I won’t even discuss without that basic knowledge.

Thanks to agree there is some source code in… bin/

And that doesn’t surprise you ?

What do you think a newcomer to OCaml can think? Or simply an old ocamler seeing that?

Hello @Luc_ML,

When I reached out earlier, I tried to make it clear that I understand your opinion. At the same time, I encourage you to explore why OCaml tools and tutorials are structured the way they are, it’s often more rewarding than it initially seems.

Any experienced programmer has probably seen many projects with a variety of file organizations. So encountering something different from your Rust or C/C++ examples shouldn’t be surprising. Even in C/C++, there are many ways to organize source code, so I don’t think there is a single “standard” in this regard. Note that, like Go, Dune is flexible about how you organize your source files, but it provides a default structure when you run dune init proj. Now, if you are a beginner, the logical approach is to follow the tutorial first, so I honestly don’t see a problem.

Now, let’s clarify your concern:

Your complaint is about dune init and the default folder structure. It’s important to note that this is not a limitation of dune itself. Dune gives you full flexibility to organize your source code however you like. For example, you can rename the default lib/ folder to src/, and dune works and it will still place build artifacts in _build. If you prefer a src/ folder, simply rename the lib folder. If you dislike bin probably the same, you can name that folder with the name you want. It’s that simple.

Finally, I really love the test folder. With dune exec test/test_feature1.exe (where a code for feature1 is in test/test_feature1.ml), I can easily run tests while developing. What I mean is: please give dune a chance, after some time, you’ll likely become comfortable with how it works and all the features it has.

1 Like

No, it doesn’t surprise me. It’s just a name. There’s no rule that says that a directory called 'bin/` must always contain only binary executables, it’s just a convention.

Newcomers to OCaml will quickly adapt to the convention, and old OCamlers will just rename the directory if they don’t like the name bin. But I suspect most don’t care.

1 Like

what you describe only works if the value you are evaluating doesn’t have dependencies, right? For example if you depend on other files and libs from your project, but also maybe on ocaml libraries, you’d have to do a bunch of #require manually or launch dune top?

Sorry, but I’m not sure that it was a chief dune designer (is there is such thing) who decided on the folders names created by dune init proj; it’s more likely a consensus among different developers and users. Please make sure to double-check that what you said is actually accurate.

To my knowledge, there are more than 200 contributors to dune’s code. The news and blog entries on the dune website are written by different programmers, and talks about dune are also given by various developers.

1 Like

However it remains the case that a bin directory is an odd and unintuitive choice of naming for a source directory, given usage elsewhere. You would expect it to be the location of the finished binaries rather than source files.

But I think this is not worth making too much of a fuss over. Dune enables you to set up any directory structure you want for your source files. mkdir does the job fine: dune init is unnecessary and I avoid it. The rest is down to your dune files, and the contents thereof.

2 Likes

Hello,

I’ve studied OCaml as a student a long time ago, and forgot it, then I came back to it around 2014-2015.
At that time, I’ve intensively studied nearly all about Ocaml. I’ve seen dune appearing, initially called jbuilder. First contact with dune (tool and documentation) was horrible.

I’ve been away from real world Ocaml programs for about 3 years.
So I’m not strictly a beginner.
I can use ocamc/ocamlopt with my own recipes, or with Makefiles.
But I’m still a beginner regarding setting up in minutes a reliable modern OCaml IDE with all tools!

This is good news.
Where is it configurable? Or should I use a script to rename directories? Hence, it may finish with my existing scripts to create a program tree… and add build files of my choice.

You suggest we could also name it foo/
Naming correctly things is of key importance.

If I want to get more OCaml programmers, to reach a momentum, the first thing I must do it to make tools as clear, easy and powerful as possible. Instead of spreading weird convention and documentation.

There’s a difference between naming a directory bin/ and naming it foo/ if it’s supposed to contain the source code of the project’s main executable. The former is chosen for a reason while the latter is completely random. In Go projects there is a convention of calling this directory cmd/. And yet it doesn’t literally contain the commands themselves, just their source code.

If we want to get more OCaml programmers and reach a momentum, there are much more important and urgent improvements that can be made. I don’t think the naming of bin/ is a huge issue tbh.

1 Like

No, all required dependencies must also be evaluated.
Yes, “old fashioned” way is to use af file with a set of #directory “xxx” #require "foo";; and open Foo(possibly generated). It has the advantage to make you aware of what you are doing.

Now, you say utop with dune files can do that for me: this is a good point.
I can see: How to Load a Project in a Toplevel - Dune documentation

When programming in, say VScode, if I want to evaluate an expression, I want the terminal launched with all the stuff (programe and dependencies) loaded.

Does utop and dune do that ? This would be another good point.

Notice that I can also get a toplevel with all my stuff with ocamlmktop, which is working for ages. A script does that well. It’s a simple routine to have it up and running
https://ocaml.org/manual/5.4/toplevel.html#s%3Acustom-toplevel

The bin files are for binaries. The lib files are for libraries. The test files are for tests. I’ve added a doc dir which also contains the documentation, and also not the generated html/man documentation but rather the .mld source for it.

It’s true that in an installation prefix bin/ has output and not source, and lib/ has .so files and not source, and doc/ may have .html but not .mld, but a project root that you’ve just cloned with git isn’t /usr/local and it’s normal for the same words to be interpreted differently in different contexts, to the point that I didn’t even realize it could be confusing until the second time you mentioned it. The very first minute with dune is seeing a main.ml in bin/ and then not seeing a binary there after building it, but realizing that build output goes into _build.

3 Likes

The naming of bin/ is just an indicator of a weird approach (see C++, java and Rust).
An experience is based on many details. But only one bad detail is often enough to lose your “customer”.
I’m also talking of my early stage dune/jbuilder hard experience and about the experience shared by other people with OCaml.

The goal of this discussion is to say:
“Hey, OCaml folks! In 2026, you should know that it’s not as easy as pie to setup a full featured OCaml IDE, especially for Win ; even for non OCaml beginners. btw, how do tools must, must not or can interact?”
I propose to discuss about that.

The naming of bin/ is just an indicator of a weird approach (see C++, java and Rust).

None of these languages normally use REPLs and don’t gain easy use of a REPL as an automatic advantage from separating source out. The code you have in lib/ gets loaded into dune utop with no scripting or configuration, and is available to your code in bin/ just by adding myproj to a list of libraries.

These languages all also have defined entry points - main functions - that a REPL could simply skip. OCaml uses side effects at the top level and doesn’t have a clear distinction between

let () = initialize_stuff () (* a repl should always call this *)
let () = run_program () (* a repl should probably skip this *)

dune utop isn’t doing anything that you can’t do yourself by other means, but “type these two words to start working interactively with the library portion of your project” is a lot less to even explain if you want to encourage someone else to adopt this very nice workflow.

I said this above:

On charity, it’s easy to immediately run into something about OCaml that can be received as the way it is, only because some very low-hanging fruit wasn’t picked, or because of some developer’s personal idiosyncrasy, or because OCaml’s just old and better ways weren’t in vogue yet.

What I had in mind for “personal idiosyncrasy” was dune’s s-expressions, because that’s how I initially received it. It’s obviously true that someone can interpret bin/ as a senseless and random decision, since you’re doing that now, but it really takes extremely little charity to overcome that initial bad impression about that name. A remark like “don’t worry about the layout, there are practical advantages to it” is all that a guide might need.

Well, dune is just exploring directories and looking for dune files with stanzas. So, it is very easy, after for example dune init proj you can just use (in Unix/Linux) mv lib src to rename the directory, and mv bin mycli (for example). Remember that the only key point are the dune files on each directory, not the name of the directory. So when you do dune build or dune exec is not important the folder names but the dune files.

The useful point when using dune init proj is to check how is the dune file inside the bin/ directory to understand the stanzas to create binary files, and in lib check the dune file to see the basic stanzas for libraries, or also the test/dune to review the stanzas for testing. By stanzas I just meant the commands (using s-expressions) written in the dune files. This would give you an idea about basic stuff, then here:

In this link you can see more advanced ideas for your stanzas, and more advanced stuff (for example a kind of meta-programming via ppx can be specified easily). You can explore C-stubs, or WASM, or Javascript compilation using dune. As I said, it is a powerful tool, from my point of view.

Again, to my knowledge the names of the folders are totally arbitrary, dune allows you to use whatever names you want. Also here, at the end you will see a list of tools on top of dune if you want to replicate, for example, the cargo style. But honestly my recommendation is to try to learn dune itself.

I wish you all the best, and great that you returned to OCaml. I hope you will enjoy.

PD: In dune there are specific stanzas that may need to be updated in case you rename directories, but this only happened for advanced features, when you want to specify data-files for your project, or when you want to define external files to be loaded by your code. But usually you introduce these features when you already have decided the names of the directories of your project, for example, if you have a directory data for data-files etc…

1 Like

I was going to say “None of these languages have REPLs”, but maybe gdb qualifies, and IRust loads your src/lib.rs

Go’s version of bin/ is cmd/ - this sample project layout is pretty nice low-effort documentation, with the commentary and examples.

Again, to my knowledge the names of the folders are totally arbitrary,

You can even have everything in the project root, with no subdirectories, at the cost of having to add modules:

(executables
 (names hello bye)
 (modules Hello Bye)
 (libraries myconfig))

(library
 (modules Myconfig)
 (name myconfig))

(documentation)

I thought that dune utop broke on this at first, but that was a conflict with calling the module Config

1 Like

Hi,
This flexibility is interesting to know.

In case it helps anyone, I found this thread quite interesting and decided to give it a try.

For the record, I’ve been interested in Ocaml but never installed it. I have a custom devcontainer image that comes with the latest LTS version of Ubuntu and many development tools installed, but it does not have Ocaml.

At 17:03 today, I created a new Devcontainer from that image, then followed the instructions from ocaml.org. To be more specific, I created a directory under my WSL terminal, which is running under Windows 10 professional, and copied my devcontainer files. Then I opened that WSL directory with Vs Code, which asked me if I wanted to open as a Devcontainer, to which I said yes. This is the most common way of creating a devcontainer, using vs code.

Once the devcontainer was ready, I used the terminal from vs code to follow the Ocaml docs, and everything just worked as documented. The only issue I had was with bwrap missing in my devcontainer, but the docs actually said I should init opam without a sandbox if I’m using a container, which is what I’m doing. If I follow the docs, bwrap is not required.

I installed the vs code extension, then started going through “your first program” from the docs. Vs code extension does require dune build to run in watch mode though, or else changes to modules won’t be recognised without a dune build followed by restarting the language server. That’s the only thing I think I had to figure out myself (and maybe it is in the docs, but I missed it). If I’d followed the docs’ advice, I’d have dune running in watch mode anyway from the beginning.

Despite the few blunders due to my lack of focus, it took me about 15 mins max to have a working env where I installed sexplib, and used it from main.ml etc. as the docs show.

Don’t get me wrong, this is not a “it works, no issues” post, but for someone who’s never installed Ocaml, 10 minutes is not too bad :slight_smile:

Admittedly, I am used to wrestling with whatever tools I need to get up to speed quickly and my devcontainer config is pretty robust after years of adding all the linux libs etc. My dev environment setup process is quite streamlined at this point.

My humble suggestion would be encouraging users to a devcontainer setup. Vs Code is very robust when it comes to its support, the technology is open source, cross platform and can integrate with all major host OSs pretty well (mount dirs from host etc).

Cheers

3 Likes