13

I am new to Ocaml and just setting up my dev environment with emacs, merlin and flycheck. Everything works more or less expected except one thing : merlin doesn't seem to be able recognise the dependencies between the modules in the same project.

e.g. I have a test project with two modules: main.ml and awesome.ml.

here is my main.ml which references the second module awesome.ml

(* main.ml *)
open Core
module A = Awesome
let _ =
   Printf.printf "hello \n Converted to string we get: %s\n"
     (A.str_of_t (A.succ A.one_t));

here is awesome.ml:

(* awesome.ml *) 
type t = int
let one_t = 1
let succ i = i + 1
let str_of_t = string_of_int

when I send main.ml buffer to evaluate into utop with utop-eval-buffer function, I am getting an error: "Error: Unbound module Awesome"

I have .merlin in the root of the project which has S instruction. I know it is found by merlin as it doesn't complain about "open Core"

S src
PKG core lwt ounit
B _build/src
B +threads

here is my _tags:

<src/**>: include
<src/**>: package(oUnit), package(core)
true:thread

the regular project compilation with ocamlbuild works fine, no errors. here is Makefile

## Makefile
default: main
main: main.native

test: test.native

%.native:
   ocamlbuild -use-ocamlfind $@
   mv $@ $*

.PHONY: test default

any ideas why Awesome module is not recognised in utop or this is expected behaviour?

Richard-Degenne
  • 2,892
  • 2
  • 26
  • 43
Roman Shestakov
  • 497
  • 5
  • 16

3 Answers3

14

Merlin will see other modules once you have compiled them (in fact, once you have compiled its interfaces). So given your .merlin is correct it will see everything after you run compilation. Your files should indeed be in a src folder, i.e., your project layout, based on your .merlin file should look like this:

Makefile
.merlin
src/
   awesome.ml
   main.ml

This is not a required layout, but this is the one, that you described to Merlin. The reason, why I suspect that it is not the same, is your Makefile.

P.S. Just as a side note, there is a small issue in your code: you should open Core.Std not Core.

ivg
  • 34,431
  • 2
  • 35
  • 63
  • thanks Ivan. It still doesn't work. I have a correct project layout - the sources are in src dir, .merlin is in the root of the project. The reason for B +thread directive is here : https://github.com/the-lambda-church/merlin, I added as suggested in merlin docs. You are right about open Core.Std. I ran the compilation - the sources compile correctly, I see o files in _build/src but merlin still doesn't recognise the awesome.ml module. Looks like something is wrong with my setup - I will keep digging. Thanks! – Roman Shestakov Jul 19 '15 at 16:29
  • I suspect, that you have problems, with your makefile, and it doesn't compile anything. So, without a `Makefile` file, if I will just go to the top directory of your project and issue `ocamlbuild src/main.native`, then merlin recognizes `Awesome` module. Basically, you `Makefile` looks incorrect to me. And it just do not compile anything. A good check: there should be `_build/src/awesome.cmi` file after running build. – ivg Jul 19 '15 at 16:59
  • nope, makefile is good - it compiles, produces a binary main which I can execute. awesome.cmi/awesome.cmo/awesome.cmt/awesome.cmti/awesome.cmxare generated in _build/src – Roman Shestakov Jul 20 '15 at 20:17
  • 1
    Well, then the next guess would be, that your emacs is somehow misconfigured. Look carefully, for the messages from emacs. The easiest way to run it without a problem is to run emacs from a terminal in which you previously run `eval $(opam config env)` – ivg Jul 20 '15 at 21:42
  • thanks, I will check my emacs setup. much appreciated. – Roman Shestakov Jul 21 '15 at 22:43
2

As Ivan's answer pointed out, Merlin can only recognize a module in your project after you compile it. If Merlin is giving you an unbound module Foo error, one solution is to run

ocamlbuild foo.cmi
Community
  • 1
  • 1
hugomg
  • 68,213
  • 24
  • 160
  • 246
  • This actually completely fixed it for me and I have no idea why. Does ocamlbuild somehow save state? I'm pretty new, so it's entirely possible that I just am very ignorant of how the whole dev environment works hah – Jay Apr 18 '17 at 02:45
  • Ocamlbuild will save the "foo.cmi" interface file inside the "_build" directory. Which I guess counts as "saving state". – hugomg Apr 18 '17 at 03:38
  • Ohhh makes sense. I assumed Merlin was looking at the second and not built files I guess. Guess I was wrong! – Jay Apr 18 '17 at 06:32
  • Very odd… I got the same problem, but compiling the CMIs didn’t solve it. – Arĥimedeς ℳontegasppα ℭacilhας Mar 22 '21 at 21:26
1

I had the same problem. I tried installing merlin through opam or sources, but I couldn't solve this problem until I put the ".merlin" file in to the \src directory--not at the root-- with a "REC" tag in it.

heykell
  • 171
  • 6