Skip to content

Commit

Permalink
Merge pull request #467 from ocaml/import-configurator
Browse files Browse the repository at this point in the history
Import configurator
  • Loading branch information
rgrinberg committed Mar 1, 2018
2 parents 7ed033c + 6dae7ca commit 66a907b
Show file tree
Hide file tree
Showing 11 changed files with 625 additions and 7 deletions.
454 changes: 454 additions & 0 deletions src/configurator/configurator.ml

Large diffs are not rendered by default.

97 changes: 97 additions & 0 deletions src/configurator/configurator.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
type t

val create
: ?dest_dir:string
-> ?ocamlc:string
-> ?log:(string -> unit)
-> string (** name, such as library name *)
-> t

(** Return the value associated to a variable in the output of [ocamlc -config] *)
val ocaml_config_var : t -> string -> string option
val ocaml_config_var_exn : t -> string -> string

(** [c_test t ?c_flags ?link_flags c_code] try to compile and link the C code given in
[c_code]. Return whether compilation was successful. *)
val c_test
: t
-> ?c_flags: string list (** default: [] *)
-> ?link_flags:string list (** default: [] *)
-> string
-> bool

module C_define : sig
module Type : sig
type t =
| Switch (** defined/undefined *)
| Int
| String
end

module Value : sig
type t =
| Switch of bool
| Int of int
| String of string
end

(** Import some #define from the given header files. For instance:
{[
# C.C_define.import c ~includes:"caml/config.h" ["ARCH_SIXTYFOUR", Switch];;
- (string * Configurator.C_define.Value.t) list = ["ARCH_SIXTYFOUR", Switch true]
]}
*)
val import
: t
-> ?c_flags: string list
-> ?link_flags:string list
-> includes: string list
-> (string * Type.t ) list
-> (string * Value.t) list

(** Generate a C header file containing the following #define. [protection_var] is used
to enclose the file with:
{[
#ifndef BLAH
#define BLAH
...
#endif
]}
If not specified, it is inferred from the name given to [create] and the
filename. *)
val gen_header_file
: t
-> fname:string
-> ?protection_var:string
-> (string * Value.t) list -> unit
end

module Pkg_config : sig
type configurator = t
type t

(** Returns [None] if pkg-config is not installed *)
val get : configurator -> t option

type package_conf =
{ libs : string list
; cflags : string list
}

(** Returns [None] if [package] is not available *)
val query : t -> package:string -> package_conf option
end with type configurator := t

(** Typical entry point for configurator programs *)
val main
: ?args:(Arg.key * Arg.spec * Arg.doc) list
-> name:string
-> (t -> unit)
-> unit

(** Abort execution. If raised from within [main], the argument of [die] is printed as
[Error: <message>]. *)
val die : ('a, unit, string, 'b) format4 -> 'a
7 changes: 7 additions & 0 deletions src/configurator/jbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(library
((name configurator)
(flags (:standard -safe-string))
(libraries (jbuilder stdune))
(preprocess no_preprocessing)))

(jbuild_version 1)
17 changes: 13 additions & 4 deletions src/io.ml
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,24 @@ let input_lines =
in
fun ic -> loop ic []

let read_file fn =
with_file_in fn ~f:(fun ic ->
let len = in_channel_length ic in
really_input_string ic len)
let read_all ic =
let len = in_channel_length ic in
really_input_string ic len

let read_file fn = with_file_in fn ~f:read_all

let lines_of_file fn = with_file_in fn ~f:input_lines ~binary:false

let write_file fn data = with_file_out fn ~f:(fun oc -> output_string oc data)

let write_lines fn lines =
with_file_out fn ~f:(fun oc ->
List.iter ~f:(fun line ->
output_string oc line;
output_string oc "\n"
) lines
)

let copy_channels =
let buf_len = 65536 in
let buf = Bytes.create buf_len in
Expand Down
4 changes: 4 additions & 0 deletions src/io.mli
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ val write_file : string -> string -> unit

val compare_files : string -> string -> Ordering.t

val write_lines : string -> string list -> unit

val copy_channels : in_channel -> out_channel -> unit

val copy_file : src:string -> dst:string -> unit

val read_all : in_channel -> string
11 changes: 8 additions & 3 deletions src/ocamlc_config.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ type t =
; ocamlc: Path.t
}

let bindings t = t.bindings

let ocamlc_config_cmd ocamlc =
sprintf "%s -config" (Path.to_string ocamlc)

let sexp_of_t t =
let open Sexp.To_sexp in
string_map Sexp.atom_or_quoted_string t.bindings

let read ~ocamlc ~env =
Process.run_capture_lines ~env Strict (Path.to_string ocamlc) ["-config"]
>>| fun lines ->
let make ~ocamlc ~ocamlc_config_output:lines =
List.map lines ~f:(fun line ->
match String.index line ':' with
| Some i ->
Expand All @@ -31,6 +31,11 @@ let read ~ocamlc ~env =
die "variable %S present twice in the output of `%s`"
key (ocamlc_config_cmd ocamlc)

let read ~ocamlc ~env =
Process.run_capture_lines ~env Strict (Path.to_string ocamlc) ["-config"]
>>| fun lines ->
make ~ocamlc ~ocamlc_config_output:lines

let ocaml_value t =
let t = String_map.to_list t.bindings in
let longest = String.longest_map t ~f:fst in
Expand Down
11 changes: 11 additions & 0 deletions src/ocamlc_config.mli
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
(** Output of [ocamlc -config] *)

open Import

type t

val sexp_of_t : t -> Sexp.t

val make
: ocamlc:Path.t
-> ocamlc_config_output:string list
-> t

val read : ocamlc:Path.t -> env:string array -> t Fiber.t

(** Used to pass these settings to jbuild files using the OCaml syntax *)
Expand All @@ -17,3 +25,6 @@ val word_size : t -> string option
val flambda : t -> bool
val stdlib_dir : t -> Path.t
val c_compiler_settings : t -> (string * string * string)

(**/**)
val bindings : t -> string String_map.t
16 changes: 16 additions & 0 deletions src/stdune/string.ml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ let break s ~pos =
(sub s ~pos:0 ~len:pos,
sub s ~pos ~len:(length s - pos))

let is_empty s = length s = 0

let is_prefix s ~prefix =
let len = length s in
let prefix_len = length prefix in
Expand Down Expand Up @@ -79,6 +81,11 @@ let lsplit2 s ~on =
(sub s ~pos:0 ~len:i,
sub s ~pos:(i + 1) ~len:(length s - i - 1))

let lsplit2_exn s ~on =
match lsplit2 s ~on with
| Some s -> s
| None -> invalid_arg "lsplit2_exn"

let rsplit2 s ~on =
match rindex s on with
| exception Not_found -> None
Expand Down Expand Up @@ -153,3 +160,12 @@ let longest_map l ~f =
max acc (length (f x)))

let longest l = longest_map l ~f:(fun x -> x)

let exists s ~f =
try
for i=0 to length s - 1 do
if (f s.[i]) then raise_notrace Exit
done;
false
with Exit ->
true
4 changes: 4 additions & 0 deletions src/stdune/string.mli
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ val compare : t -> t -> Ordering.t

val break : t -> pos:int -> t * t

val is_empty : t -> bool
val is_prefix : t -> prefix:t -> bool
val is_suffix : t -> suffix:t -> bool

Expand All @@ -22,6 +23,7 @@ val extract_comma_space_separated_words : t -> t list
val extract_blank_separated_words : t -> t list

val lsplit2 : t -> on:char -> (t * t) option
val lsplit2_exn : t -> on:char -> t * t
val rsplit2 : t -> on:char -> (t * t) option

val split : t -> on:char -> t list
Expand All @@ -35,3 +37,5 @@ val escape_double_quote : t -> t
(** Return the length of the longest string in the list *)
val longest : string list -> int
val longest_map : 'a list -> f:('a -> string) -> int

val exists : t -> f:(char -> bool) -> bool
10 changes: 10 additions & 0 deletions test/unit-tests/configurator/jbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(jbuild_version 1)

(executable
((name test_configurator)
(libraries (configurator))))

(alias
((name runtest)
(deps (./test_configurator.exe))
(action (run ${<}))))
1 change: 1 addition & 0 deletions test/unit-tests/configurator/test_configurator.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Configurator.main ~name:"test_configurator" (fun _ -> ())

0 comments on commit 66a907b

Please sign in to comment.