【问题标题】:OCaml Compilation #use errorOCaml 编译#use 错误
【发布时间】:2019-10-25 15:49:44
【问题描述】:

我正在尝试编译带有调试器标志 -g 的 OCaml 文件,文件中包含以下行 -- #use "file2.ml"。为什么只要我有 use 关键字,文件就无法编译? “#use”关键字究竟是做什么的?有其他选择吗?

【问题讨论】:

    标签: ocaml


    【解决方案1】:

    # 开头的指令仅在*OCaml 解释器中受支持,也称为read-eval-print 循环。

    在顶层,#use 使解释器从文本文件中读取 OCaml 代码。之后它会继续以交互方式执行命令。

    对于已编译的代码,您应该单独编译,然后将您的模块链接在一起。如果file2.ml 中的代码没有形成完整的模块,您可能希望将其直接剪切/粘贴到主文件中。 OCaml 不像 C 系列那样包含编译时源文件。

    更新

    以下是如何以老式方式编译两个 OCaml 文件。你会发现有些人说这些方法已经过时了,你应该学会使用ocamlbuild。这可能是正确的,但我至少现在是老派。

    $ ocamlc -o program file2.ml file1.ml
    

    您必须按依赖顺序列出.ml 文件,即,一个文件必须在它使用的任何文件之后 列出。这已经是使用更强大的构建工具的原因之一。

    请注意,这与 #use 的行为不同,后者会将 file2.ml 的所有*名称加载到全局命名空间中。通过单独编译,来自file2.ml 的名称将包含在名为File2 的模块中。如果你想调用file2.ml中定义的函数f,你应该调用它为File2.f

    【讨论】:

    • 你是说file2.ml需要像这样用file1.ml编译? ocamlc -g file1.ml file2.ml
    • 我不知道谁说直接使用ocamlc 已经过时了,但这些人都是白痴。如果您想成为一名熟练的 OCaml 程序员,那么了解基本工具链的工作原理以及它们产生的构建工件是必不可少的。我强烈建议阅读并重新阅读manual 的第三部分
    • 如果您想成为一名熟练的程序员,最好开始使用 OCaml 进行编程。 OCaml 基础设施已经对新手非常不友好,因此,通过将他们指向低级工具来进一步提高标准是通往一个小而濒临死亡(但可能是精英?)社区的一种方式。
    • 对于它的价值,我认为将初学者问题的答案与关于这个问题的辩论混淆起来是不合适的。值得讨论,但不包括初学者提出的简单问题的答案。
    • 当然,这绝对是真的。
    【解决方案2】:

    TL;DR;

    使用ocamlbuild 驱动您的编译过程。

    ocamlbuild -clfags -g file1.native
    

    深入树林

    #use 是 OCaml 顶层中的特殊指令,换句话说,在 OCaml 解释器中。该指令是解释器为某些效果执行的特殊命令。它们不是语言的一部分。此外,不同的解释器有不同的指令。如果你想写一个 OCaml 程序,那么你需要编译,因为 OCaml 是一种编译语言。

    OCaml 带有一个非常下降的基础设施,这里有一个简短的指南。首先,有两种编译器,字节码和本机。字节码很慢(仍然比 Python 或 Ruby 快得多),但可移植。本机编译为本机机器代码,因此非常快。如果您可以访问这两个编译器,请使用后者。可以说,本机编译速度较慢,我会说在现代机器上差异可以忽略不计。

    过多的工具非常多,ocaml 用于解释器,ocamlc 用于字节码编译器,ocamlopt 用于本地编译,ocamldep 用于查找模块之间的依赖关系,ocamldoc 用于编译文档,@ 987654329@ 用于制作您自己的解释器,ocamlmklib 用于捆绑库,ocamlrun 用于运行字节码。我们也有ocamlfind 在您的系统上查找库。幸运的是,我们也有一个工具来统治他们,一个工具来找到他们,一个工具来把他们带到黑暗中并在黑暗中束缚他们

    ocamlbuild 来了。这个工具是 OCaml 语言发行版的一部分,它知道所有 9 个小工具的一切。因此,您实际上不需要学习它们就可以开始使用 OCaml 进行编程。 ocamlbuild 将找到所有依赖项、链接库,并为您创建任何您想要的内容,包括共享库或您自己的解释器。例如,要与core 库链接,只需传递-pkg core 选项。此外,ocamlbuild 有_tags 文件,它允许您存储参数并在命令行上节省一些空间。因此,始终将-g 选项(不是一个坏主意,顺便说一句)传递给编译器的另一种方法是将以下内容添加到您的_tags 文件中:

    debug : true
    

    既然您要添加此-g 选项,我怀疑您对回溯感兴趣。如果这是真的,那么不要忘记通过调用Printexc.record_backtrace 或设置环境变量OCAMLRUNPARAM=b 来启用回溯记录。

    【讨论】:

      【解决方案3】:

      我遇到了完全相同的问题,但我找到的解决方案是使用 cppo 预处理器中的 #include 指令。您可以在 OCaml 编译器的 -pp 开关中包含预处理器。

      【讨论】: