dune icon indicating copy to clipboard operation
dune copied to clipboard

"Error: Pure bytecode executables cannot contain foreign stubs." is misleading

Open smcpeak opened this issue 3 years ago • 1 comments

If one attempts to create an executable with (modes (byte exe)) and foreign_stubs, dune complains: "Error: Pure bytecode executables cannot contain foreign stubs." This message seems to be saying that it is impossible to create a bytecode executable with foreign stubs. However, it can be done, simply by wrapping the stubs in a library.

Example of error message

dune:

(executable
  (name main)
  (modules
    Main
    Ext
  )
  (foreign_stubs
    (language c)
    (names ext_impl)
  )
  (modes
    (native exe)
    (byte exe)
  )
)

(rule
  (alias runtest)
  (deps ./main.bc)
  (action
    (bash "env LD_LIBRARY_PATH=. ./main.bc")
  )
)

Main.ml:

(* Main.ml *)
let () =
  Ext.hello ()
(* EOF *)

Ext.ml:

(* Ext.ml *)
external hello : unit -> unit = "ext_hello"
(* EOF *)

ext_impl.c:

// ext_impl.c
#define CAML_NAME_SPACE
#include <caml/mlvalues.h>
#include <stdio.h>
CAMLprim value ext_hello(value unit)
{
  printf("in ext_hello\n");
  return Val_unit;
}
// EOF

Attempted compilation:

$ dune clean; dune test
File "dune", line 1, characters 0-163:
 1 | (executable
 2 |   (name main)
 3 |   (modules
....
13 |     (byte exe)
14 |   )
15 | )
Error: Pure bytecode executables cannot contain foreign stubs.
Hint: If you only need to build a native executable use "(modes exe)".
Exit 1                            

Workaround: encapsulate in a library

Modified dune:

(library            ; ADDED
  (name ext)
  (modules Ext)
  (foreign_stubs
    (language c)
    (names ext_impl)
  )
)

(executable          ; MODIFIED
  (name main)
  (modules Main)
  (libraries
    ext
  )
  (modes
    (native exe)
    (byte exe)
  )
)

(rule
  (alias runtest)
  (deps ./main.bc)
  (action
    (bash "env LD_LIBRARY_PATH=. ./main.bc")
  )
)

This works:

$ dune clean; dune test
in ext_hello

Expected Behavior

Ideally, the first example should just work. But if that is not possible, then the error message should suggest putting the foreign stubs into a library.

Specifications

  • Version of dune (output of dune --version): 3.3.1
  • Version of ocaml (output of ocamlc --version): 4.14.0
  • Operating system (distribution and version): Linux Mint 20.1

smcpeak avatar Aug 16 '22 06:08 smcpeak

If one attempts to create an executable with (modes (byte exe)) and foreign_stubs, dune complains: "Error: Pure bytecode executables cannot contain foreign stubs." This message seems to be saying that it is impossible to create a bytecode executable with foreign stubs. However, it can be done, simply by wrapping the stubs in a library.

The message is correct, in the sense that a pure bytecode executable cannot contain custom C code. Instead the custom C code must be loaded from a shared library, and this requires defining a library, as you discovered.

I agree that a comment about this point in the error message may be useful.

nojb avatar Aug 16 '22 07:08 nojb