See also Ocamlscript. This page is now somewhat obsolete, although some things are explained more nicely here than in other places.
Documentation for Ocamlscript 2.0 (in progress)
Ocamlscript is a utility for compiling and running OCaml scripts. As opposed to the standard ocaml
command, it compiles the program to native code instead of byte code, which usually makes the program faster. In addition to that, it recompiles the script only when an update is required by comparing the last modification date of the script and the compiled executable, so compilation is performed once, unlike scripts that use the ocaml
command.
The scripts themselves are pure OCaml, by they are normally preceded by a dedicated header where compilation options are specified. A variety of compilation options for OCaml are supported, including support for camlp4 and ocamllex. Complex libraries may be easily loaded using the Findlib package management system.
Ocamlscript compilation relies on a dedicated header, whereas ocaml
relies on special directives such as #load
or #require
which are inserted in the program but are not valid for ocamlc
or ocamlopt
compilers.
Here is a script written for the ocaml
, followed by the equivalent version using ocamlscript
. They both load the PCRE-OCaml library using Findlib:
#!/usr/bin/ocamlrun ocaml
#use "topfind"
#require "pcre"
let _ = ...
#!/usr/bin/ocamlscript
Ocaml.packs := ["pcre"]
--
let _ = ...
Foreword about Unix scripts in general
The shebang (#!
) line in Unix scripts is a line which tells the operating system how to execute a given file, when it is used directly as a command. How it works is out of the scope this tutorial and varies slightly from one OS to another.
In our examples we will assume that the ocamlscript command resides in /usr/bin
, although it could be anywhere else. Our scripts will therefore start with #!/usr/bin/ocamlscript
. The location of ocamlscript can also be found automatically in the directories specified by the PATH environment variable using the /usr/bin/env
command, which hopefully will be at this place on every system. In that configuration, the first line of a script would be #!/usr/bin/env ocamlscript
.
Please note that using this mechanism is optional. Any script can be executed using ocamlscript name-of-your-script
.
Basic usage
A simple program that should be compiled with no options and no libraries is a plain OCaml program, may start with a shebang line and its name can be chosen freely:
#!/usr/bin/ocamlscript
print_endline "Hello"
This program named hello
will be compiled if necessary and executed by the following command:
Run it a second time and you should notice that it is faster since it doesn't need a recompilation.
We are assuming a Unix-kind of OS where ocamlscript
is installed in /usr/bin
, so after making the file executable (chmod u+x hello
), we can also execute it as a command:
You can notice that in the same directory as the hello file, a file hello.exe has been created. It is the binary executable version of the hello script, automatically compiled with the native code compiler. Each time you modify the original script hello, the compiled version hello.exe is re-compiled. Ocamlscript determines if a recompilation is needed based on the last modification date of the source script.
Loading libraries
Almost any useful script will require some libraries. Such compilation options need to be specified in a dedicated section of the ocamlscript script called the header. This first section is a short, specialized OCaml program which comes before the main script:
#!/usr/bin/ocamlscript
(* this is the header *)
Ocaml.packs := ["pcre"]
(* here comes the separator *)
--
(* this is the script *)
open Pcre
let _ =
...
The recommended way of loading libraries is to use the Findlib package manager. The example above shows that Findlib packages, i.e. those which have been installed with ocamlfind
, can be loaded by setting the Ocaml.packs
variable. Ocaml.packs
has type string list ref: it is a global variable which holds the list of Findlib packages to use. The following aspects are taken care of automatically:
- library location: you don't have to specify where each library is located, so it makes your scripts more portable;
- dependencies: libraries that are required by a given package are automatically loaded;
- syntax extensions: packages which provide a Camlp4 syntax extension pass the appropriate arguments to the preprocessor, so a single package name is enough to load both syntax and runtime libraries.
Now, if for some reason a library was not installed with Findlib but you know where it is located (maybe it is a library file in the current directory or a wild installation in OCaml standard library's directory), you can pass it to the compiler by using the Ocaml.ocamlflags
variable. Like Ocaml.packs
, it is a list of strings. Those strings can be any valid option that you may want to pass directly to ocamlopt
. For example, here is how I could load a native code library named mylib.cmxa
:
#!/usr/bin/ocamlscript
Ocaml.ocamlflags := ["mylib.cmxa"]
--
(* the modules provided by mylib.cmxa are now available *)
let _ =
...
Several other options can be more conveniently set using dedicated variables provided by the Ocaml module.
Multiple source files - "includes"
It is possible to use several source files instead of just one. There is still a main script, which will be read directly by ocamlscript
, but the header of that script can instruct the compiler to use, compile and link other files. These other files are specified by the Ocaml.sources
variable:
#!/usr/bin/ocamlscript
(* this is our main script, which uses 3 other source files *)
Ocaml.sources := ["../thing1.ml"; "thing2.ml";
"/home/lib/thing3.ml"]
--
open Thing1
open Thing2
open Thing3
...
The paths to these source files can be absolute or relative to the directory of the main script.
However, these files must be pure OCaml source files, with the usual constraints:
- implementation files end in .ml,
- interface files end in .mli,
- their name without extension must be a valid module name once capitalized (e.g. no dash or space in their name),
- files other than implementation (.ml) or interface (.mli) units are not supported yet.
The same compilation options, including Camlp4 preprocessing, are applied to the main script and to those files.
For speed purposes, a recompilation of the sources will be triggered only by comparing the last modification date of the main script against the last modification date of the executable (.exe). None of the "included" source files will be checked for modifications. To force a recompilation while developing, use ocamlscript -f your-main-script
, or even ocamlscript -c -f your-main-script
if you don't want to execute the program after compiling.
Compilation only
Recommended uses
Using a whole different compiler than ocamlopt
Technicalities
Installation
You will need following software:
Compilation:
Installation:
By default, the ocamlscript command is installed in the same directory as the ocamlfind command. In the following we assume it is /usr/bin/.
Uninstallation:
Switching from Ocamlscript 1 to Ocamlscript 2
For compatibility with Ocamlscript 1, libraries can still be passed directly on the command-line or on the shebang line. This is now deprecated, but it can be a quick way to make older scripts compatible with Ocamlscript 2. The rule of thumb is: if only one library is given, add the phony argument "--" at the end, otherwise no change should be necessary. For example, if you had a script like that:
#!/usr/bin/ocamlscript unix.cmxa
(* Ocamlscript1 script *)
open Unix
...
You must change it into this:
#!/usr/bin/ocamlscript unix.cmxa --
(* Ocamlscript2-compatible script *)
open Unix
...
Reference manual (in progress)
Syntax
Command-line usage
Ocamlscript supports the following options:
-- | marks the end of ocamlscript arguments |
-help | displays a help message and exit |
--help | same as -help |
-c | compile only |
-o EXEC_NAME | specify a name for the executable (required if the program is not read from a file) |
-e PROGRAM | execute the code given here instead of reading it from a file |
-f | force recompilation which is otherwise based on modification dates |
-debug | print messages about what ocamlscript is doing |
-version | prints the version identifier to stdout and exit |
- | read program from stdin instead of a file |
-vm VIRTUAL_MACHINE | run the executable using this virtual machine (e.g. ocamlrun) |
Those arguments can be given on the command line calling ocamlscript (ocamlscript -debug name_of_my_script) or on the shebang line of script (#!/usr/bin/ocamlscript -debug). fixme: true??
The Ocaml compilation module
The Ocamlscript.Ocaml module defines following global variables:
| Type | Meaning |
camlp4o | string ref | name of camlp4o command |
camlp4r | string ref | name of camlp4r command |
ocamllex | string ref | name of ocamllex command |
ocamlc | string ref | name of ocamlc command |
ocamlopt | string ref | name of ocamlopt command |
ocamlfind | string ref | name of ocamlfind command |
packs | string list ref | findlib packages |
use_ocamllex | bool ref | (default: false) if true, preprocess with ocamllex before camlp4 |
use_camlp4 | bool ref | (default: true) if true, use camlp4 |
use_ocamlc | bool ref | (default: false) if true, use ocamlc instead of ocamlopt |
use_ocamlfind | bool ref | (default: false) if true, force the use of ocamlfind |
revised | bool ref | (default: false) if true, use revised syntax |
ocamlflags | string list ref | any options that you may want to pass to ocamlopt |
ppopt | string list ref | ny options that you may want to pass to camlp4o or camlp4r |
"Ocaml" is a submodule of the "Ocamlscript" module.
Ocamlscript also provides a global "Common" submodule and a "Pipeline" submodule. Their purpose is to make the integration of compilers for other languages easier. These modules are fully documented.
Comments (0)
You don't have permission to comment on this page.