(* * Copyright (c) 2013-2020 Thomas Gazagnaire * Copyright (c) 2013-2020 Anil Madhavapeddy * Copyright (c) 2015-2020 Gabriel Radanne * * 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 [.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 [.start ]. *) 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