forked from ocaml/dune
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgen_meta.ml
173 lines (164 loc) · 5.17 KB
/
gen_meta.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
open! Stdune
open Import
open Meta
module Pub_name = struct
type t =
| Dot of t * string
| Id of string
let parse s =
let s = Lib_name.to_string s in
match String.split s ~on:'.' with
| [] -> assert false
| x :: l ->
let rec loop acc l =
match l with
| [] -> acc
| x :: l -> loop (Dot (acc, x)) l
in
loop (Id x) l
let rec root = function
| Dot (t, _) -> root t
| Id n -> n
let to_list =
let rec loop acc = function
| Dot (t, n) -> loop (n :: acc) t
| Id n -> n :: acc
in
fun t -> loop [] t
let to_string t = String.concat ~sep:"." (to_list t)
end
let string_of_deps deps =
Lib_name.Set.to_string_list deps
|> String.concat ~sep:" "
let rule var predicates action value =
Rule { var; predicates; action; value }
let requires ?(preds=[]) pkgs =
rule "requires" preds Set (string_of_deps pkgs)
let ppx_runtime_deps ?(preds=[]) pkgs =
rule "ppx_runtime_deps" preds Set (string_of_deps pkgs)
let description s = rule "description" [] Set s
let directory s = rule "directory" [] Set s
let archive preds s = rule "archive" preds Set s
let plugin preds s = rule "plugin" preds Set s
let archives ?(preds=[]) lib =
let archives = Lib.archives lib in
let plugins = Lib.plugins lib in
let make ps =
String.concat ~sep:" " (List.map ps ~f:Path.basename)
in
[ archive (preds @ [Pos "byte" ]) (make archives.byte )
; archive (preds @ [Pos "native"]) (make archives.native)
; plugin (preds @ [Pos "byte" ]) (make plugins .byte )
; plugin (preds @ [Pos "native"]) (make plugins .native)
]
let gen_lib pub_name lib ~version =
let desc =
match Lib.synopsis lib with
| Some s -> s
| None ->
(* CR-someday jdimino: wut? this looks old *)
match (pub_name : Pub_name.t) with
| Dot (p, "runtime-lib") ->
sprintf "Runtime library for %s" (Pub_name.to_string p)
| Dot (p, "expander") ->
sprintf "Expander for %s" (Pub_name.to_string p)
| _ -> ""
in
let preds =
match Lib.kind lib with
| Normal -> []
| Ppx_rewriter | Ppx_deriver -> [Pos "ppx_driver"]
in
let lib_deps = Lib.Meta.requires lib in
let ppx_rt_deps = Lib.Meta.ppx_runtime_deps lib in
List.concat
[ version
; [ description desc
; requires ~preds lib_deps
]
; archives ~preds lib
; if Lib_name.Set.is_empty ppx_rt_deps then
[]
else
[ Comment "This is what dune uses to find out the runtime \
dependencies of"
; Comment "a preprocessor"
; ppx_runtime_deps ppx_rt_deps
]
; (match Lib.kind lib with
| Normal -> []
| Ppx_rewriter | Ppx_deriver ->
(* Deprecated ppx method support *)
let no_ppx_driver = Neg "ppx_driver" and no_custom_ppx = Neg "custom_ppx" in
List.concat
[ [ Comment "This line makes things transparent for people mixing \
preprocessors"
; Comment "and normal dependencies"
; requires ~preds:[no_ppx_driver]
(Lib.Meta.ppx_runtime_deps_for_deprecated_method lib)
]
; match Lib.kind lib with
| Normal -> assert false
| Ppx_rewriter ->
[ rule "ppx" [no_ppx_driver; no_custom_ppx]
Set "./ppx.exe --as-ppx" ]
| Ppx_deriver ->
[ rule "requires" [no_ppx_driver; no_custom_ppx] Add
"ppx_deriving"
; rule "ppxopt" [no_ppx_driver; no_custom_ppx] Set
("ppx_deriving,package:" ^ Pub_name.to_string pub_name)
]
]
)
; (match Lib.jsoo_runtime lib with
| [] -> []
| l ->
let root = Pub_name.root pub_name in
let l = List.map l ~f:Path.basename in
[ rule "linkopts" [Pos "javascript"] Set
(List.map l ~f:(sprintf "+%s/%s" root) |> String.concat ~sep:" ")
; rule "jsoo_runtime" [] Set
(String.concat l ~sep:" ")
]
)
]
let gen ~package ~version libs =
let version =
match version with
| None -> []
| Some s -> [rule "version" [] Set s]
in
let pkgs =
List.map libs ~f:(fun lib ->
let pub_name = Pub_name.parse (Lib.name lib) in
(pub_name,
gen_lib pub_name lib ~version))
in
let pkgs =
List.map pkgs ~f:(fun (pn, meta) ->
match Pub_name.to_list pn with
| [] -> assert false
| _package :: path -> (path, meta))
in
let pkgs = List.sort pkgs ~compare:(fun (a, _) (b, _) -> compare a b) in
let rec loop name pkgs =
let entries, sub_pkgs =
List.partition_map pkgs ~f:(function
| ([] , entries) -> Left entries
| (x :: p, entries) -> Right (x, (p, entries)))
in
let entries = List.concat entries in
let subs =
String.Map.of_list_multi sub_pkgs
|> String.Map.to_list
|> List.map ~f:(fun (name, pkgs) ->
let pkg = loop name pkgs in
Package { pkg with
entries = directory name :: pkg.entries
})
in
{ name = Some (Lib_name.of_string_exn ~loc:None name)
; entries = entries @ subs
}
in
loop package pkgs