mte/unikernel/duniverse/mirage/lib/functoria/device.mli
2025-11-11 02:07:51 +01:00

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