package dkml-install
Install
Dune Dependency
Authors
Maintainers
Sources
md5=9c2fc122d49103ce9bf513fcc11b443d
sha512=c746d7a4482109c725bfe44542c146914add4d77e8e76556ce0de6e2567683a7ac7dc9909f1252aea7facbcf130153b8e752607a3c44e35b8cfd8ea5d99eb356
doc/dkml-install.api/Dkml_install_api/index.html
Module Dkml_install_api
Source
Component Configuration
You are responsible for creating a module of type Component_config
to describe your component. A do-nothing implementation for most of the module is available as Default_component_config
.
Dkml_install_api
will use the Component_config
to create four (4) command line applications.
Each of the command line applications are "subcommands" in the language of the OCaml Cmdliner
package. You will not need to understand Cmdliner to define your own component, although you may visit the Cmdliner documentation if you want more information.
The four (4) command line applications have limited access to the OCaml runtime. The expectation is that all installation logic is embedded in bytecode executables which have the complete set of package dependencies you need to run your logic. Through Component_config
Dkml_install_api
will have given you a ~ctx_t
Cmdliner term that, when evaluated, leads to the context record Context.t
. The context record has the information needed to run your bytecode executables.
On Windows it is recommended security practice to separate functionality that requires administrative privileges from functionality that does not require non-administrative privileges. Dkml_install_api
follows the same recommendations:
- There will be a single executable
"dkml-install-admin-runner.exe"
that is responsible for the following functionality for all components:
- Administrator installation defined by
Component_config.install_admin_subcommand
- Administrator uninstallation defined by
Component_config.uninstall_admin_subcommand
- There will be a single executable
"dkml-install-user-runner.exe"
that is responsible for the following functionality for all components:
- User installation defined by
Component_config.install_user_subcommand
- User uninstallation defined by
Component_config.uninstall_user_subcommand
Configuration
Component configuration values that can be supplied with defaults.
Each component must define a configuration module
You should include Default_component_config
in any of your components so that your component can be future-proof against changes in the Component_config
signature.
Default values for a subset of the module type Component_config
.
Process execution
val log_spawn_onerror_exit :
id:string ->
?conformant_subprocess_exitcodes:bool ->
Bos.Cmd.t ->
unit
log_spawn_onerror_exit ~id ?conformant_subprocess_exitcodes cmd
logs the command cmd
and runs it synchronously, and prints an error on the fatal logger fl ~id
and then exits with a non-zero exit code if the command exits with a non-zero error code.
The environment variable "OCAMLRUNPARAM"
will be set to "b"
so that any OCaml bytecode launched by log_spawn_onerror_exit
will have backtraces. Any exiting environment variable "OCAMLRUNPARAM"
will be kept, however.
Exit Codes
The exit code used to leave this process depends on conformant_subprocess_exitcodes
.
When conformant_subprocess_exitcodes = true
or conformant_subprocess_exitcodes
is not specified, the exit code will be the same as the spawned process exit code if and only if the exit code belongs to one of Forward_progress.Exit_code
; if the spawned exit code does not belong then the exit code will be Forward_progress.Exit_code.t.Exit_transient_failure
.
When conformant_subprocess_exitcodes = false
the exit code will always be Forward_progress.Exit_code.t.Exit_transient_failure
if the spawned process ends in error.
Logging
Logging follows the Cmdliner standards.
All dkml_install generated executables can be supplied with the following options:
--color=WHEN (absent=auto) Colorize the output. WHEN must be one of `auto', `always' or `never'. -q, --quiet Be quiet. Takes over -v and --verbosity. -v, --verbose Increase verbosity. Repeatable, but more than twice does not bring more. --verbosity=LEVEL (absent=warning) Be more or less verbose. LEVEL must be one of `quiet', `error', `warning', `info' or `debug'. Takes over -v.
You can use Log_config
to pass the color and verbosity options into your own bytecode executables.
Start by initializing the logger in your own executables with the following setup_log_t
Cmdliner Term:
let setup_log style_renderer level =
Fmt_tty.setup_std_outputs ?style_renderer ();
Logs.set_level level;
Logs.set_reporter (Logs_fmt.reporter ());
Dkml_install_api.Log_config.create ?log_config_style_renderer:style_renderer
?log_config_level:level ()
let setup_log_t =
Term.(const setup_log $ Fmt_cli.style_renderer () $ Logs_cli.level ())
Finally, with a Log_config.t
you can use Log_config.to_args
to pass the correct command line options into your own executables. For components that are configured to spawn bytecode programs you can locate the Log_config.t
in the Dkml_install_api.Context.t.log_config
(ctx.Dkml_install_api.Context.log_config
) context field. That could look like:
let execute ctx =
let ocamlrun =
ctx.Context.path_eval "%{staging-ocamlrun:share-abi}/bin/ocamlrun"
in
log_spawn_onerror_exit
(* Always use your own unique id; create it with PowerShell on Windows:
[guid]::NewGuid().Guid.Substring(0,8)
or on macOS/Unix:
uuidgen | tr A-Z a-z | cut -c1-8
*)
~id:"9b7e32e0"
Cmd.(
v (Fpath.to_string
(ctx.Context.path_eval "%{staging-ocamlrun:share-abi}/bin/ocamlrun"))
% Fpath.to_string
(ctx.Context.path_eval "%{_:share}%/generic/your_bytecode.bc")
(* Pass --verbosity and --color to your bytecode *)
%% Log_config.to_args ctx.Context.log_config)
let () =
let reg = Component_registry.get () in
Component_registry.add_component reg
(module struct
include Default_component_config
let component_name = "enduser-yourcomponent"
let depends_on = [ "staging-ocamlrun" ]
let install_user_subcommand ~component_name:_ ~subcommand_name ~fl ~ctx_t =
let doc = "Install your component" in
Dkml_install_api.Forward_progress.Continue_progress (Cmdliner.Term.(const execute $ ctx_t, info subcommand_name ~doc), fl)
end)
Others can use the Log_config.t
return value from setup_log
when calling Log_config.to_args
.
Forward_progress
provides common functions to handle graceful and informative exits from the nested chain of subprocesses typical in DKML Install API and many other applications.