OCaml - 将程序编译为库

时间:2013-03-04 11:26:26

标签: ocaml

我有一个OCaml程序(使用main方法 - 它生成一个可执行文件),我想将它用作库。

我正在编译我的程序:ocamlc -I someDir -g -unsafe lotsOfCmoFiles -o outputFile,程序运行正常。

现在我删除使其成为可执行文件的行(类似let _ = ...)并添加-a参数以编译命令:ocamlc -a -I someDir -g -unsafe lotsOfCmoFiles -o outputFile.cma

但不知怎的,我无法使用ocamltop加载生成的.cma文件,ocamlbrowser显示空列表。当我尝试从ocamltop

加载时
# #load "outputFile.cma";;
Error: Reference to undefined global `Xyz'

而且我100%确定xyz.cmo包含在lotsOfCmoFiles中。

编译时我给出了一些参数错误吗?或者,我应该怎么做才能在ocamltop中加载我的程序? (我将在另一个程序中使用此库,我将ocamltop输出作为示例)

任何帮助将不胜感激。

编辑:所以我终于可以设法编译并加载它了,感谢@cago,现在我可以加载我的库,当我不删除主let _ = ...行时,它会在我加载{{}时自动运行{1}}。

但我还是无法打开任何模块。奇怪的是,这不会引发异常

.cma

但是当我从模块Main调用一个函数时:

open Main

# someFun;; Error: Reference to undefined global `Main' 仍显示空列表。现在为什么会这样?

EDIT2:我意识到ocamlbrowse没有失败,因为我在同一文件夹中有一个主模块(即使我没有明确加载它)。如果我将.cma文件移动到其他地方并加载它,它就可以工作(即主函数自动运行),但是现在我无法打开任何模块,即使open Main显示模块。

EDIT3: - 我没有帮助:

ocamlobjinfo

2 个答案:

答案 0 :(得分:8)

lotsOfCmoFiles中的某些cmo需要知道模块Xyz。您需要处理cmo文件之间的依赖关系。

例如:

toto.ml:

let x = "toto"

titi.ml:

let y = Toto.x ^ " titi"

ocamlc -c toto.ml
ocamlc -c titi.ml
ocamlc -a  titi.cmo toto.cmo -o lib.cma (* here is  the probleme *)

# #load "lib.cma"
Error: Reference to undefined global `Toto'

因为titi取决于toto所以你需要改变cmos的顺序:

ocamlc -a toto.cmo titi.cmo -o lib.cma 

# #load "lib.cma"
# Titi.y;;
 - : string = "toto titi"

编辑:

如果您的cma位于子目录中,例如,当您致电ocaml时,您需要指定路径:

ocaml -I subdir/ (* subdir which contains lib.cma *)

# #load "lib.cma"
# Toto.x;;
- : string = "toto"

答案 1 :(得分:0)

TL; DR:确保

中没有任何顶级副作用

我遇到了同样的麻烦。我的项目将构建良好,大多数模块都可用,但有一个模块一直触发Reference to undefined global。但很明显,该模块对系统是可见的:它显示在utop的自动完成列表中,以及它的所有值,我可以引用它并将其导入其他模块。

问题结果是加载该模块时抛出的未捕获异常。该异常是由于尝试加载不存在的文件。它在复杂化过程中不会引起问题,但是当模块实际被加载时,它会被破坏,异常在我看到它之前就被吞噬了。