| 
  • If you are citizen of an European Union member nation, you may not use this service unless you are at least 16 years old.

  • Social distancing? Try a better way to work remotely on your online files. Dokkio, a new product from PBworks, can help your team find, organize, and collaborate on your Drive, Gmail, Dropbox, Box, and Slack files. Sign up for free.

View
 

Ocamlscript

Page history last edited by izan 8 years, 6 months ago

Documentation draft: follow OcamlscriptDoc

 

What is ocamlscript?

 

Ocamlscript is a tool which allows to use OCaml as a fast scripting language. The compilation process is performed as needed, and all the program and the compilation options are contained in one file.

 

The main advantage over traditional scripting languages is speed since now OCaml programs are compiled to native code, not only bytecode like the ocaml command does.

 

The main advantage over regular OCaml programs is that everything is contained in one file. No more tar.gz archives, no more Makefiles.

 

The main purpose of this page is to propose a preview of the next version of ocamlscript (ocamlscript 2) and discuss it before making a definitive release. Ocamlscript 2 is being developed by David Mentre and Martin Jambon.

 

Toward ocamlscript 2

 

Download the pre-release 1.99 now!

 

Files for ocamlscript 2 will be composed of two parts:

  • an optional header, which sets compilation options
  • the body, i.e. the program itself

 

The header is written in OCaml, and is optional. It is separated from the body by a line containing only "--" possibly followed by whitespace).

 

The body is by default handled using ocamlopt. The compilation commands can be configured and even completely redefined, so that the program itself may not be written in OCaml at all.

 

Example: I want a script which requires camlp4 preprocessing, and a runtime library which depends on other libraries. For instance, micmatch_pcre has this kind of requirement. If it was installed with ocamlfind, things are really easy. The script is just:

 

 

!#/usr/bin/env ocamlscript

OCaml.packs := ["micmatch_pcre"]

--

let _ = print_endline "Hello" (* or more *)

 

 

Here is a copy of the output of "ocamlscript -help" for the development version of the future ocamlscript 2:

 

 

Usage: ocamlscript PACKED_OPTIONS [ OPTIONS -- SCRIPTNAME ARGS ]

 

Ocamlscript normally reads the source code of a program from a file, looks

if a compiled executable exists for this program. If it exists and if it

is more recent than the source file, the executable is executed immediately,

otherwise it is updated by executing compilation instructions that can

be specified in the program file.

 

A typical self-executable script looks as follows:

 

#!/usr/bin/env ocamlscript

(* this is the compilation section, in OCaml *)

packs := ["unix"; "micmatch_pcre"]

--

(* this is the program section *)

let _ =

...

 

For a complete documentation, see http://????????

 

 

Structure of the command line:

 

PACKED_OPTIONS:

the first argument of ocamlscript. It is either unpacked into

several arguments that are passed to ocamlscript or into a script name

if this name doesn't start with "-". Double-quotes can be used

to enclose arguments that contain whitespace or double-quotes.

Double-quotes must be doubled. For instance, the following

self-executable script would be compiled into an executable named

Hello "World":

#!/usr/bin/ocamlscript -o "Hello ""World"""

print_endline "Hello "World""

 

Important note: on Unix, the whole '-o "Hello ""World"""' string

is passed as a single argument to ocamlscript. This is why the first

argument must be unpacked, even if ocamlscript is called explicitely

from the command line.

 

OPTIONS:

any number of arguments in this section are treated like options

to ocamlscript until a either a non-option is encountered, which is

understood as the script name (SCRIPTNAME) or "--" which stops

the list of arguments that are passed to ocamlscript.

 

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)

 

"--": passed as an argument to ocamlscript in the PACKED_OPTIONS argument

or in the OPTIONS argument marks the end of the arguments that

are passed to ocamlscript. Arguments that follow will be

interpreted as arguments of the script.

Arguments that follow "--" in the PACKED_OPTIONS argument

will be passed as arguments to the final executable. The first

argument that follows "--" in the OPTIONS command line arguments

is treated as the script name, unless the program is read from

another source, as specified by options "-e" (a string) or "-"

(standard input).

 

Compatibility with ocamlscript 1

 

Ocamlscript 2 will not be 100% compatible with ocamlscript 1, but the changes to convert a script from ocamlscript 1 to ocamlscript 2 are minor. Scripts of the form "#!/usr/bin/ocamlscript unix.cmxa" where there really is only one word after ocamlscript must be modified. "#!/usr/bin/ocamlscript unix.cmxa --" would work, but the recommended way is to do that:

 

#!/usr/bin/ocamlscript

Ocaml.packs := ["unix"]

It requires ocamlfind (Findlib). If ocamlfind is not installed or you don't want to use it, you can do that:

 

#!/usr/bin/ocamlscript

Ocaml.ocamlflags := ["unix.cmxa"]

Scripts starting like "#!/usr/bin/ocamlscript unix.cmxa str.cmxa" (more than one word) are still valid, although not recommended.

 

Questions? Suggestions?

 

Discuss here!

 

Q: is there a way to detect the directory of the running script inside the header? Eg, in most unices, one can use something like:

 

#!/bin/bash

JUNK=`dirname $0`

export SCRIPT_DIR=`cd $JUNK; pwd`

 

What I want is for a $PROJECT/test/foo.ml main to take some relative path files $PROJECT/thing1-3.ml and just include them from above (no cma files), regardless of where the source code is checked out. I want it to reduce to

 

 

ocamlopt $PROJECT/test/thing1.ml $PROJECT/test/thing2.ml $PROJECT/test/thing3.ml $PROJECT/test/foo.ml

Ocaml.ocamlflags := ["../thing1.ml"]

 

but I don't suppose that it will know what I mean since the current dir is probably reserved for where the script is run from, not where the script lives.

 

Obviously I could bang out an implementation in ocaml Sys, but I'd have to reproduce dirname because exec-ing is hard, etc. Seems like this should be an ocamlscript builtin.

 

A: Good suggestion. I added that feature in release 1.99.4. There is an example in the examples/ subdirectory of the package. In your example, you would do:

 

Ocaml.sources := ["../thing1.ml"]

It uses the Common.script_dir variable, which can also be set to something else if you prefer to make another directory the default for finding source files.

 

 

Q author (Jeff Henrikson):

 

Awesome, thanks for the quick response. I sat down for an hour today to implement it myself, but got stuck on what was considered "input", what needod to be copied, etc. Now I can just get yours.

 

A semi-obvious addition to my original comment: the builtin Filename.dirname provides almost identical if not idential functionality to the unix utility dirname. So with that and Sys.chdir, Sys.getcwd, and Sys.argv, one can translate the script directory hack literally.

 

I'm using this for benchmark testing, where I would use the toplevel for testing but I need ocamlopt to get anything like the final performance characteristics. This allows me to just bench test the modules that I need without mucking with my real makefiles. A huge help!

 

Q : Ocamlscript 2.02 build process gives an error with ocaml 3.12.1.

     I Have solved it changing ocamlp4 references to ocamlp5 in the build process. May be this solution should be permanent ? 

 

Comments (0)

You don't have permission to comment on this page.