12

I have a file Tools.ml which contains some common utility functions I write myself. Under .../Code/ I have several folders which each contains a project. My question is where I should place this Tools.ml such that all the folders and files under .../Code/ could share this module by Open Tools.

Hope my question is clear... Does anyone have a good solution?

Edit1: Following @gasche's answer, I have written tools.ml as follows:

module Tools =
  struct
    let a_function = ...
    ...
  end

Then I compiled it, and done ocamlfind install tools META tools.cmo tools.cmx tools.ml as suggested, which looks going well. Then I have written test.ml as follows:

open Tools

let f = Tools.a_function

then I compiled it with ocamlc test.ml -o test, then I got an error:

File "test.ml", line 1, characters 0-1:
Error: Error while linking test.cmo:
Reference to undefined global `Tools'

Could anyone tell me what happened?

SoftTimur
  • 5,630
  • 38
  • 140
  • 292

1 Answers1

12

You could package it as an independent library, install it with other OCaml libraries, and access to it, from your project, as a library.

A very simple way to do this is to write a META file for ocamlfind. Create a directory somewhere you're comfortable to hold you "personal library" project. Suppose you have tools.ml and tools.mli, and your code depends on some findlib package (eg. unix and bigarray). You META would look like this:

name="tools"
description="personal collection of utilities"
version="0.1"
requires="unix,bigarray"
archive(byte)="tools.cmo"
archive(native)="tools.cmx"

Once you have written this META file, it is easy to ask ocamlfind to "install" the library (and remove it if you want to), and use it in your other projects. To install, the syntax is ocamlfind install <name> <meta-file> <file1> <file2> ... where <file1>, <file2>.. are the file you wish to see included in the installation directory. You must at least have tools.cmi tools.cmo (and tools.o and tools.cmx for native compilation), but it is good practice to also have tools.mli for example (and, if you want to provide the code, tools.ml).

ocamlfind install tools META tools.cmi tools.cmo tools.o tools.cmx tools.mli

(Of course tools.cmo etc. have to exist, that is you must install after you have compiled your package. If you have used ocamlbuild, they are likely to be in a _build subdirectory, so ocamlfind install ... _build/tools.cmo ....)

From your numerous projects, you can use your library easily, either using the ocamlfind toold directly if this is what you already do to compile your programs

ocamlfind ocamlc -package tools ....

or through the facilities provided by ocamlbuild for example, adding package(tools) to your tags.

To reinstall your library if you made a change to it and want it accessible from your projects

ocamlfind remove tools
ocamlfind install tools META ...

You could also handle all this through oasis, which is a layer on top of ocamlfind/ocamlbuild to automate this process. I'm not familiar enough with oasis to give such examples off the top of my head, but it should be equally simple for such a restricted case (one-file library), and scale better if you wish later to extend your library (eg. it can also handle documentation generation, pre-compilation configuration...).

ReyCharles
  • 1,772
  • 10
  • 30
gasche
  • 31,259
  • 3
  • 78
  • 100
  • Thanks for your comment... Could you please take a look at my test in OP? – SoftTimur Jan 02 '12 at 05:39
  • 1
    @SoftTimur: the correct compilation command in your case is `ocamlfind ocamlc -package tools -linkpkg test.ml -o test`. The option `-package tools` adds the package, and `-linkpkg` links it to produce an executable (needed when you produce an executable, but not when compiling to a `.cmo`). You could probably also use `ocamlbuild -tag "package(tools)" test.byte` (not tested). – gasche Jan 02 '12 at 06:48
  • @gashe: `ocamlfind ocamlc -package tools -linkpkg test.ml -o test` works only when `test.ml` is in the same folder as the executable `tool`... Do you know why? – SoftTimur Jan 02 '12 at 08:34
  • Why is `tool` an executable? I thought that was only a library (.ml(i) code meant to be used in other projects). Did you `ocamlfind install ...` the package correctly? Does `ocamlfind list` list the `tools` package? – gasche Jan 02 '12 at 08:45
  • I did `ocamlfind install ...` correctly, and `ocamlfind list` does list the `tools` package with the right version. I try to compile a `test.ml` in a folder other than `tools`, it gives `Error: Unbound module Tools`. – SoftTimur Jan 02 '12 at 09:53
  • I suppose the META file must be wrong (is the `archive(byte) = foo.cmo` line present?) or the installation incomplete (was `foo.cmo` installed with the META? Is it present in the directory indicated by `ocamlfind query tools`?). – gasche Jan 02 '12 at 10:23
  • OK, I got it... the thing is not to forget `tools.cmi` in `ocamlfind install tools META ...`... I do not know if it is better to mention `tools.cmi` in `META`... – SoftTimur Jan 14 '12 at 09:46