我想编译一些OCaml字节码,让它在Windows和Unix类型的系统上运行。如果我在每个平台上重新编译它,我的源代码工作正常,但字节码不可移植。
示例代码:
open Unix
let on_windows = Filename.dir_sep <> "/";;
Printf.printf "On windows: %b\n" on_windows;;
let child = create_process "gpg" (Array.of_list ["gpg"; "--version"]) stdin stdout stderr;;
Printf.printf "Child %d\n" child;;
构建命令:
ocamlbuild -use-ocamlfind -pkg unix test.byte
如果我在Windows上编译并在Linux上运行,我会得到
Fatal error: unknown C primitive `win_waitpid'
如果我在Linux上编译并在Windows上运行,我会得到:
Fatal error: unknown C primitive `unix_waitpid'
如何让字节码在任何地方都能正常工作?
答案 0 :(得分:8)
显然,原因是ocaml unix库根据平台有不同的C存根名称,这阻碍了字节码的可移植性。除了修补存根名称外,我没有看到出路..
答案 1 :(得分:2)
仅仅重命名C符号并不起作用,因为unix.ml模块有两个完全不同的版本(尽管具有相同的接口)。如果您静态链接您的代码,您将获得构建平台的代码,并且它不会在另一个平台上工作。
解决方案是创建和分发.cma存档(未链接的Unix模块)而不是可执行文件。然后使用ocaml
在目标平台上动态链接:
http://roscidus.com/blog/blog/2013/07/07/ocaml-binary-compatibility/#windows--linux-compatibility
更新:这不安全。执行ocaml /path/to/script.ml
时,它会将当前目录(而不是包含脚本的目录)添加到搜索路径的开头。因此:
$ cd /tmp
$ /usr/bin/myprog
首先会尝试从unix.cma
加载myprog的库(例如/tmp
)。
应该在4.03中修复:http://caml.inria.fr/mantis/view.php?id=6081