Compiling multiple Ocaml files

2019-02-22 11:18发布

I am new to Ocaml and trying to write some small example application. I am using ocamlc version 3.11.2 under Linux Ubuntu 10.04. I want to compile two files:

a.ml
b.ml

File b.ml uses definitions from a.ml. As far as I understand, I can use ocamlc -c to perform compilation only. I can call ocamlc one final time when I have all the .cmo files to link them to an executable. Also, when compiling a file that uses definitions from another file, I have to tell the compiler in which .cmi file to find the external definitions.

So my idea was to use:

ocamlc -i -c a.ml > a.mli
ocamlc -c a.mli b.ml
ocamlc -o b a.cmo b.cmo

The first step works and produces files a.mli and a.cmo, but when running the second step I get

File "b.ml", line 1, characters 28-31:
Error: Unbound value foo

where foo is a function that is defined in a.ml and called in b.ml.

So my question is: how can I compile each source file separately and specify the interfaces to be imported on the command line? I have been looking in the documentation and as far as I can understand I have to specify the .mli files to be included, but I do not know how.

EDIT

Here some more details. File a.ml contains the definition

let foo = 5;;

File b.ml contains the expression

print_string (string_of_int foo) ^ "\n";;

The real example is bigger but with these files I already have the error I reported above.

EDIT 2

I have edited file b.ml and replaced foo with A.foo and this works (foo is visible in b.ml even though I have another compilation error which is not important for this question). I guess it is cleaner to write my own .mli files explicitly, as suggested by

2条回答
兄弟一词,经得起流年.
2楼-- · 2019-02-22 11:53

First fix the unbound value issue, as explained by Jeffrey's answer. This is a comment about the commands you're using.

Decomposing compilation in several steps is a good way to understand what's going on. If you want to write your own a.mli, most likely to hide some values of the module A, then your command ocaml -i -c a.ml > a.mli is a good way to get a first version of the this file and then edit it. But if you're not touching a.mli, then you don't need to generate it: you can also directly enter

ocamlc -o foo a.ml b.ml

which will produce a.cmo, b.cmo and the exectuable foo.

(It will also generate a.cmi, which is the compiled version of a.mli, that you get by issuing ocamlc -c a.mli. Likewise it will also generate b.cmi).

Note that order matters: you need to provide a.ml before b.ml on the command line. This way, when compiling b.ml, the compiler has already seen a.ml and knows where to find the module A.


Some more comments:

  • You're right in your "As far as I understand" paragraph.
  • you don't really include a separate file, it's more like import in Python: the values of module A are available, but under the name A.foo. The contents of a.ml has not been copy-pasted into b.ml, rather, values of the module A, defined in a.ml and it's compiled version a.cmo have been accessed.
  • if you're using this module A in b.ml, you can pass any of the following on the command line before b.ml:
    • a.mli, which will get compiled into a.cmi
    • a.cmi if you've already compiled a.mli into a.cmi
    • a.ml or its compiled version a.cmo if you don't need to write your own a.mli, i.e. if the default interface of module A suits you. (This interface is simply every value of a.ml).
查看更多
smile是对你的礼貌
3楼-- · 2019-02-22 11:56

It would be clearer if you showed the code that's not working. As Kristopher points out, though, the most likely problem is that you're not specifyig which module foo is in. You can specify the module explicitly, as A.foo. Or you can open A and just use the name foo.

For a small example it doesn't matter, but for a big project you should be careful not to use open too freely. You want the freedom to use good names in your modules, and if you open too many of them, the good names can conflict with each other.

查看更多
登录 后发表回答