如何在OCaml中编译多个文件?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在OCaml中编译多个文件?相关的知识,希望对你有一定的参考价值。

我目前正在教自己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

当我运行我的testMakefile规则时,我得到错误:Error: Unbound module Get_file_buffer

我一直试图用这些问题作为参考:Compiling multiple Ocaml filesCalling functions in other files in OCaml

但是我还没能让程序正确编译。如何正确编译上面的代码以使程序正常运行?

答案

而不是逐个构建* .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

$ make ....

使用沙丘(以前的jbuilder),这是目前最为连贯的ocaml构建工具。

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

$ cat jbuild

(jbuild_version 1)

(executable
 ((name start)))

$ jbuilder build start.exe

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

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

$ cat Makefile

.PHONY: all test

all: start test

test: start
    jbuilder exec -- ./start.exe get_file_buffer.ml

start:
    jbuilder build start.exe

$ make

另一答案

为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}的依赖。

另一答案

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

更准确地说,main.cmx的编辑也取决于gen_file_buffer.o。但由于该文件与gen_file_buffer.cmx同时创建,你应该没问题。 (据我所知,make无法指定单个规则同时创建多个文件。)

以上是关于如何在OCaml中编译多个文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何可选地提供 OCaml (let*) 运算符以与新旧编译器一起使用?

OCaml 中的依赖类型

如何为Ocaml项目生成正确的makefile

如何在 utop 中重新加载 OCaml 模块

如何在 Ocaml 中使用多核进行蒙特卡罗模拟?

为啥 OCaml 中的模块类型注释会导致此代码无法编译?