"Error: Pure bytecode executables cannot contain foreign stubs." is misleading
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 ofdune --version): 3.3.1 - Version of
ocaml(output ofocamlc --version): 4.14.0 - Operating system (distribution and version): Linux Mint 20.1
If one attempts to create an
executablewith(modes (byte exe))andforeign_stubs,dunecomplains: "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 alibrary.
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.