Module Godi_script


module Godi_script: sig .. end
This module contains library functions for GODI configuration scripts written in OCaml. This is mainly intended for the conf-foo packages.

In order to activate such a script, define the following variables in the driver Makefile of conf-foo:

A number of environment variables are automatically passed to this script:




Primitives


val runcmd : string -> int
Starts the command, waits for its completion, and returns the exit code. Similar to Sys.command, but preferable.
val runcmdf : ('a, unit, string, int) format4 -> 'a
Same as runcmd, but accepts a printf-like format string.
val read_file : string -> string
Reads the file into memory, and returns it as string
val write_file : string -> string -> unit
Writes to the file whose name is passed as first argument the contents passed as second argument.
val read_from_cmd : string -> int * string
Starts the command, reads its output (stdout), waits for its completion, and returns both the exit code and the output.
val read_from_cmdf : ('a, unit, string, int * string) format4 -> 'a
Same as read_from_cmd, but accepts a printf-like format string.
val env : string -> string
Returns the named environment variable, or "" if the variable does not exist.
val env_opt : string -> string option
Returns the named environment variable, or None if the variable is empty or does not exist.

Commandlets



A "commandlet" is a command function that takes a state variable as input and that returns the possibly modified state variable as output. The state variable contains the exit code of the last executed shell command, and optionally a further result value.

Remember that the exit code 0 means that the command was successful.

type 'a cmdstate 
The state with further values of type 'a
val code : 'a cmdstate -> int
The current exit code
val result : 'a cmdstate -> 'a option
The current result value
val return_code : int -> 'a cmdstate -> 'a cmdstate
Returns the modified state where the code is set to the int
val return_result : 'a option -> 'a cmdstate -> 'a cmdstate
Returns the modified state where the result is set
val initial_state : unit -> 'a cmdstate
The initial state has code 0, and no result value
type 'a cmdlet = 'a cmdstate -> 'a cmdstate 
A commandlet is a function taking state and returning state
val cmd : string -> 'a cmdlet
The commandlet that executes the passed command (as string). The exit code is set in the resulting state.
val cmdf : ('a, unit, string, 'b cmdlet) format4 -> 'a
Same as cmd but accepts a printf-like format string
val cmd_output : string -> string cmdlet
The commandlet that executes the passed command (as string), and reads the output of the command (stdout). The exit code is set in the resulting state, and the output is returned as result value.
val cmdf_output : ('a, unit, string, string cmdlet) format4 -> 'a
Same as cmd_output but accepts a printf-like format string
val set_code : int -> 'a cmdlet
The commandlet that sets the exit code to the passed integer
val set_code_from : ('a cmdstate -> int) -> 'a cmdlet
The commandlet that calls the function, and sets the exit code from the integer result of the function.
val set_bool_code : bool -> 'a cmdlet
The commandlet that sets the exit code to 0 if the boolean is true, and to 1 if the boolean is false.
val set_bool_code_from : ('a cmdstate -> bool) -> 'a cmdlet
The commandlet that calls the function, and sets the exit code from the boolean result of the function (as set_code_bool).
val (&-) : 'a cmdlet -> 'a cmdlet -> 'a cmdlet
Conditional sequencing: If the first commandlet returns the exit code 0, the second commandlet is also executed (like the "&&" shell operator).
val (|-) : 'a cmdlet -> 'a cmdlet -> 'a cmdlet
Conditional sequencing: If the first commandlet returns a non-zero exit code, the second commandlet is also executed (like the "||" shell operator).
val ignore_code : 'a cmdlet -> 'a cmdlet
Executes the commandlet, and ignores the exit code, i.e. sets it always to 0.
val eval : 'a cmdlet -> 'a option
Evaluates a commandlet, and returns the result value. Note that None is always returned if the exit code is non-zero, regardless of whether there is a result value or not.
val eval_test : 'a cmdlet -> bool
Evaluates a commandlet, and returns true if the exit code is 0, and false if the exit code is non-zero.

Example: This piece of code returns the file listing of "/a" if readable, or otherwise the file listing of "/b":

 
 eval (cmd_output "ls /a" |- cmd_output "ls /b")
 

Loops should be programmed with recursion, or by folding:


 eval
   (List.fold_left
     (fun acc x ->
        acc |- cmdf_output "ls %s" (Filename.quote x))
     (set_bool_code true)
     [ "/a"; "/b"; "/c" ]
   )
 


Logging



Logging outputs to "script.log" in the cwd.
val log : string -> unit
Appends the string to the log file.
val logf : ('a, unit, string, unit) format4 -> 'a
Same as log, but accepts a printf-like format string

Finding C libraries



type c_env = {
   c_incdirs : string list; (*List of directories for "#include"*)
   c_libdirs : string list; (*List of library directories*)
   c_libs : string list; (*Names of libraries (w/o "lib" and suffix)*)
   c_flags : string list; (*Further flags for C compiling*)
   ld_flags : string list; (*Further flags for linking*)
   elf_rpath : bool; (*Whether c_libdirs must be added to the runtime lookup path*)
   config_script : string option; (*The name of a foreign config script*)
   godi_deps : string list; (*List of additional GODI dependencies to output*)
}
The environment to compile and link the mentioned libraries. The c_incdirs can be translated to further C compiler flags; the c_libdirs and c_libs can be translated to further linker flags. The c_flags and ld_flags are additional flags. It is also allowed to only fill c_flags and ld_flags and let the other components empty.

The config_script is the name of another script that can be called to get the C compiler and linker flags (e.g. pkg-config scripts).

The godi_deps are dependencies to GODI packages that are required at run-time to make the C library available. (These are usually base-foo packages.)

val create_test_whether_c_function_exists : string -> string
Input is the name of a C function. The returned string is a C program that can only be compiled and linked if the C function exists. The program returns the exit code 0.
val c_compile_test : c_env -> string -> string cmdlet
The string must contain the C program to be used as test. The program is compiled and linked using the C environment. The result stored into the commandlet state is the name of the executable.
val run_test : string cmdlet
Runs the executable whose name is stored in the state. The exit code is set, and the new result is the output of the program.
val find_c_library : ?godi_deps:string list ->
?pref_incdir:string ->
?pref_libdir:string ->
?c_flags:string list ->
?ld_flags:string list ->
?inc_name:string ->
libs:string list ->
test:(c_env -> c_env option) ->
unit -> c_env cmdlet
Searches a C library. First, the preferred locations pref_incdir and pref_libdir are tried. If not successful, searching continues with the locations found in the environment variable SEARCH_LIBS.

A C library is found if:

If found, the return value of test is the result of the commandlet.

The C environment passed to the test function is properly set up:


val print_c_result : file:string -> prefix:string -> c_env -> unit
Prints the C environment to the file and to the screen. The prefix is prepended to the variables in file. Example: print_c_result ~file:"conf-foo.mk" ~prefix:"CONF_FOO" ce
val main_c_finder : ?godi_deps:string list Pervasives.ref ->
?pref_incdir:string option Pervasives.ref ->
?pref_libdir:string option Pervasives.ref ->
?c_flags:string list Pervasives.ref ->
?ld_flags:string list Pervasives.ref -> unit -> unit
A configurable main program. The arguments godi_deps, pref_incdir, pref_libdir, c_flags, and ld_flags can be set by command-line if a string reference is passed to the function.

Example:


 let pref_incdir = ref None in
 let pref_libdir = ref None in
 main_c_finder ~pref_incdir ~pref_libdir ();
 let c_opt = eval
               (find_c_library 
                  ?pref_incdir:!pref_incdir 
                  ?pref_libdir:!pref_libdir 
                  ~libs:... ~test:... ()) in
 match c_opt with
   None -> failwith "Cannot find library"
   Some c -> print_c_result ~file:"conf-foo.mk" ~prefix:"CONF_FOO" c