Permalink
Browse files

extended configuration options for plugins (#420)

This PR allows plugins to specify their own
configuration parameters, ocamlbuild plugins, tags,
and interpolation files.

Details
-------

File `oasis/<plugin>.setup.ml.in` will be copied to a final `setup.ml`,
and can contain arbitrary ocaml code that will be executed at
configuration time. A handful shortcuts are provided, e.g.,
`add_variable` function will add a configuration variable.

File `oasis/<plugin>.files.ab.in` can contain a list of files, where
substitution will be performed. It can contain variables of the form
`$<var>` where `<var>` is one of the variables set in the configuration
time (see `setup.data` for a full list).

Files `oasis/<plugin>.tags.in` and `oasis/<plugin>.ocamlbuild.ml.in`
will end up in `_tags` and `myocamlbuild.ml` correspondingly.

Also, all `ml` files in the configuration suit now contain special
literals, that will allow to jump to a correct places for errors.
  • Loading branch information...
ivg committed May 5, 2016
1 parent e611278 commit 72a549c7fb661317b80a395ca5fcf966869ead38
Showing with 108 additions and 51 deletions.
  1. +0 −8 _tags.in
  2. +11 −6 configure
  3. +0 −8 myocamlbuild.ml.in
  4. +0 −1 oasis/common
  5. +1 −0 oasis/common.files.ab.in
  6. +9 −0 oasis/common.ocamlbuild.ml.in
  7. +49 −0 oasis/common.setup.ml.in
  8. +8 −0 oasis/common.tags.in
  9. +0 −16 setup.ml.in
  10. +20 −11 tools/cat.ml
  11. +1 −0 tools/cat.mli
  12. +5 −0 tools/collect.ml
  13. +4 −1 tools/oasis_sections.ml
@@ -1,8 +0,0 @@
# OASIS_START
# OASIS_STOP
true: short_paths
true: bin_annot
true: debug
<**/*.ml{,i}>: predicate(ppx_driver)
<**/*.native>: predicate(ppx_driver)
<**/*.ml{,i}> and not <lib/bap_elf/elf_parse.ml>: pp(ppx-jane -dump-ast -inline-test-lib bap)
@@ -26,9 +26,14 @@ for i in "$@"; do
done
SECTIONS=`ocaml tools/oasis_sections.ml $@`
ocaml tools/cat.ml $SECTIONS _oasis
ocaml tools/cat.ml _tags.in _tags
ocaml tools/cat.ml myocamlbuild.ml.in myocamlbuild.ml
ocaml tools/cat.ml setup.ml.in setup.ml
oasis -quiet setup
ocaml setup.ml -quiet -configure "$@"
TAGS=`ocaml tools/collect.ml tags $SECTIONS`
PLUGINS=`ocaml tools/collect.ml ocamlbuild.ml $SECTIONS`
SETUPS=`ocaml tools/collect.ml setup.ml $SECTIONS`
AB=`ocaml tools/collect.ml files.ab $SECTIONS`
ocaml tools/cat.ml '"\n# $name\n"' -- $SECTIONS $AB _oasis
ocaml tools/cat.ml '"\n# $name\n"' -- $TAGS _tags.in _tags
ocaml tools/cat.ml '"\n#1 \"$name\"\n"' -- $PLUGINS myocamlbuild.ml.in myocamlbuild.ml
ocaml tools/cat.ml '"\n#1 \"$name\"\n"' -- $SETUPS setup.ml.in setup.ml
oasis setup
ocaml setup.ml -configure "$@"
@@ -1,12 +1,4 @@
(* OASIS_START *)
(* OASIS_STOP *)
let oasis_env =
BaseEnvLight.load
~filename:MyOCamlbuildBase.env_filename
~allow_empty:true
()
let nonempty = function (A s) -> String.length s <> 0 | _ -> true
let expand s = BaseEnvLight.var_expand s oasis_env;;
(* the piqi support is rather fragile *)
let piqic_rule () : unit =
@@ -17,7 +17,6 @@ XOCamlbuildExtraArgs:
BuildDepends: ppx_jane, core_kernel
FilesAB: lib/bap_config/bap_config.ml.ab
PreConfCommand: $rm setup.data
PostDistcleanCommand: $rm _tags myocamlbuild.ml setup.ml setup.data
@@ -0,0 +1 @@
FilesAB: lib/bap_config/bap_config.ml.ab
@@ -0,0 +1,9 @@
(* OASIS_START *)
(* OASIS_STOP *)
#4 "oasis/common.ocamlbuild.ml.in"
let oasis_env =
BaseEnvLight.load
~filename:MyOCamlbuildBase.env_filename
~allow_empty:true
()
let expand s = BaseEnvLight.var_expand s oasis_env
@@ -0,0 +1,49 @@
#load "unix.cma";;
(* OASIS_START *)
(* OASIS_STOP *)
#5 "oasis/common.setup.ml.in"
let definition_end = BaseEnv.var_ignore
let ctxt = !BaseContext.default
(** [add_variable ?define ~doc name] defines a variable with a [name]
and short description [doc]. The variable can be set via the
command line with [--var=value] syntax, or through the environment,
e.g., [var=value ./configure]
Note: A variable name must conform to OCaml variable name
requirements. In the command line a variable name is dashified,
i.e., all underscores are mapped to dashes.
Parameter [define] is some function, that is applied to [None] if
a variable wasn't set explicitly by a user and to [Some x], if a
user set the variable to string [x]. A function should return a
final value of a variable.
*)
let add_variable ?define ~doc (name : string) : unit =
let value = ref None in
let set x = value := Some x in
let get () = match define with
| Some f -> f !value
| None -> match !value with
| None -> "#undefined"
| Some x -> x in
let dashify x = "--" ^ String.map (function '_' -> '-' | c -> c) x in
BaseEnv.var_define
~hide:false ~dump:true
~short_desc:(fun () -> doc)
~cli:(BaseEnv.CLIUser [dashify name,Arg.String set,"str " ^ doc])
name get |>
definition_end
let getvar var : string option =
try Some (BaseEnv.var_get var) with exn -> None
let is_defined var : bool =
match getvar var with None -> false | _ -> true
let is_undefined var : bool = not (is_defined var)
let is_set_to var value : bool =
is_defined var && BaseEnv.var_get var = value
@@ -0,0 +1,8 @@
# OASIS_START
# OASIS_STOP
true: short_paths
true: bin_annot
true: debug
<**/*.ml{,i}>: predicate(ppx_driver)
<**/*.native>: predicate(ppx_driver)
<**/*.ml{,i}> and not <lib/bap_elf/elf_parse.ml>: pp(ppx-jane -dump-ast -inline-test-lib bap)
@@ -1,10 +1,3 @@
#load "unix.cma";;
(* OASIS_START *)
(* OASIS_STOP *)
let definition_end = BaseEnv.var_ignore
let ctxt = !BaseContext.default
let piqic () : unit =
let chop str = try
Filename.chop_extension str
@@ -139,13 +132,6 @@ let llvm_lib () : unit =
BaseEnv.var_get lib) |>
definition_end
let is_defined var : bool =
try (BaseEnv.var_get var) |> ignore; true with exn -> false
let is_undefined var : bool = not (is_defined var)
let is_set_to var value : bool =
is_defined var && BaseEnv.var_get var = value
let check =
@@ -164,8 +150,6 @@ let install_headers hdrs =
| Some "bap" -> (cs, bs, lib, hdrs)
| _ -> (cs, bs, lib, [])
let define definitions =
List.iter (fun f -> try f () with exn -> ()) definitions
@@ -1,25 +1,34 @@
(* this is a slowmo implementation of cat utility,
that we need since `cat` is not guaranteed to exist
on all platforms*)
(* concatenate files with a header *)
let read_all file =
let chan = open_in_bin file in
let data = really_input_string chan (in_channel_length chan) in
close_in chan;
data
let cat inputs output =
let data = List.map read_all inputs in
let subst file str =
let buf = Buffer.create 16 in
Buffer.add_substitute buf (function "name" -> file | s -> s) str;
Buffer.contents buf
let cat header inputs output =
let data = List.map (fun file ->
subst file header,read_all file) inputs in
let ch = open_out output in
data |> List.iter (output_string ch);
data |> List.iter (fun (header,data) ->
output_string ch header;
output_string ch data);
close_out ch
let () =
match Array.to_list Sys.argv with
| [] | [_] | [_; _] ->
prerr_endline "Usage: cat input1 [.. inputN] output"
| _ :: ios ->
| _ :: sep :: "--" :: (_ :: _ as ios) ->
let soi = List.rev ios in
let inputs = List.(soi |> tl |> rev) in
let output = List.hd soi in
cat inputs output
let sep = try Scanf.sscanf sep "%S" (fun x -> x) with exn ->
Printf.eprintf "Failed to unescape: %s\n" sep;
sep in
cat sep inputs output
| _ ->
prerr_endline "Usage: cat header -- input1 [.. inputN] output"
@@ -0,0 +1 @@
(** a fat cat on steroids - utility that concatenates files *)
@@ -0,0 +1,5 @@
let () = match Array.to_list Sys.argv with
| _ :: ext :: features -> features |> List.iter (fun feature ->
let file = feature ^ "." ^ ext ^ ".in" in
if Sys.file_exists file then print_endline file)
| _ -> failwith "Usage: collect extension features..."
@@ -2,9 +2,12 @@ let (/) = Filename.concat
let header = "common"
let has_extension name =
String.contains name '.'
let everything =
Sys.readdir "oasis" |> Array.to_list |>
List.filter (fun sec -> sec <> header)
List.filter (fun sec -> sec <> header && not (has_extension sec))
let enable_feature arg =
let length = String.length arg in

0 comments on commit 72a549c

Please sign in to comment.