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

时间:2018-03-05 10:07:14

标签: compiler-errors compilation 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

当我运行test的{​​{1}}规则时,我收到错误消息: Makefile

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

然而,我无法让程序正确编译。如何正确编译上面的代码以使程序正确运行?

3 个答案:

答案 0 :(得分:4)

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

P.S。 :在您的情况下,您确实错过了-no-alias-depsmain.cmx的依赖关系。

答案 1 :(得分: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

$ make ....

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

一个。在与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

答案 2 :(得分:0)

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

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