Compiling and Running Ocaml Script from the Terminal - ocaml

I have files called assert.ml, assert.mli, test.ml and test.mli stored in a folder. assert is I guess you'd call it a library file--it's something I downloaded but didn't write myself. test.ml is a file containing the script
;; open Assert
;; print_endline "test"
In the terminal I navigate to the containing folder and run
$ ocamlc -c assert.mli test.mli
$ ocaml assert.ml test.ml
Nothing happens as a result. However, if I remove the ;; open Assert line from the script and run
$ ocaml test.ml
then it prints.
As a note, I've had some people tell me not to write the open command as ;; open Assert but the advice seems entirely stylistic. I have to write it this way for the class I'm taking.
If anyone can explain to me how I ought to be compiling and running differently I'd appreciate it. I tried following some other guides' advice in using ocamlopt instead but when I ran it, no executable file was produced as a result.

The ocaml command is the REPL for OCaml. The command line looks like this:
ocaml [ object-files ] [ script-file ]
An object file is a compiled (bytecode) module, which is produced by the ocamlc command. These files end with .cmo. A script file is a file of OCaml source code, which ends with .ml.
Note that only one script file is allowed.
The command you say you're using has two script files and no object files. So, it's not surprising that it doesn't work. In my experiments, what ocaml does is run just the first of the two script files. I believe this explains what you see. One of your files produces output, and it will be run if you give it first. The other produces no output, so there is no output when that file is given first.
What you should probably be doing is producing a .cmo file for the Assert module.
That would look like this:
$ ocamlc -c assert.mli assert.ml test.mli
Then you should run ocaml with one object file and one script file, like this:
$ ocaml assert.cmo test.ml

Related

Unbound Module (Personal Files)

I have two .ml files, type.ml and main.ml, in the same directory.
I am following this official link: https://ocaml.org/docs/modules
File main.ml:
open Type
let () = print_endline "Hello World!"
I compile with this line, accordingly to the tutorial:
ocamlopt -o main main.ml type.ml
However, I have this error:
Error: Unbound module Type
The source files need to be ordered with the dependencies coming before the dependent. That is, it should be:
ocamlopt -o main type.ml main.ml
This is somewhat vaguely explained in the manual:
The order in which .cmx and .ml arguments are presented on the command line is relevant: compilation units are initialized in that order at run-time, and it is a link-time error to use a component of a unit before having initialized it. Hence, a given x.cmx file must come before all .cmx files that refer to the unit x.
Also, if you're doing anything more significant I would recommend using a build system like dune to avoid having to mess with details like this.

Why does "./a.out" only run the last compiled executable program and not the previous ones?

I have taken my first two courses in java and now have to take Data Structures in C++. I'm trying to open up the different files I've compiled.
They're just two "Hello, world!" programs with slightly different text.
When I type:
g++ HelloWorld.cpp
The file "a.out" is created which I run by typing ./a.out into the command prompt.
Now that I compiled a second executable program, HelloWorldII.cpp, the a.out file only runs that program.
When I try to run ./HelloWorld.cpp I got permission denied, so I typed in:
sudo chmod 744 /Users/username/HelloWorld
to make me the owner of the folder which didn't work so I typed in:
sudo chown -R "$garyjones:" users/username/HelloWorld
to give the owner(me) permission to edit/open, after which when I attempted to run ./HelloWorld.cpp, terminal began to attempt executing it but instead showed me syntax error even though compiling them with g++ HelloWorld.cpp and running them with their a.out files worked fine.
If I have multiple executable files in a folder, how can I open the one I want?
When you compile and link code, the executable is by default named a.out - you are supposed to add a parameter to the linking to name it.
If you don’t do it, they are all going to be named a.out, and of course overwrite each other - there can be only one file with that name.
It is strange for you attempting to execute a pure ascii text file. You don't understand the execution mode's meaning. You are not familiar with g++. It seems like you don't know the process of how an executable file generated by compiler from source file.
And here is my advice.
Google the basic usage of g++ or some other compilers. Choose your favourite.
Here is the temporary solution.
g++ <source file> -o <executable filename>
Example:
## if you don't specific a name for the binary file,
## it will generate a.out and delete the exiting a.out firstly
g++ HelloWorld.cpp -o HelloWorld
## and then you can execute it
./HelloWorld
Figure out what the exact meaning of file permission.
The a.out filename has traditional reason and I recommend you to explore it. It's funny.

Ocamldoc and open modules

I'm trying to document a small project of mine using ocamldoc.
I have one main .ml file which opens two others .ml files.
$ ocamldoc -html included1.ml included2.ml
Works just fine, but when I add the including file, like
$ ocamldoc -html included1.ml included2.ml including.ml
I get this:
File "including.ml", line 5, characters 5-16:
Error: Unbound module Included1
1 error(s) encountered
I see from the ocamldoc documentation that opening modules is perfectly fine, until no conflict arises.
How should I proceed?
It's fine for a module to use other modules however it needs to be able to see the compiled interfaces for those. So in your case you first need to compile the .ml files to generate .cmi files. Then you need to indicate to ocamldoc where these files are. So something like this should do:
ocamlc -c included1.ml
ocamlc -c included2.ml
ocamlc -c -I . including.ml
ocamldoc -html -I . included1.ml included2.ml including.ml
Note that in general it's a good (essential) practice to create .mli files for each of your modules an document and ocamldoc these rather than the .ml files.

OCamlbuild not resolving subdirectory dependency

I have an OCaml project and I'm running into a weird issue.
The directory structure looks like this:
./tests
test.ml
templatetest.ml
./src
template.ml
...
andsoforth.ml
I am building it like this:
ocamlbuild -Is src,tests tests/test.native
Key point being, tests/test.ml depends on tests/templatetest.ml.
When I build it, I get:
+ /usr/local/bin/ocamlc.opt -c -I tests -I src -o tests/test.cmo tests/test.ml
File "tests/test.ml", line 1, characters 0-17:
Error: Unbound module TemplateTest
Command exited with code 2.
Compilation unsuccessful after building 2 targets (0 cached) in 00:00:00.
I tried adding a _tags file in the top directory containing:
<src> or <tests>: include
That still produced the same error. (I believe ocamlbuild tests/test.native with the _tags file is the exact same thing as the previous build line I used.)
I also created an empty _tags file in both ./tests and ./src, but that didn't change anything either.
Any suggestions? If you need, the entire source is here. Just run make test. Thanks!
It a funny issue: not TemplateTest but Templatetest. For the former name, you module file should be named templateTest.ml

Creating an OCaml library

I am trying to create a library that I can use in other OCaml projects, and I'm totally lost.
I'm currently using ocamlbuild which is great for spitting out executables, but I don't know how to get a library out of it.
I've discovered the -a option in ocamlopt and ocamlc but I'm not really sure how to use it. The documentation I've found (for example, here), seems to assume some preexisting knowledge. I don't even know what a .a file is. After I run that, which of the outputted files do I need to build a project that depends on this library? Do I need the mli files so that the application knows the signatures of the library code, or is that included in the output somehow? Also, it would be nice to be able to package all the files together, something similar to a .jar file for Java.
In any case, I would love for ocamlbuild to do all of this for me, since if I have to invoke ocamlopt -a I will have to either manually specify dependencies or hack a script around ocamldep -- something that ocamlbuild was supposed to fix. However, I don't know how to tell it to build a library.
I'm willing to use oasis or OPAM or something if it's necessary, but I would like to learn how to do this using just the basic tools first.
OCamlbuild has some built-in functionality for building libraries, so you can get started with just ocamlbuild foo.cma foo.cmxa (assuming foo.ml is your entry point). This will invoke ocamlopt -a and ocamlc -a for you, handling all the dependency plumbing and leaving the generated files inside _build.
That should be enough to let you compile a library and link it from another program. Since this is just a test you can simply point at the aforementioned _build with -I when compiling the program that uses the library. For real use a library should be packaged - when you get to that point you'll want to look into ocamlfind, oasis, etc.
Have a look at the ocaml.org tutorial on compiling OCaml projects. Additionally the official manual for the bytecode and native code compilers contains useful detail on producing and using the various types of files.
The documentation for ocamlbuild archives seems to cover this pretty well.
In any case, here's one way to do ocaml libraries. Let's say you have a directory called foo containing your .ml, .mli, and .mllib files. Let's say it contained bar.ml, bar.mli, baz.ml, and baz.mli. To distribute all this as one library, you'd also have a foo.mllib in that directory, whose contents are
Bar
Baz
Then to compile, do
$ ocamlbuild -use-ocamlfind foo.cma foo.cmxa
Here is an example.
Then to use your library foo, let's say you had a sibling directory called main, and main contains main.ml, _tags, myocamlbuild.ml.
myocamlbuild.ml should have the following contents:
open Ocamlbuild_plugin
open Command
let () =
dispatch (
function
| After_rules ->
ocaml_lib
~extern:true
~dir:"/path/to/foo/_build"
"foo"
| _ -> ()
)
_tags should have the following contents:
<main.{ml,native,byte}>: use_foo
Compile main.ml with
$ ocamlbuild -use-ocamlfind main.byte main.native
run with
$ ./main.byte
$ ./main.native
More information here as well: https://ocaml.org/learn/tutorials/ocamlbuild/Using_an_external_library.html