this repo has no description
1opam-version: "2.0" 2maintainer: "Gabriel Radanne <drupyog@zoho.com>" 3authors: [ "Thomas Gazagnaire" 4 "Anil Madhavapeddy" 5 "Dave Scott" 6 "Thomas Leonard" 7 "Gabriel Radanne" ] 8homepage: "https://github.com/mirage/functoria" 9bug-reports: "https://github.com/mirage/functoria/issues" 10dev-repo: "git+https://github.com/mirage/functoria.git" 11doc: "https://mirage.github.io/functoria/" 12license: "ISC" 13tags: ["org:mirage"] 14 15build: ["ocaml" "pkg/pkg.ml" "build" "--pkg-name" name "--pinned" "%{pinned}%" ] 16depends: [ 17 "ocaml" {>= "4.02" & < "4.12"} 18 "ocamlfind" {build} 19 "ocamlbuild" {build} 20 "topkg" {build & >= "0.7.3"} 21 "cmdliner" {>= "0.9.8"} 22 "fmt" 23] 24conflicts: [ 25 "functoria" {< "2.0.0"} 26] 27patches: [ 28 "num.patch" 29] 30synopsis: "A DSL to organize functor applications" 31description: """ 32[![Build Status](https://travis-ci.org/mirage/functoria.svg)](https://travis-ci.org/mirage/functoria) 33[![docs](https://img.shields.io/badge/doc-online-blue.svg)](https://mirage.github.io/functoria/index.html) 34 35## What is this for? 36 37Functoria is a DSL to describe a set of modules and functors, their types and how to apply them in order to produce a complete application. 38 39The main use case is mirage. See the [mirage][] repository for details. 40 41## How to write a configuration file? 42 43There are numerous examples of configuration files in [mirage-skeleton][]. Most of them should be fairly general and understandable, even outside the context of mirage. We can distinguish two parts in a `config.ml`: Defining new modules and using them. 44 45In order to define a new module, we use the `foreign` function. Among its various arguments, it takes a module name and a type. The type is assembled with the DSL's combinators and the `@->` operator, which symbols a functor arrow. 46 47```ocaml 48let main = foreign "Unikernel.Main" (console @-> job) 49``` 50 51Here, we declare the functor `Unikernel.Main` that takes a module that should be a `console` and returns a module that is a `job`. It is up to the user to ensure that the declaration matches the implementation (or be punished by a compiler error later on). If the declaration is correct, everything that follows will be. 52 53We can now use this declaration: 54 55```ocaml 56let () = register "console" [main $ default_console] 57``` 58 59Here, we register a new application with the `register` function. This function should only be called once and takes as argument the name of the application and a list of jobs. We use the `$` operator to apply the functor `main` (aka `Unikernel.Main`) to the default console. 60 61Now that everything is ready, you can use the `configure` subcommand! 62 63### What is a job? 64 65A job is a module containing a function `start`. This function will receive one argument per functor argument and one per dependency, in this order. `foreign` assumes the function `start` returns `unit`. 66 67### Defining new keys 68 69A key is composed of: 70 71- _name_ : The name of the value in the program. 72- _description_ : How it should be displayed/serialized. 73- _stage_ : Is the key available only at runtime, at configure time or both? 74- _documentation_ : It is not optional so you should really write it. 75 76Consider a multilingual application: we want to pass the default language as a parameter. We will use a simple string, so we can use the predefined description `Key.Desc.string`. We want to be able to define it both at configure and run time, so we use the stage `` `Both``. This gives us the following code: 77 78```ocaml 79let lang_key = 80 let doc = Key.Doc.create 81 ~doc:"The default language for the application." [ "l" ; "lang" ] 82 in 83 Key.create ~doc ~stage:`Both ~default:"en" "language" Key.Desc.string 84``` 85 86Here, we defined both a long option `--lang` and a short one `-l` (the format is similar to the one used by [Cmdliner][cmdliner]). 87In the application code, the value is retrieved with `Key_gen.language ()`. 88 89The option is also documented in the `--help` option for both the `configure` subcommand (at configure time) and `./my_application` (at startup time). 90 91``` 92 -l VAL, --lang=VAL (absent=en) 93 The default language for the application. 94``` 95 96[cmdliner]: http://erratique.ch/software/cmdliner 97 98### Using switching keys 99 100We can do much more with keys: we can use them to switch implementation at configure time. Imagine we want to completely change some implementation based on the language. Finns are special snowflakes, they deserve their special application! 101 102First, we have to compute a boolean value from `lang`: 103 104```ocaml 105let is_fi = Key.(pure ((=) "fi") $ value lang_key) 106``` 107 108We can use the `if_impl` combinator to choose between two implementations depending on the value of the key: 109 110```ocaml 111let dynamic_storage = 112 if_impl is_fi 113 finnish_implementation 114 not_finnish_implementation 115``` 116 117This distinction will be visible using the `describe` subcommand and a dot diagram is available with the `--dot` option! 118 119## Internals 120 121### Phases 122 123Configuration is separated into phases: 124 1251. Specialized DSL keys 126 The specialized DSL's keys (along with functoria's keys) are resolved. 1272. Compilation and dynlink of the config file. 1283. Registering. 129 When the `register` function is called, the list of jobs is recorded and 130 immediately transformed into a graph. 1314. Switching keys and tree evaluation. 132 The switching keys are the keys inside the [If]. 133 Those keys are resolved and the graph is simplified. At this point, 134 the actual modules used are fully known. 135 Note: for the `describe` command, Only _partial_ evaluation is done, which 136 means decision nodes are resolved only if the value was given on the command 137 line, disregarding default values. 1385. Full Key resolution. 139 Once the actual modules are known, we can resolve all the keys and figure out 140 libraries and packages. 1416. Dependency handling, configuration and code emission. 142 143Phases 1. to 4. are also applied for the `clean` command. 144 145 146 147[mirage]: https://github.com/mirage/mirage 148[mirage-skeleton]: https://github.com/mirage/mirage-skeleton""" 149url { 150 src: 151 "https://github.com/mirage/functoria/releases/download/2.0.0/functoria-runtime-2.0.0.tbz" 152 checksum: [ 153 "sha256=891cd88dff14cd0c2dad5d429515d817657f3365ae4067e7e36b7d1664fd14c9" 154 "md5=139240af0ca1e09b1d30795059d81f52" 155 ] 156} 157extra-source "num.patch" { 158 src: 159 "https://raw.githubusercontent.com/ocaml/opam-source-archives/main/patches/functoria-runtime/num.patch" 160 checksum: [ 161 "sha256=254fc9981c54af957ff3e43ef679c256d254a0bbc809fbfcace1d8f84e706991" 162 "md5=0a424789bef2d5ac3f230442e2fe03b1" 163 ] 164} 165available: opam-version >= "2.2.0" 166flags: deprecated