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
open Utils
type config = {
interface_file : string;
package_name : string option;
ocaml_output : string option;
dune_output : string option;
}
open Fmt
let get_optional proj suffix config =
let default =
str "%s_%s"
Filename.(basename config.interface_file |> chop_extension)
suffix
in
Option.value (proj config) ~default
let get_ocaml_output = get_optional (fun cfg -> cfg.ocaml_output) "wrapped.ml"
let get_lib_name cfg = Filename.(basename cfg.interface_file |> chop_extension)
let get_name_output =
get_optional
(fun cfg ->
match cfg.ocaml_output with
| Some s -> Some (Filename.chop_extension s)
| None -> None)
"wrapped"
let get_intf_output =
get_optional
(fun cfg ->
match cfg.ocaml_output with
| Some s -> Some (Filename.chop_extension s ^ ".mli")
| None -> None)
"wrapped.mli"
let wrapper ppf _ = pf ppf "wrapper"
let msg ppf config =
pf ppf
"; This file is generated by ortac dune wrapper@\n\
; It contains the rules for generating a wrapper for %s@\n"
config.interface_file
let package config =
match config.package_name with
| None -> []
| Some s -> [ (fun ppf _ -> pf ppf "(package %s)" s) ]
let gen_ortac_lib ppf config =
let gen_name = get_name_output config in
let modules ppf _ = pf ppf "(modules %s)" gen_name in
let name ppf _ = pf ppf "(name %s)" gen_name in
let libraries ppf config =
pf ppf "(libraries ortac-runtime %s)" (get_lib_name config)
in
let stanzas = [ name; modules; libraries ] @ package config in
let library ppf = library ppf stanzas in
stanza_rule library ppf config
let gen_copy_rule ppf config =
let copy ppf =
copy ppf
[
(fun ppf _ -> pf ppf "%s" "%{deps}");
(fun ppf _ -> pf ppf "%s" "%{targets}");
]
in
let action ppf = action ppf (stanza copy) in
let stanzas =
[
runtest;
promote;
targets get_intf_output;
deps (fun c -> c.interface_file);
action;
]
in
let rule ppf = rule ppf stanzas in
stanza_rule rule ppf config
let gen_ortac_rule ppf config =
let args = [ ortac; wrapper; with_deps ] in
let run ppf = run ppf args in
let ignore_err = ignore_err (stanza run) in
let action ppf =
action_with_env "ORTAC_ONLY_PLUGIN" "wrapper" ppf (with_target ignore_err)
in
let stanzas =
[
runtest;
promote;
targets get_ocaml_output;
deps (fun cfg -> cfg.interface_file);
action;
]
in
let rule ppf = rule ppf stanzas in
stanza_rule rule ppf config
let gen_dune_rules ppf config =
let rules = [ msg; gen_copy_rule; gen_ortac_rule; gen_ortac_lib ] in
concat ~sep:cut rules ppf config