Reputation: 193
I am currently teaching myself ocaml
for my programming language class and I am having trouble compiling multiple files in ocaml
.
I have defined a function in my get_file_buffer.ml
file
Source code of 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. *)
;;
I am trying to call the function in my main.ml
Source code of 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 *)
In order to compile the program I am using a MakeFile
Makefile content
.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
When I run the test
rule of my Makefile
I get the error:
Error: Unbound module Get_file_buffer
.
I have been trying to use these question as references: Compiling multiple Ocaml files and Calling functions in other files in OCaml.
Yet I have not been able to get the program to compile correctly. How would I correctly compile the above code to make the program run correctly?
Upvotes: 1
Views: 1342
Reputation: 2423
Rather than build *.ml files one by one. You have a couple of better options which are both productive and effective.
Use ocamlbuild with Makefile like so.
Rename main.ml
to start.ml
and use the following Makefile
.
$ cat Makefile
.PHONY: all test
all: start test
test: start
@./start.native get_file_buffer.ml
start:
ocamlbuild start.native
$ make ....
Use dune(formerly jbuilder) which is far the most coherent build tool for ocaml these days.
a. Create a jbuild
file in the same directory as the *.ml
files.
$cat jbuild
(jbuild_version 1)
(executable
((name start)))
$ jbuilder build start.exe
$ jbuilder exec -- ./start.exe get_file_buffer.ml
If you prefer you can use make
to drive dune/jbuilder
by creating a 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
Upvotes: 2
Reputation: 18912
Writing a correct Makefile for OCaml is complicated: OCaml compilers tend to produce multiple files which is not something that Makefile handles gracefully, moreover the exact dependency graph might depend on the compiler flags (e.g. -opaque
or -no-alias-deps
) and the version (bytecode, native without flambda, native with flambda) of the compiler. That's why the easiest solution by far is to use a build system like jbuilder/dune(http://dune.readthedocs.io/en/stable/), or ocamlbuild (https://github.com/ocaml/ocamlbuild/blob/master/manual/manual.adoc).
p.s. : in your case, you are indeed missing the dependency of main.cmx
to get_file_buffer.{cmi,cmx}
.
Upvotes: 4
Reputation: 1418
I believe the problem is that main.cmx
should depend on get_file_buffer.cmx
. Otherwise make
might try to compile main.cmx
first, in which case of course the module Get_file_buffer
cannot be found because it does not yet exist.
More precisely, the compilation of main.cmx
also depends on gen_file_buffer.o
. But as that file is created at the same time as gen_file_buffer.cmx
, you should be fine. (And to my limited knowledge it is not possible with make
to specify that a single rule creates more than one file at the same time.)
Upvotes: 0