# Compiling .ml containing toplevel directives

**URL:** <https://discuss.ocaml.org/t/compiling-ml-containing-toplevel-directives/11038>\
**Category:** Community\
**Tags:** build\
**Created:** [December 22, 2022, 10:57pm UTC](https://discuss.ocaml.org/t/compiling-ml-containing-toplevel-directives/11038 "2022-12-22T22:57:34Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![aqjune](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/aqjune/32/4090_2.png) [@aqjune](https://discuss.ocaml.org/u/aqjune)\
**Post date:** [December 22, 2022, 10:57pm UTC](https://discuss.ocaml.org/t/compiling-ml-containing-toplevel-directives/11038/1 "2022-12-22T22:57:34Z")

</div>

Hi,

Is there a systematic approach to preprocess .ml containing toplevel directives so that the preprocessed .ml output file can be compiled with ocaml compilers?  
Toplevel directives like `#directory` would require some commandline arguments to be added to the ocaml compiler, but we are willing to take the complexity.

Thanks!

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [December 23, 2022, 1:14pm UTC](https://discuss.ocaml.org/t/compiling-ml-containing-toplevel-directives/11038/2 "2022-12-23T13:14:46Z")

</div>

You didn’t say much about your use case so the following suggestion may be off.

Did you maybe consider doing the converse ?

That is augument your sources with directives as [floating attributes](https://v2.ocaml.org/manual/attributes.html#floating-attribute) e.g.

```
[@@@top.directory "my/dir"]

```

and extract the directives via compiler libs. These files will compile without surgery.

---

<div class="post-metadata">

**Author:** ![aqjune](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/aqjune/32/4090_2.png) [@aqjune](https://discuss.ocaml.org/u/aqjune)\
**Post date:** [December 23, 2022, 3:09pm UTC](https://discuss.ocaml.org/t/compiling-ml-containing-toplevel-directives/11038/3 "2022-12-23T15:09:37Z")

</div>

Hi,

The background is that we have a few big .ml files that contain top directives. They are supposed to be used with `#use "x.ml";;` in OCaml REPL, but as the ml files are getting larger, running `#use` is now taking a significant time (around a minute). To make loading it faster, I am looking for a method to compile x.ml into .cmo/.cmi/.cma and load it.

Does using the floating attribute generate new .ml files that can be compiled with ocamlopt or ocamlc, or am I understanding wrong?

---

<div class="post-metadata">

**Author:** ![progman](https://avatars.discourse-cdn.com/v4/letter/p/8797f3/32.png) [@progman](https://discuss.ocaml.org/u/progman)\
**Post date:** [December 23, 2022, 4:35pm UTC](https://discuss.ocaml.org/t/compiling-ml-containing-toplevel-directives/11038/4 "2022-12-23T16:35:56Z")

</div>

if you don’t mind jiggling the compiler to ignore #-directives…

cd `opam var ocaml-variants:build`  
vi parsing/lexer.mll  
the compiler lexer has a clause for handling just `# <line> "<file name>"`  
at

```auto
and directive = parse
...

```

add this 2nd case to ignore any other # directive:

```auto
  | [^ '\010' '\013'] * { token lexbuf }

```

make ocamlc.opt ocamlopt.opt install

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [December 23, 2022, 7:49pm UTC](https://discuss.ocaml.org/t/compiling-ml-containing-toplevel-directives/11038/5 "2022-12-23T19:49:08Z")

</div>

> [@aqjune](#):
>
> Does using the floating attribute generate new .ml files that can be compiled with ocamlopt or ocamlc, or am I understanding wrong?

Custom attributes are ignored by the compiler. You can put there whatever you want.

You may also want to have a look at [`ocamlscript`](https://github.com/ocaml-community/ocamlscript) (or [`b0caml`](https://erratique.ch/software/b0caml/doc/manual.html), but it’s unreleased and again one of these projects I had that was assuming we were going towards a simplification of the notion of library and needs to be reviewed now that this did not happen).

---

<div class="post-metadata">

**Author:** ![aqjune](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/aqjune/32/4090_2.png) [@aqjune](https://discuss.ocaml.org/u/aqjune)\
**Post date:** [January 6, 2023, 10:01pm UTC](https://discuss.ocaml.org/t/compiling-ml-containing-toplevel-directives/11038/6 "2023-01-06T22:01:34Z")

</div>

Hi all,  
It turns out that the number of toplevel directives was pretty small so I could manually deal with them. :). Thanks for your all answers.

I have a new question though. The `.ml` file is using `Topdirs` and `Toplevel` modules, and when I compile the `.ml` using `ocamlc` I am seeing:

```auto
$ ocamlfind ocamlc -linkpkg x.ml -package compiler-libs
...
Error: Required module `Topdirs' is unavailable

```

Does anyone have idea about this error message?

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [January 6, 2023, 10:33pm UTC](https://discuss.ocaml.org/t/compiling-ml-containing-toplevel-directives/11038/7 "2023-01-06T22:33:22Z")

</div>

> [@aqjune](#):
>
> Does anyone have idea about this error message?

Topdirs is in the `compiler-libs.toplevel` library.

---

<div class="post-metadata">

**Author:** ![Luc\_ML](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/luc_ml/32/1671_2.png) [@Luc\_ML](https://discuss.ocaml.org/u/Luc_ML)\
**Post date:** [January 19, 2026, 6:12pm UTC](https://discuss.ocaml.org/t/compiling-ml-containing-toplevel-directives/11038/8 "2026-01-19T18:12:01Z")

</div>

> [@dbuenzli](#):
>
> That is augument your sources with directives as [floating attributes](https://v2.ocaml.org/manual/attributes.html#floating-attribute) e.g.
> 
> ```auto
> [@@@top.directory "my/dir"]
> 
> ```
> 
> and extract the directives via compiler libs. These files will compile without surgery.

Testing in the TopLevel with .ml files that I also want to compile, I have 2 very simple and usual ways for doing that:

1/ Add a commented block of Toplevel directives in the source file and uncomment/evaluate/comment it when required.  
It’s even just a shortcut away in your editor.  
No compiler option. But source file is modified…

2/ For `program foo.ml`, put directives in `foo.ml.directives`.  
But it requires first to write (or copy-past) and evaluate `#directory “path/to/foo.ml.directives”` and `#use “directives_foo.ml”` from the TopLevel…  
Hence, I often handle a file `foo.ml.directive`next to`foo.ml` and simply copy-paste-evaluate its content in the Toplevel.  
No compiler option. But source files directory is modified…

Something like this is not working and it also pollutes source file:

```auto
[@@@top.directory "my/dir"]

```

But it would be nice to add something similar that can be evaluated in the Toplevel while source files can be preprocessed to get rid of such directives.

I can also use a custom Toplevel with all the required env. But it’s not just launching the Toplevel and start playing with my source files.

It seems module `Topdirs` is not to be used in a program.

In 2026, is there a simple way to handle Toplevel directives in some format that can be preprocessed (by the compiler or so), so I can:

- play with source files in the Toplevel, after a simple evaluation of directives
- compile them at anytime without any change (even just commenting directives)  
→ which options to ocamlc/ocamlopt ?
- preprocess them to just filter out these “personal directives” before delivering them  
→ which options to ocamlc/ocamlopt ?

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [January 19, 2026, 6:37pm UTC](https://discuss.ocaml.org/t/compiling-ml-containing-toplevel-directives/11038/9 "2026-01-19T18:37:45Z")

</div>

If you put the files in a dune library, it will compile without modifications. Then you can load the library with `dune utop`. You don’t need toplevel directives for that, dune automatically does it for you.

---

<div class="post-metadata">

**Author:** ![Luc\_ML](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/luc_ml/32/1671_2.png) [@Luc\_ML](https://discuss.ocaml.org/u/Luc_ML)\
**Post date:** [January 19, 2026, 10:28pm UTC](https://discuss.ocaml.org/t/compiling-ml-containing-toplevel-directives/11038/10 "2026-01-19T22:28:48Z")

</div>

I don’t need utop at all.  
I already have a Toplevel environment setup file.  
Why another setup file?… And another Toplevel?  
And why using “dune, a build system designed for large programs”, which UI… has not yet been designed, for doing such a simple thing? Hence becoming dependent on some kind of beast.

Maybe you didn’t understand my question.  
I’m not blocked **at all**.  
I may be interested to improve my **very lightweight** procedure (i.e. evaluate a few expressions already written or generated) WITHOUT dealing with compiler options.

However, maybe I should consider compiler options to filter out all directives.

Any other agnostic (i.e. non dune) answer ?
