Build error when using c stubs and external object file

I’m trying to run some hand written asm code in my ocaml program via c stubs using dune, but i cannot get it to work.

This is my dune file:

(library
 (name c_test)
 (extra_objects test)
 (foreign_stubs (language c) (names file1)))

(rule
 (targets test.o)
 (deps test.asm)
 (action (run nasm -f elf64 %{deps})))

I first tried without the extra_objects stanza, then the build of the library works fine, but it fails when linking the executable with undefined reference to 'ASM_Succ'. When looking at the dune documentation, it seems like the extra_objects stanza is the solution to the problem. But then i get the following error.

/usr/bin/ld: lib/test.o: in function `ASM_Succ':
test.asm:(.text+0x0): multiple definition of `ASM_Succ'; lib/libc_test_stubs.a(test.o):test.asm:(.text+0x0): first defined here

It seems like dune is adding test.o into lib/libc_test_stubs.a and also using test.o directly making my function defined twice. If i remove test.o from libc_test_stubs.a the command that dune runs succeeds.

Am i doing something wrong, or is dune misbehaving? Is there some other stanza i should be using to get this to work?

Any help is highly appreciated!

How are you declaring ASM_Succ in file1.c? Are you missing an extern?

Cheers,
Nicolas

these are my files:
file1.c

#include "caml/mlvalues.h"
#include "caml/memory.h"

int ASM_Succ(int, int);

CAMLprim value c_succ(value val, value rep) {
  CAMLparam2(val,rep);
  int v = Int_val(val);
  int r = Int_val(rep);
  int ret = ASM_Succ(v,r);

  CAMLreturn (Val_int(ret));
}

test.asm

bits 64
global ASM_Succ

section .text

ASM_Succ:
    inc rdi
    dec rsi
    jnz ASM_Succ
    mov rax, rdi
    ret

test.ml

external succ: int -> int -> int = "c_succ"

So yes, i was missing an extern. but adding it doesn’t seem to help. I still get the same error.

Today i found that I can successfully run the asm code if i move the .asm file to the bin folder and move the dune rule to build the asm file and the extra_objects stanza to the executable stanza in the bin folder dune file.

However, this doesn’t seem like a solution to the problem. I would like to be able to keep it in the lib folder. According to the dune docs extra_objects should work for libraries as well.

It is hard to give more precise help without all the details (eg the content of all Dune files). Is the code publicly accessible?

Cheers,
Nicolas

Created a github repo with the working and not working code.

Thanks.
I had a look, this looks like it’s a bug in dune.

It emits ocamlmklib -g -o lib/c_test_stubs lib/file1.o lib/test.o, which will make a cmxa with the following metadata:

Extra C object files: -lc_test_stubs lib/test.o

(making a double link)

Can you open an issue on dune? thanks

opened an issue now.

For anyone else following the discussion: the bugfix has been merged and will be included in the next release.

Cheers,
Nicolas