package unic

  1. Overview
  2. Docs
A tool to infer what is needed to vendors to compile unikernels

Install

dune-project
 Dependency

Authors

Maintainers

Sources

uniq-0.1.0.tbz
sha256=998588f1053cf03161a4bded6d7f8068c88de497e77fc0bbca81a5234fa444d5
sha512=53d4ee5ad8c01e19a2e1fbda86266768d118f78566b82f0c736338ce2c12258185a5f4dbb90bf0da37a7528098266ec81861bdcfea29e55daa3122a4f3a1daca

doc/src/unic.resolve/unic_resolve.ml.html

Source file unic_resolve.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
module Set = Set.Make (Modname)

let ( let* ) = Result.bind
let error_msgf fmt = Fmt.kstr (fun msg -> Error (`Msg msg)) fmt

module Elt = struct
  type t =
    | Resolved of Modname.t * Uniq_meta.Path.t
    | Ambiguous of Modname.t * Uniq_meta.Path.t list
    | Not_found of Modname.t

  let pp ppf = function
    | Resolved (modname, pkg) ->
        Fmt.pf ppf "%a => %a"
          Fmt.(styled (`Fg `Green) Modname.pp)
          modname Uniq_meta.Path.pp pkg
    | Not_found modname ->
        Fmt.pf ppf "%a" Fmt.(styled (`Fg `Red) Modname.pp) modname
    | Ambiguous (modname, pkgs) ->
        Fmt.pf ppf "%a => @[<hov>%a@]"
          Fmt.(styled (`Fg `Yellow) Modname.pp)
          modname
          Fmt.(Dump.list Uniq_meta.Path.pp)
          pkgs
end

let run _quiet cfg recurse root without_stdlib ocamlfind_roots =
  let sources = Uniq_resolve.Src.sources ~recurse root in
  let srcs =
    match cfg with
    | None -> [ sources ]
    | Some cfg ->
        begin if without_stdlib then [ sources ]
        else
          match Uniq_cfg.(get cfg ~key:"standard_library" Value.path) with
          | Some stdlib -> [ sources; Uniq_resolve.Src.objects stdlib ]
          | None -> [ sources ]
        end
  in
  let* ts = Uniq_resolve.qualify ~stdlib:(not without_stdlib) srcs in
  let intfs, impls =
    let fn (intfs, impls) t =
      let intfs', impls' = Uniq_info.missing t in
      let intfs' = List.map fst intfs' in
      let impls' = List.map fst impls' in
      let intfs = Set.add_seq (List.to_seq intfs') intfs in
      let impls = Set.add_seq (List.to_seq impls') impls in
      (intfs, impls)
    in
    List.fold_left fn Set.(empty, empty) ts
  in
  let results =
    let missing = Set.union intfs impls in
    if Set.is_empty missing then []
    else
      let missing = Set.to_list missing in
      let providers = Uniq_meta.find_providers ~roots:ocamlfind_roots missing in
      let not_found =
        let fn s (m, _) = Set.add m s in
        let provided = List.fold_left fn Set.empty providers in
        let fn m = not (Set.mem m provided) in
        List.filter fn missing
      in
      let not_found = List.rev_map (fun m -> (m, [])) not_found in
      let elements = List.rev_append providers not_found in
      let fn (modname, pkgs) =
        match pkgs with
        | [ pkg ] -> Elt.Resolved (modname, pkg)
        | [] -> Elt.Not_found modname
        | pkgs -> Elt.Ambiguous (modname, pkgs)
      in
      List.map fn elements
  in
  List.iter (fun elt -> Fmt.pr "%a\n%!" Elt.pp elt) results;
  Ok 0

open Cmdliner
open Unic_cli

let path =
  let doc = "The OCaml project directory." in
  let parser str =
    match Fpath.of_string str with
    | Ok v when Sys.file_exists str ->
        if Sys.is_directory str then Ok (Fpath.to_dir_path v) else Ok v
    | Ok v -> error_msgf "%a does not exist" Fpath.pp v
    | Error _ as err -> err
  in
  let existing_context = Arg.conv (parser, Fpath.pp) in
  let open Arg in
  required
  & pos ~rev:true 0 (some existing_context) None
  & info [] ~doc ~docv:"DIRECTORY"

let recurse =
  let doc = "Include sub-directories." in
  Arg.(value & flag & info [ "r"; "recurse" ] ~doc)

let without_stdlib =
  let doc = "Do not add the standard library to the list of include sources." in
  Arg.(value & flag & info [ "without-stdlib" ] ~doc)

let term =
  let open Term in
  const run
  $ setup_logs
  $ setup_ocaml
  $ recurse
  $ path
  $ without_stdlib
  $ setup_ocamlfind
  |> term_result

let cmd =
  let doc = "Resolve the missing modules of an OCaml project." in
  let man =
    [
      `S Manpage.s_description
    ; `P
        "$(tname) qualifies the given OCaml project (as $(b,unic qualify) \
         does) and collects the modules required by the project but not \
         provided by it. Then, for each missing module, $(tname) searches an \
         $(b,ocamlfind) package which provides it."
    ; `P
        "For each missing module, three results are possible: the module is \
         resolved (only one package provides it), the module is ambiguous \
         (several packages provide it) or the module is not found (no package \
         provides it)."
    ]
  in
  Cmd.v (Cmd.info "resolve" ~doc ~man) term