【问题标题】:How to compile multiple files in OCaml?如何在 OCaml 中编译多个文件?
【发布时间】:2018-03-05 10:07:13
【问题描述】:

我目前正在为我的编程语言课自学ocaml,我在编译ocaml 中的多个文件时遇到问题。

我在get_file_buffer.ml 文件中定义了一个函数

get_file_buffer.ml的源码

(* 
   Creating a function that will read all the chars 
   in a file passed in from the command argument.
   And store the results in a char list. 
*)

let read_file char_List =
    let char_in = open_in Sys.argv.(1) in   (* Creating a file pointer/in_channel *)
  try
    while true do
      let c = input_char char_in in         (* Getting char from the file *)
            char_List := c :: !char_List    (* Storing the char in the list *)
    done
  with End_of_file ->
        char_List := List.rev !char_List;   (* End of file was reaching, reversing char list *)
        close_in char_in;                   (* Closing the file pointer/in_channel *)

    (* Need to figure out how to catch if the file was not openned. *)
;; 

我正在尝试在我的 main.ml 中调用该函数

main.ml的源码

(* Storing the result of read_file to buffer which buffer is a char list reference *)
let buffer = ref [] in
      Get_file_buffer.read_file(buffer);

      print_string "\nThe length of the buffer is: ";
      print_int (List.length !buffer); (* Printing length of the list *)
      print_string ("\n\n");
      List.iter print_char !buffer;    (* Iterating through the list and print each element *)

为了编译程序,我使用了MakeFile

Makefile 内容

.PHONY: all
all: test

#Rule that tests the program
test: read_test
    @./start example.dat

#Rules that creates executable
read_test: main.cmx get_file_buffer.cmx
    @ocamlc -o start get_file_buffer.cmx mail.cmx

#Rule that creates main object file
main.cmx: main.ml
    @ocamlc -c main.ml

#Rule that creates get_file_buffer object file
get_file_buffer.cmx: get_file_buffer.ml
    @ocamlc -c get_file_buffer.ml

当我运行 Makefiletest 规则时,我收到错误: Error: Unbound module Get_file_buffer.

我一直在尝试将这些问题用作参考: Compiling multiple Ocaml filesCalling functions in other files in OCaml.

但我还没有让程序正确编译。如何正确编译上述代码,使程序正常运行?

【问题讨论】:

  • 与您的问题无关,您的read_test 规则调用mail.cmx 而不是main.cmx

标签: compiler-errors compilation ocaml


【解决方案1】:

为 OCaml 编写正确的 Makefile 很复杂:OCaml 编译器倾向于生成多个文件,这些文件不是 Makefile 可以优雅处理的,而且确切的依赖关系图可能取决于编译器标志(例如 -opaque-no-alias-deps)和编译器的版本(字节码,没有 flambda 的原生,带 flambda 的原生)。这就是为什么迄今为止最简单的解决方案是使用像 jbuilder/dune(http://dune.readthedocs.io/en/stable/) 或 ocamlbuild (https://github.com/ocaml/ocamlbuild/blob/master/manual/manual.adoc) 这样的构建系统。

附言:在您的情况下,您确实缺少 main.cmxget_file_buffer.{cmi,cmx} 的依赖关系。

【讨论】:

    【解决方案2】:

    而不是一个一个地构建 *.ml 文件。您有几个更好的选择,既高效又高效。

    像这样将 ocamlbuild 与 Makefile 一起使用。

    main.ml 重命名为start.ml 并使用以下Makefile

    $ cat Makefile

    .PHONY: all test
    
    all: start test
    
    test: start
        @./start.native get_file_buffer.ml
    
    start:
        ocamlbuild start.native
    

    $ 制作 ....

    使用 dune(以前的 jbuilder),它是目前 ocaml 最连贯的构建工具

    一个。在与*.ml 文件相同的目录中创建一个jbuild 文件。

    $cat jbuild

    (jbuild_version 1)
    
    (executable
     ((name start)))
    

    $ jbuilder build start.exe

    $ jbuilder exec -- ./start.exe get_file_buffer.ml

    如果您愿意,可以通过创建Makefile 来使用make 驱动dune/jbuilder

    $cat 生成文件

    .PHONY: all test
    
    all: start test
    
    test: start
        jbuilder exec -- ./start.exe get_file_buffer.ml
    
    start:
        jbuilder build start.exe
    

    $ 制作

    【讨论】:

    • 感谢@Bikal Lem 的帮助。我已经用你建议的第一种方法编译了程序。
    【解决方案3】:

    我认为问题在于main.cmx 应该依赖于get_file_buffer.cmx。否则make 可能会尝试先编译main.cmx,在这种情况下当然找不到模块Get_file_buffer,因为它还不存在。

    更准确地说,main.cmx 的编译也依赖于gen_file_buffer.o。但是由于该文件是与gen_file_buffer.cmx 同时创建的,所以应该没问题。 (据我所知,make 不可能指定一个规则同时创建多个文件。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-26
      • 1970-01-01
      • 2015-05-20
      • 2011-12-12
      • 1970-01-01
      • 1970-01-01
      • 2020-10-25
      • 1970-01-01
      相关资源
      最近更新 更多