169 lines
5.9 KiB
OCaml
169 lines
5.9 KiB
OCaml
(*
|
|
* Copyright (c) 2013-2020 Thomas Gazagnaire <thomas@gazagnaire.org>
|
|
* Copyright (c) 2013-2020 Anil Madhavapeddy <anil@recoil.org>
|
|
* Copyright (c) 2015-2020 Gabriel Radanne <drupyog@zoho.com>
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*)
|
|
|
|
(** Signature for functoria devices. A [device] is a module implementation which
|
|
contains a runtime state which can be set either at configuration time (by
|
|
the application builder) or at runtime, using command-line arguments. *)
|
|
|
|
type ('a, 'b) t
|
|
(** The type for devices whose runtime state is of type ['a] and having extra
|
|
data-dependencies of type ['b]. *)
|
|
|
|
val module_type : ('a, 'b) t -> 'a Type.t
|
|
(** [module_type t] is [t]'s module type. *)
|
|
|
|
val module_name : ('a, 'b) t -> string
|
|
(** [module_name t] is [t]'s module name. *)
|
|
|
|
val packages : ('a, 'b) t -> Package.t list Key.value
|
|
(** [packages t] is the list of OPAM packages that are needed by [t].*)
|
|
|
|
val local_libs : ('a, 'b) t -> string list
|
|
(** [local_libs t] is the list of local libraries that are needed by [t]. *)
|
|
|
|
val install : ('a, 'b) t -> Info.t -> Install.t Key.value
|
|
(** [install t i] is the list of files installed by [t], using the build
|
|
information [i]. *)
|
|
|
|
val extra_deps : ('a, 'b) t -> 'b list
|
|
(** [extra_deps t] is the list of dependencies that be initialized before
|
|
running the code generated by [connect t]. *)
|
|
|
|
val id : ('a, 'b) t -> int
|
|
(** [id t] is [t]'s unique identifier. Freshly generated for each call to {!v}.
|
|
*)
|
|
|
|
val pp : 'b Fmt.t -> ('a, 'b) t Fmt.t
|
|
(** [pp pp_dep] is the pretty-printer for devices, using [pp_dep] to
|
|
pretty-print the extra data-dependencies. *)
|
|
|
|
val equal : ('a, 'b) t -> ('c, 'd) t -> bool
|
|
(** [equal] is the equality function for devices. *)
|
|
|
|
val witness : ('a, _) t -> ('b, _) t -> ('a, 'b) Typeid.witness
|
|
(** [witness a b] provides an equality witness. *)
|
|
|
|
val hash : ('a, 'b) t -> int
|
|
(** [hash t] is [t]'s hash. *)
|
|
|
|
(** {1 Resources} *)
|
|
|
|
val files : ('a, 'b) t -> Info.t -> Fpath.Set.t
|
|
(** [files t info s] is the list of files generated configure-time. *)
|
|
|
|
val keys : ('a, 'b) t -> Key.t list
|
|
(** [keys t] is the list of keys which can be used to configure [t]. *)
|
|
|
|
val runtime_args : ('a, 'b) t -> Runtime_arg.t list
|
|
(** [runtime_args t] is the list of command-line arguments which can be used to
|
|
configure [t] at runtime. *)
|
|
|
|
(** {1 Code Generation} *)
|
|
|
|
type 'a code = private {
|
|
pos : (string * int * int * int) option;
|
|
code : string;
|
|
}
|
|
(** The type for fragments of code of type ['a]. *)
|
|
|
|
val code :
|
|
pos:string * int * int * int ->
|
|
('a, Format.formatter, unit, 'b code) format4 ->
|
|
'a
|
|
(** Generate localised code. *)
|
|
|
|
val connect : ('a, 'b) t -> Info.t -> string -> string list -> 'a code
|
|
(** [connect t info impl_name args] is the code to execute in order to create a
|
|
new state (usually calling [<module_name t>.connect]) with the arguments
|
|
[args], in the context of the project information [info]. The freshly
|
|
created state will be made available in [var_name t] *)
|
|
|
|
val start : ?pos:string * int * int * int -> string -> string list -> 'a code
|
|
(** [start ?pos impl_name args] is the code [<impl_name>.start <args>]. *)
|
|
|
|
val nice_name : _ t -> string
|
|
(** [nice_name d] provides a identifier unique to [d] which is a valid OCaml
|
|
identifier. *)
|
|
|
|
(** {1 Actions} *)
|
|
val dune : ('a, 'b) t -> Info.t -> Dune.stanza list
|
|
(** [dune t info] are the dune stanza which needs to be generated to build the
|
|
application. *)
|
|
|
|
(** {1 Configuration} *)
|
|
|
|
val configure : ('a, 'b) t -> Info.t -> unit Action.t
|
|
(** [configure t info] is configure hook for [t] the device and the files it
|
|
generates. During the configure phase, you cannot rely on [packages t] being
|
|
installed.
|
|
|
|
To run code during the [build] phase, generate a [dune] fragment instead. *)
|
|
|
|
(** {1 Constructors} *)
|
|
|
|
val v :
|
|
?packages:Package.t list ->
|
|
?packages_v:Package.t list Key.value ->
|
|
?local_libs:string list ->
|
|
?install:(Info.t -> Install.t) ->
|
|
?install_v:(Info.t -> Install.t Key.value) ->
|
|
?keys:Key.t list ->
|
|
?runtime_args:Runtime_arg.t list ->
|
|
?extra_deps:'b list ->
|
|
?connect:(Info.t -> string -> string list -> 'a code) ->
|
|
?dune:(Info.t -> Dune.stanza list) ->
|
|
?configure:(Info.t -> unit Action.t) ->
|
|
?files:(Info.t -> Fpath.t list) ->
|
|
string ->
|
|
'a Type.t ->
|
|
('a, 'b) t
|
|
|
|
val extend :
|
|
?packages:Package.t list ->
|
|
?packages_v:Package.t list Key.value ->
|
|
?dune:(Info.t -> Dune.stanza list) ->
|
|
?pre_configure:(Info.t -> unit Action.t) ->
|
|
?post_configure:(Info.t -> unit Action.t) ->
|
|
?files:(Info.t -> Fpath.t list) ->
|
|
('a, 'b) t ->
|
|
('a, 'b) t
|
|
|
|
(** {1 Device graphs} *)
|
|
|
|
module Graph : sig
|
|
type ('a, 'i) device
|
|
|
|
(** A graph of devices, annotated with their arguments, dependencies, and a
|
|
unique identifier.
|
|
|
|
Warning: this is truly a DAG: sharing {b must} be preserved. Manual walks
|
|
are discouraged, please use {!fold} instead. *)
|
|
type t =
|
|
| D : { dev : (_, _) device; args : t list; deps : t list; id : int } -> t
|
|
|
|
val fold : (t -> 'a -> 'a) -> t -> 'a -> 'a
|
|
(** [fold f g z] applies [f] on each device in topological order. *)
|
|
|
|
val var_name : t -> string
|
|
(** [var_name t] returns the name identifying [t] which is a valid OCaml
|
|
variable identifier. *)
|
|
|
|
val impl_name : t -> string
|
|
(** [impl_name t] returns the name identifying [t]'s module implementation. *)
|
|
end
|
|
with type ('a, 'i) device := ('a, 'i) t
|