title: Embedding OCaml in C: linking error
body: <p>I'm trying to compile a program using mixed C and Ocaml sources, with the main of the application in C calling some pieces of OCaml code.
  All right, no problem here, It's seems to be a common operation, <a href="http://caml.inria.fr/pub/docs/manual-ocaml/manual032.html#toc142" rel="noreferrer">fully documented</a>, easy to do with the standard Ocaml tools.</p>
  
  <p>Let me explain a bit, this kind of compilation is divided in 4 steps : Caml compiling to Caml objects, then compiling the Caml to C objects, then compiling the C files, and lastly compiling all the C objects together and getting the executable.</p>
  
  <p>The theory is, the Ocaml compiler will embed the Caml runtime, GC, and all its stuff automatically, and we just have to indicate if we use whichever the ocaml bytecode (referencing <code>-lcamlrun</code>) or the native binary (referencing <code>-lasmrun</code>).</p>
  
  <p>So, it seems to be quite simple, let's do it. Steps 1, 2 and 3 went as expected, good!
  Only the 4th step is problematic. Just take a look:</p>
  
  <pre class="lang-none prettyprint-override"><code>cc -o /home/thomas/Documents/projects/ocaml/GogoGame/bin/GogoPlayer.exe \
          -L/usr/lib/ocaml  -lcamlrun \
          /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o \
              /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o \
              /home/thomas/Documents/projects/ocaml/GogoGame/src/interface.o \
              /home/thomas/Documents/projects/ocaml/GogoGame/src/caml_func.oo
  /home/thomas/Documents/projects/ocaml/GogoGame/src/interface.o: In function `main':
  interface.c:(.text+0x0): multiple definition of `main'
  /usr/lib/ocaml/libcamlrun.a(main.o):(.text+0x0): first defined here
  /usr/lib/ocaml/libcamlrun.a(floats.o): In function `caml_exp_float':
  (.text+0x488): undefined reference to `exp'
  /usr/lib/ocaml/libcamlrun.a(floats.o): In function `caml_fmod_float':
  (.text+0x4f9): undefined reference to `fmod'
  /usr/lib/ocaml/libcamlrun.a(floats.o): In function `caml_log_float':
  (…)
  /usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlopen':
  (.text+0x2ed): undefined reference to `dlopen'
  /usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlclose':
  (.text+0x300): undefined reference to `dlclose'
  /usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlsym':
  (.text+0x31b): undefined reference to `dlsym'
  /usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlerror':
  (.text+0x342): undefined reference to `dlerror'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0xc): undefined reference to `caml_array_get_addr'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x10): undefined reference to `caml_array_get_float'
  (...)
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x31c): undefined reference to `caml_lazy_make_forward'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x320): undefined reference to `caml_get_public_method'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3ac): undefined reference to `caml_terminfo_setup'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3b0): undefined reference to `caml_terminfo_backup'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3b4): undefined reference to `caml_terminfo_standout'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3b8): undefined reference to `caml_terminfo_resume'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
  (.text+0xc): undefined reference to `camlPervasives'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
  (.text+0x11): undefined reference to `camlPervasives__output_string_1191'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
  (.text+0x19): undefined reference to `camlPervasives__string_of_int_1130'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
  (.text+0x20): undefined reference to `camlPervasives'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
  (.text+0x25): undefined reference to `camlPervasives__output_string_1191'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__format_result_1034':
  (.text+0x9c): undefined reference to `camlPrintf__sprintf_1414'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__entry':
  (.text+0xe1): undefined reference to `caml_c_call'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__entry':
  (.text+0xfb): undefined reference to `caml_c_call'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__entry':
  (.text+0x115): undefined reference to `caml_c_call'
  /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
  (.text+0x32): undefined reference to `camlPervasives__print_newline_1276'
  collect2: ld returned 1 exit status
  make: *** [GogoPlayer] Error 1
  </code></pre>
  
  <p>IMHO, it seems that there is two errors:</p>
  
  <ul>
  <li>Multiple definitions of <code>main</code></li>
  <li>The linker doesn't find the module <code>Pervasive</code></li>
  </ul>
  
  <p>I have really no idea how to fix that, maybe I have to link an other file.
  Does someone have an idea ?</p>
  
  <p>As asked, I put the code that give these errors. It will be quite simple because there is very little code, most of it was given in an example in the documentation.</p>
  
  <p><strong><code>init.ml</code></strong></p>
  
  <pre class="lang-ml prettyprint-override"><code>let f x = print_string "f is applied to "; print_int x; print_newline()
  let rec fib n = if n &lt; 2 then 1 else fib(n-1) + fib(n-2)
  let format_result n = Printf.sprintf "Result is: %d\n"
  
  let _ =
    Callback.register "Arbitrary Name" f;
    Callback.register "fib" fib;
    Callback.register "format_result" format_result
  </code></pre>
  
  <p><strong><code>caml_func.c</code></strong></p>
  
  <pre class="lang-c prettyprint-override"><code>#include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  #include &lt;caml/mlvalues.h&gt;
  #include &lt;caml/callback.h&gt;
  
  void call_caml_f(int x)
  {
      static value * closure_f = NULL;
      if (closure_f == NULL) /* First time around, look up by name */
          closure_f = caml_named_value("Arbitrary Name");
  
      caml_callback(*closure_f, Val_int(x));
  }
  
  int fib(int n)
  {
      static value * fib_closure = NULL;
      if (fib_closure == NULL) fib_closure = caml_named_value("fib");
      return Int_val(caml_callback(*fib_closure, Val_int(n)));
  }
  
  char * format_result(int n)
  {
     static value * format_result_closure = NULL;
     if (format_result_closure == NULL)
        format_result_closure = caml_named_value("format_result");
     return strdup(String_val(caml_callback(*format_result_closure, Val_int(n))));
     /* We copy the C string returned by String_val to the C heap
     so that it remains valid after garbage collection. */
  }
  </code></pre>
  
  <p><strong><code>interface.c</code></strong></p>
  
  <pre class="lang-c prettyprint-override"><code>#include &lt;stdio.h&gt;
  #include "caml_func.c"
  
  #define BYTECODE
  
  int main(int argc, char **argv)
  {
  #ifdef BYTECODE
      caml_startup(argv);
  #else
      caml_main(argv);
  #endif
  
      /* Make sure that stdout is not block buffered. */
      setbuf(stdout, NULL);
  
      /* Process GTP commands. */
      //gtp_main_loop(commands, stdin, NULL);
      // CAML code here ?
  
      return 0;
  }
  </code></pre>
  
  <p>And this is all. Obviously, I skipped all the meaningless stuff as this simple example <strong>should</strong> work and does not. It must be my <code>Makefile</code>, which follows.</p>
  
  <p>By the way, it's quite ugly. If you have proposals for this kind of application (Caml <em>inside</em> C), or refactoring suggestions, I'll take them all.</p>
  
  <p><strong><code>Makefile.ocaml</code></strong></p>
  
  <pre><code>.PHONY: all clean mrproper
  
  # RULES and EXEC are magically set in Makefile.magic
  all: depend $(RULES) $(EXE)
      @echo [DONE]
  
  mli: $(CAML_ONLY:.ml=.mli)
  ml-byte: $(CAML_ONLY:.ml=.cmo)
  ml-called-byte: $(CAML_CALLED_BY_C:.ml=.$(OBJ))
  ml-nativ: $(CAML_ONLY:.ml=.cmx)
  ml-called-nativ: $(CAML_CALLED_BY_C:.ml=.$(OBJ))
  c-wrapper: $(C_WRAPPERS:.c=.oo)
  c-only: $(C_ONLY:.c=.o)
  
  $(EXE):
      $(CC) -o $(BIN)/$(EXE).exe \
          $(FLAGS) \
          -L$(OCAMLLIB) $(LINKED) -l$(RUNLIB) \
          $(wildcard $(SRC)/*.$(OBJ)) $(wildcard $(SRC)/*.oo) # */
  
  %.o: %.c
      $(CC) $(FLAGS_C) -c $&lt; -o $(SRC)/$(*F).o
  %.mli: %.ml
      $(OCAMLC) $(FLAGS_ML) -i $&lt; &gt; $(SRC)/$(*F).mli
  %.cmi: %.mli
      $(OCAMLC) $(FLAGS_ML) -c $&lt; -o $(SRC)/$(*F).cmi
  %.cmo: %.ml
      $(CAMLC) $(FLAGS_ML) -c $&lt; -o $(SRC)/$(*F).cmo
  %.cmx: %.ml
      $(CAMLOPT) $(FLAGSOPT) -c $&lt; -o $(SRC)/$(*F).cmx
  # native
  %.o: %.ml
      $(cd $(SRC))
      $(OCAMLC) -output-obj -o $(*F)_camlcode.o \
          $(FLAGS_MLC) \
          $&lt;
  # bytecode
  %.ob: %.ml
      $(cd $(SRC))
      $(OCAMLOPT) -output-obj -o $(*F)_camlcode.ob \
          $(FLAGS_MLC) \
          $&lt;
  %.oo: %.c
      $(CC) $(FLAGS_WRAP) -c $&lt; -o $(SRC)/$(*F).oo
  
  
  clean_mli:
      rm -f $(SRC)/*.mli # */
  clean:
      rm -f $(BIN)/*.{a,o,oo,cmi,cmo,cmx} # */
      rm -f $(SRC)/*.{a,o,oo,cmi,cmo,cmx} # */
  
  mrproper: clean, clean_mli
      rm -f $(BIN)/$(EXE)
  
  depend:
      $(OCAMLDEP) $(INCLUDES) $(SRC)/*.ml $(SRC)/*.mli &gt; .depend # */
  
  include .depend
  </code></pre>