# Miou & Solo5 This library can be used to create unikernels with [Miou][miou] and [Solo5][solo5]. The library exposes what Solo5 can expose and implements a simple scheduler using Miou in order to develop a unikernel. Examples are available in the [tests][tests] to show how to implement and build an unikernel. Basically, a unikernel can be built from 2 devices: - the net device (a [TAP interface][tap]) - the device block (a simple file) ## How to build an unikernel with Miou & Solo5 Here's an example of a simple unikernel with `Miou_solo5` which displays "Hello World": ```ocaml let () = Miou_solo5.(run []) @@ fun () -> print_endline "Hello World" ``` First of all, we can build a simple executable from this code: ```dune (executable (name main) (modules main) (modes native) (link_flags :standard -cclib "-z solo5-abi=hvt") (libraries miou-solo5) (foreign_stubs (language c) (names manifest.sleep))) ``` As you can see, the executable needs a "manifest.c". This is a file that describes the devices that the unikernel needs. In this case, the `run` function takes a list of devices as its first argument, and we have just specified no devices in our example. As far as our _host toolchain_ is concerned, we can generate an empty file for the "manifest.c" required: ```dune (rule (targets manifest.c) (enabled_if (= %{context_name} "default")) (action (write-file manifest.c ""))) ``` Our first objective is to _infer_ the devices needed for our unikernel. In this case, our unikernel in our host context is not really going to run. It will collect the devices we have in the list we pass to `Miou_solo5.run` and generate a JSON file describing the devices needed by our unikernel. ```shell $ dune exec main.exe {"type":"solo5.manifest","version":1,"devices":[]} ``` We can now specify a new toolchain, that of solo5 (available via the [ocaml-solo5][ocaml-solo5] package) so that we can compile our OCaml code and build our unikernel. ```shell $ cat >dune-workspace <