module Goaljobs:sig
..end
val target : bool -> unit
target
condition defines the target condition that will
be met once the current goal has run.
You can think of the target as a promise or contract that you make, which is met by running the rest of the goal.
Goaljobs is much more flexible than make
. In make
only a
single type of target is possible. The following are roughly
equivalent:
foo.o: foo.c ...
let goal compiled () = target (more_recent ["foo.o"] ["foo.c"]); require (file_exists "foo.c"); ...
Targets in goaljobs can be any arbitrary expression. For example, it can access network resources or test URLs.
Almost every goal should have one target, which should accurately state the outcome once the goal has been run.
It is possible to have no target. This means the goal always runs (like using "force" in make).
You should not have multiple targets in a single goal. They won't work the way you expect, and future versions of goaljobs will likely stop you from doing this.
Normally you put the target(s) early on in the goal, before any
running code and before any require
s. This is not a
hard-and-fast rule and it is not enforced, but doing it will
ensure the goal runs most efficiently since if the target is met
already then the rest of the goal doesn't run.
val target_all : bool list -> unit
target_all [t1; t2; ...]
is the same as writing
target (t1 && t2 && ...)
val target_exists : bool list -> unit
target_exists [t1; t2; ...]
is the same as writing
target (t1 || t2 || ...)
val require : (unit -> unit) -> unit
require
goal defines the requirements of this goal, that
is, other goals that have to be met before the rest of the
goal is able to run.
In terms of make
, require
s are roughly equivalent to the
right hand side after the :
, but in goaljobs the requirements
can be much richer than simply "that file must exist".
Some very simple goals don't need any require
s. You can
have as many require
s as you need in a goal, and you can
use a loop or make them conditional if you want.
Unlike make
, the requirements of a goal can be
placed anywhere within the goal, as long as you put them
before they are needed.
type
period_t =
| |
Seconds |
| |
Days |
| |
Months |
| |
Years |
val seconds : int * period_t
val sec : int * period_t
val secs : int * period_t
val second : int * period_t
val minutes : int * period_t
val min : int * period_t
val mins : int * period_t
val minute : int * period_t
val hours : int * period_t
val hour : int * period_t
val days : int * period_t
val day : int * period_t
val weeks : int * period_t
val week : int * period_t
val months : int * period_t
val month : int * period_t
val years : int * period_t
val year : int * period_t
val every : ?name:string -> int -> int * period_t -> (unit -> unit) -> unit
every N (seconds|minutes|hours|days|weeks|months|years) f
runs the function f
periodically.
The optional ~name
parameter can be used to name the job
(for debugging).
Various functions to test the existence of files, URLs.
val file_exists : string -> bool
This function also exists as a goal. Writing:
require (file_exists "somefile");will die unless
"somefile"
exists.val directory_exists : string -> bool
There is also a goal version of this function.
val file_newer_than : string -> string -> bool
file_newer_than file_a file_b
returns true if file_a
is
newer than file_b
. Note that if file_a
does not exist, it
returns false. If file_b
does not exist, it is an error.
There is also a goal version of this function.
val more_recent : string list -> string list -> bool
more_recent objects sources
expresses the make
relationship:
object(s) ...: source(s) ...
in a convenient way:
let goal built objects sources = target (more_recent objects sources); ... code to rebuild ...
It is roughly equivalent to checking that all the object files exist and are newer than all of the source files.
Note that both parameters are lists (since in make
you can
have a list of source files and a list of object files). If you
don't want a list, pass a single-element list containing the
single the object/source file.
There is also a goal version of this function.
val url_exists : string -> bool
There is also a goal version of this function.
val file_contains_string : string -> string -> bool
file_contains_string filename str
checks if the named file
contains the given substring str
.
There is also a goal version of this function.
val url_contains_string : string -> string -> bool
url_contains_string url str
downloads the URL and checks
whether the content contains the given substring str
.
There is also a goal version of this function.
val (//) : string -> string -> string
val quote : string -> string
val sh : ?tmpdir:bool -> ('a, unit, string, unit) Pervasives.format4 -> 'a
The command runs in a newly created temporary directory (which
is deleted after the command exits), unless you use
~tmpdir:false
.
val shout : ?tmpdir:bool -> ('a, unit, string, string) Pervasives.format4 -> 'a
Anything printed on stdout is returned as a string.
The trailing \n
character, if any, is not returned.
The command runs in a newly created temporary directory (which
is deleted after the command exits), unless you use
~tmpdir:false
.
val shlines : ?tmpdir:bool -> ('a, unit, string, string list) Pervasives.format4 -> 'a
Any lines printed to stdout is returned as a list of strings.
Trailing \n
characters are not returned.
The command runs in a newly created temporary directory (which
is deleted after the command exits), unless you use
~tmpdir:false
.
val shell : string Pervasives.ref
/bin/sh
).
Most string functions are provided by the OCaml standard
library (see the module String
). For convenience some
extra functions are provided here.
val change_file_extension : string -> string -> string
change_file_extension ext filename
changes the file extension
of filename
to .ext
. For example
change_file_extension "o" "main.c"
returns "main.o"
.
If the original filename has no extension, this function
adds the extension.val memory_exists : string -> bool
memory_exists key
checks that the named key
exists in
the Memory. It doesn't matter what value it has.
This is also available as a goal, so you can write
require (memory_exists key)
val memory_set : string -> string -> unit
key
to value
in the Memory.val memory_get : string -> string option
key
in the Memory. Returns None
if the key has never been set or was deleted.val memory_delete : string -> unit
key
. If the key doesn't exist, has no effect.val publish : string -> (string list -> unit) -> unit
Use this function as in this example:
let goal compiled program sources = ... stuff for building the program from sources ... let () = publish "compiled" ( fun args -> let program = List.hd args in let sources = List.tl args in require (compiled program sources) )
This could be used as follows:
./script compiled program main.c utils.c
You will notice you have to write a bit of OCaml code to
map the string arguments from the command line on to the
goal arguments. In the example it means taking the first
string argument as the program name, and the rest of the
string arguments as the source filenames. This is also
the place to perform string to int conversion, checks, and
so on (remember that OCaml is strongly typed).