Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OCaml cross linking

how does referenced linking work in OCaml?

Example, let's assume I have 3 modules declared as

  • A.ml
  • B.ml
  • C.ml

of which

  • A needs B and C
  • B needs A

How should I proceed in compiling?

Since order is relevant using ocamlc or ocamlopt how can I fix the cross reference between B and A?

I'm trying to first compile them all into .cmo with ocamlc -c and then link all of them together but with no success since swapping arguments will just move a problem from a module to another.

The specific error is:

Error: Error while linking A.cmo: Reference to undefined global `B'

(or viceversa, if I swap the order of the args)

I thinks this is an easy question but I'm unable to solve it.. thanks in advance

like image 238
Jack Avatar asked Jul 01 '10 15:07

Jack


1 Answers

You have to combine the modules into one file and make them recursive. I don't believe there is a way to do this from the compilation process of two separate files.

module rec A : 
    sig
        val f : int -> int
        val g : int -> int
    end = 
    struct
        let f x = (B.g x) + 1
        let g x = x + 1
    end
and B :
    sig
        val f : int -> int
        val g : int -> int
    end = 
    struct
        let f x = (A.g x) + 1
        let g x = x + 1
    end

EDIT: From your comment, I am guessing you have the type definition of the parser and the functions that process/operate on the type in the same file. I agree with you, it makes sense. But like you've experienced if that file is to not only operate on the type but call the parser to produce the data, how is the parser going to construct it? My solution has been to separate the type into it's own module and open that module in the module that does the operations.

Therefore, you are splitting A into (A and A'), where A' contains the type produced by B, and used in A. Your dependencies become,

  • A needs A' and B and C
  • B needs A'

For example, I have a parser for configuration files I use to start up any application I write.

ConfType   --contains the type t  
Conf       --calls parser, and contains helper functions for type ConfType.t  
ConfParser --for ocamlyacc
ConfLexer  --for ocamllex

An alternative to all this is to use polymorphic variants. In this way you remove the dependency since they are defined ad-hoc. Of course, the type produced by the parser has the potential to be different then the one in Conf, and the compiler wont be able to help you with the error.

like image 87
nlucaroni Avatar answered Sep 21 '22 02:09

nlucaroni