This repo contains templates for building and debugging with Visual Studio code for OCaml with the Dune build system. Make sure to check out OCaml's vscode platform repo
- An installation of OCaml which includes the Dune build system
- The opam package
earlybird
, which provides the debugger. - Visual Studio Code, install the
OCaml Platform
extension - I have written this guide with Linux in mind. This is the only operating system I have tested it on.
Activate your opam environment:
eval $(opam env)
Afterwards, if you do not have earlybird
installed, install with
opam install earlybird
Create the project as normal, with the command:
dune init proj ${projectName}
where ${projectName}
is the name of the project. I created this repository with project name as ocamldunebuildtemplates
.
Here, the setup may differ depending on the language version, check with:
dune --version
For versions 3 and above, you need to add the following (which has been done for this repository, as I have dune version 3.11) to your dune-project
file in the root folder of the project:
(map_workspace_root false)
Another step for debugging is to add support for compiling your file to bytecode, which is done by adding byte
as a supported mode in the /bin/dune
file in the project, next to where the main.ml file sits. It should now include the following:
(modes byte exe)
The first build script that will be added is just for a quick and dirty "compile and run" setup. This is implemented by adding the following to the .vscode/tasks.json
file:
{
"tasks": [
{
"type": "shell",
"label": "OCaml: Dune build and run active project",
"command": "eval $(opam env) && dune build && dune exec ${workspaceFolderBasename}",
"args": [],
"options": {
"cwd": "${fileDirname}"
},
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Build and run OCaml"
}
],
"version": "2.0.0"
}
This does not do any debugging, but just spawns a new terminal which first activates the build environment, builds the file project (you have to have opened the ocamldunebuildtemplates
folder in the "open folder" dialog for vscode for this to work properly, otherwise replace the ${workspaceFolderBasename}
which your project name), and then executes the program. If you want to run the programs with arguments, you can add them to the end of the exec command. The most important part to point out here are the lines:
"group": {
"kind": "build",
"isDefault": true
},
which makes it so that this is the default build task that will run when you press the Run Build Task
hotkey (Ctrl+Shift+B), which provides a massive speedup to compiling and running over having to type out:
dune build
dune exec ocamldunebuildtemplates
every time in the terminal, even using arrow keys to select past commands entered in the terminal will quickly start wasting time.
This configuration will allow debugging with earlybird
. Now a launch.json
which performs the debugging is needed, however, before the launch task runs, we also need to invoke a preLaunchTask
which performs the compilation step. Now the file .vscode/tasks.json
also contains the compile task:
{
"type": "shell",
"label": "OCaml: Dune build debug binary",
"command": "eval $(opam env) && dune build main.bc",
"args": [],
"options": {
"cwd": "${fileDirname}"
},
"detail": "Build OCaml Bytecode"
},
which compiles into a bytecode file which will then be used for debugging. The debugging task lives in the file .vscode/launch.json
:
{
"version": "0.2.0",
"configurations": [
{
"name": "OCaml earlybird (experimental)",
"type": "ocaml.earlybird",
"request": "launch",
"program": "${workspaceFolder}/_build/default/bin/main.bc",
"arguments": [],
"cwd": "${fileDirname}",
"stopOnEntry": false,
"preLaunchTask": "OCaml: Dune build debug binary"
}
]
}
and is a modification of the default task generated by the debugger, which has "stopOnEntry"
set to true and opens a select file dialog when debugging starts. If the program to be debugged needs launching with arguments, add them as a list in the arguments
brackets as a comma separated string list.
The debugging is a bit janky, so it might be the case that you need to write:
eval $(opam env)
in the spawned terminal for debugging, in case it is not configured that way already.
Start the debugging with Run->Start Debugging
button or by pressing the F5
hotkey.
- When you start debugging, vscode will take you to a file
_build/default/bin/main.ml
, which is a read only copy of the file/bin/main.ml
. So after debugging, make sure to switch back to your regular file. I have many times started fixing things in the code only to realize when I am trying to save that I am editing the wrong file. - Breakpoints can be finnicky, sometimes the debugger doesn't stop on some of them, so make sure to throw a bunch of breakpoints around where you want to debug. Some type of statements, such as if/match statements, can have weird side effects, such as having to place a breakpoint like you normally would, by clicking on the left side of the line number, but another grey dot will appear in the middle of the line that you need to click on in order for the breakpoint to work.