Skip to content

Commit 5a33236

Browse files
committed
impl
1 parent 216436c commit 5a33236

16 files changed

+442
-398
lines changed

jscomp/bsb/bsb_build_util.ml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,8 @@ let extract_pinned_dependencies (map : Ext_json_types.t Map_string.t) : Set_stri
155155

156156
let rec walk_all_deps_aux (visited : string Hash_string.t) (paths : string list)
157157
~(top : top) (dir : string) (queue : _ Queue.t) ~pinned_dependencies =
158-
let bsconfig_json = dir // Literals.bsconfig_json in
159-
match Ext_json_parse.parse_json_from_file bsconfig_json with
160-
| Obj { map; loc } ->
158+
match Bsb_config_parse.parse_json ~per_proj_dir:dir ~warn_legacy_config:false with
159+
| _, _, Obj { map; loc } ->
161160
let cur_package_name =
162161
match Map_string.find_opt map Bsb_build_schemas.name with
163162
| Some (Str { str; loc }) ->
@@ -220,7 +219,7 @@ let rec walk_all_deps_aux (visited : string Hash_string.t) (paths : string list)
220219
| Expect_name _ -> ());
221220
Queue.add { top; proj_dir = dir; is_pinned } queue;
222221
Hash_string.add visited cur_package_name dir
223-
| _ -> ()
222+
| _, _, _ -> ()
224223

225224
let walk_all_deps dir ~pinned_dependencies : package_context Queue.t =
226225
let visited = Hash_string.create 0 in

jscomp/bsb/bsb_clean.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ let clean_bs_garbage proj_dir =
5151
Bsb_log.warn "@{<warning>Failed@} to clean due to %s" (Printexc.to_string e)
5252

5353
let clean_bs_deps proj_dir =
54-
let _, _, _, pinned_dependencies = Bsb_config_parse.deps_from_bsconfig () in
54+
let _, _, _, pinned_dependencies = Bsb_config_interpret.deps_from_bsconfig () in
5555
let queue = Bsb_build_util.walk_all_deps proj_dir ~pinned_dependencies in
5656
Queue.iter
5757
(fun (pkg_cxt : Bsb_build_util.package_context) ->

jscomp/bsb/bsb_config_interpret.ml

Lines changed: 367 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,367 @@
1+
(* Copyright (C) 2015 - 2016 Bloomberg Finance L.P.
2+
* Copyright (C) 2017 - Hongbo Zhang, Authors of ReScript
3+
* This program is free software: you can redistribute it and/or modify
4+
* it under the terms of the GNU Lesser General Public License as published by
5+
* the Free Software Foundation, either version 3 of the License, or
6+
* (at your option) any later version.
7+
*
8+
* In addition to the permissions granted to you by the LGPL, you may combine
9+
* or link a "work that uses the Library" with a publicly distributed version
10+
* of this file to produce a combined library or application, then distribute
11+
* that combined work under the terms of your choosing, with no requirement
12+
* to comply with the obligations normally placed on you by section 4 of the
13+
* LGPL version 3 (or the corresponding section of a later version of the LGPL
14+
* should you choose to use a later version).
15+
*
16+
* This program is distributed in the hope that it will be useful,
17+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
* GNU Lesser General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU Lesser General Public License
22+
* along with this program; if not, write to the Free Software
23+
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)
24+
25+
(* let get_list_string = Bsb_build_util.get_list_string *)
26+
let ( // ) = Ext_path.combine
27+
28+
let resolve_package cwd package_name =
29+
let x = Bsb_pkg.resolve_bs_package ~cwd package_name in
30+
{
31+
Bsb_config_types.package_name;
32+
package_install_path = x // Bsb_config.lib_ocaml;
33+
}
34+
35+
type json_map = Ext_json_types.t Map_string.t
36+
37+
(* Key is the path *)
38+
let ( |? ) m (key, cb) = m |> Ext_json.test key cb
39+
let ( .?() ) = Map_string.find_opt
40+
41+
(*TODO: it is a little mess that [cwd] and [project dir] are shared*)
42+
43+
let extract_package_name_and_namespace (map : json_map) : string * string option
44+
=
45+
let package_name =
46+
match map.?(Bsb_build_schemas.name) with
47+
| Some (Str { str = "_" } as config) ->
48+
Bsb_exception.config_error config "_ is a reserved package name"
49+
| Some (Str { str = name }) -> name
50+
| Some config ->
51+
Bsb_exception.config_error config "name expect a string field"
52+
| None -> Bsb_exception.invalid_spec "field name is required"
53+
in
54+
let namespace =
55+
match map.?(Bsb_build_schemas.namespace) with
56+
| None | Some (False _) -> None
57+
| Some (True _) ->
58+
Some (Ext_namespace.namespace_of_package_name package_name)
59+
| Some (Str { str }) ->
60+
(*TODO : check the validity of namespace *)
61+
Some (Ext_namespace.namespace_of_package_name str)
62+
| Some x ->
63+
Bsb_exception.config_error x "namespace field expects string or boolean"
64+
in
65+
(package_name, namespace)
66+
67+
(**
68+
There are two things to check:
69+
- the running bsb and vendoring bsb is the same
70+
- the running bsb need delete stale build artifacts
71+
(kinda check npm upgrade)
72+
73+
Note if the setup is correct:
74+
the running compiler and node_modules/rescript
75+
should be the same version,
76+
The exact check is that the running compiler should have a
77+
compatible runtime version installed, the location of the
78+
compiler is actually not relevant.
79+
We disable the check temporarily
80+
e.g,
81+
```
82+
bsc -runtime runtime_dir@version
83+
```
84+
*)
85+
let check_stdlib (map : json_map) : bool =
86+
(*built_in_package*)
87+
match map.?(Bsb_build_schemas.use_stdlib) with
88+
| Some (False _) -> false
89+
| None | Some _ -> true
90+
91+
let extract_gentype_config (map : json_map) : Bsb_config_types.gentype_config =
92+
match map.?(Bsb_build_schemas.gentypeconfig) with
93+
| None -> false
94+
| Some (Obj _) -> true
95+
| Some config ->
96+
Bsb_exception.config_error config "gentypeconfig expect an object"
97+
98+
let extract_uncurried (map : json_map) : bool =
99+
match map.?(Bsb_build_schemas.uncurried) with
100+
| None -> false
101+
| Some (True _) -> true
102+
| Some (False _) -> false
103+
| Some config ->
104+
Bsb_exception.config_error config "uncurried expects one of: true, false."
105+
106+
let extract_string (map : json_map) (field : string) cb =
107+
match map.?(field) with
108+
| None -> None
109+
| Some (Str { str }) -> cb str
110+
| Some config -> Bsb_exception.config_error config (field ^ " expect a string")
111+
112+
let extract_boolean (map : json_map) (field : string) (default : bool) : bool =
113+
match map.?(field) with
114+
| None -> default
115+
| Some (True _) -> true
116+
| Some (False _) -> false
117+
| Some config ->
118+
Bsb_exception.config_error config (field ^ " expect a boolean")
119+
120+
let extract_reason_react_jsx (map : json_map) =
121+
let default : Bsb_config_types.reason_react_jsx option ref = ref None in
122+
map
123+
|? ( Bsb_build_schemas.reason,
124+
`Obj
125+
(fun m ->
126+
match m.?(Bsb_build_schemas.react_jsx) with
127+
| Some (Flo { loc; flo }) -> (
128+
match flo with
129+
| "3" -> default := Some Jsx_v3
130+
| _ -> Bsb_exception.errorf ~loc "Unsupported jsx version %s" flo
131+
)
132+
| Some x ->
133+
Bsb_exception.config_error x
134+
"Unexpected input (expect a version number) for jsx, note \
135+
boolean is no longer allowed"
136+
| None -> ()) )
137+
|> ignore;
138+
!default
139+
140+
let extract_warning (map : json_map) =
141+
match map.?(Bsb_build_schemas.warnings) with
142+
| None -> Bsb_warning.use_default
143+
| Some (Obj { map }) -> Bsb_warning.from_map map
144+
| Some config -> Bsb_exception.config_error config "expect an object"
145+
146+
let extract_ignored_dirs (map : json_map) : Set_string.t =
147+
match map.?(Bsb_build_schemas.ignored_dirs) with
148+
| None -> Set_string.empty
149+
| Some (Arr { content }) ->
150+
Set_string.of_list (Bsb_build_util.get_list_string content)
151+
| Some config -> Bsb_exception.config_error config "expect an array of string"
152+
153+
let extract_generators (map : json_map) =
154+
let generators = ref Map_string.empty in
155+
(match map.?(Bsb_build_schemas.generators) with
156+
| None -> ()
157+
| Some (Arr { content = s }) ->
158+
generators :=
159+
Ext_array.fold_left s Map_string.empty (fun acc json ->
160+
match json with
161+
| Obj { map = m; loc } -> (
162+
match
163+
(m.?(Bsb_build_schemas.name), m.?(Bsb_build_schemas.command))
164+
with
165+
| Some (Str { str = name }), Some (Str { str = command }) ->
166+
Map_string.add acc name command
167+
| _, _ ->
168+
Bsb_exception.errorf ~loc
169+
{| generators exepect format like { "name" : "cppo", "command" : "cppo $in -o $out"} |}
170+
)
171+
| _ -> acc)
172+
| Some config ->
173+
Bsb_exception.config_error config
174+
(Bsb_build_schemas.generators ^ " expect an array field"));
175+
!generators
176+
177+
let extract_dependencies (map : json_map) cwd (field : string) :
178+
Bsb_config_types.dependencies =
179+
match map.?(field) with
180+
| None -> []
181+
| Some (Arr { content = s }) ->
182+
Ext_list.map (Bsb_build_util.get_list_string s) (fun s ->
183+
resolve_package cwd (Bsb_pkg_types.string_as_package s))
184+
| Some config -> Bsb_exception.config_error config (field ^ " expect an array")
185+
186+
(* return an empty array if not found *)
187+
let extract_string_list (map : json_map) (field : string) : string list =
188+
match map.?(field) with
189+
| None -> []
190+
| Some (Arr { content = s }) -> Bsb_build_util.get_list_string s
191+
| Some config -> Bsb_exception.config_error config (field ^ " expect an array")
192+
193+
let extract_ppx (map : json_map) (field : string) ~(cwd : string) :
194+
Bsb_config_types.ppx list =
195+
match map.?(field) with
196+
| None -> []
197+
| Some (Arr { content }) ->
198+
let resolve s =
199+
if s = "" then
200+
Bsb_exception.invalid_spec "invalid ppx, empty string found"
201+
else
202+
(Bsb_build_util.resolve_bsb_magic_file ~cwd
203+
~desc:Bsb_build_schemas.ppx_flags s)
204+
.path
205+
in
206+
Ext_array.to_list_f content (fun x ->
207+
match x with
208+
| Str x -> { Bsb_config_types.name = resolve x.str; args = [] }
209+
| Arr { content } -> (
210+
let xs = Bsb_build_util.get_list_string content in
211+
match xs with
212+
| [] -> Bsb_exception.config_error x " empty array is not allowed"
213+
| name :: args -> { Bsb_config_types.name = resolve name; args })
214+
| config ->
215+
Bsb_exception.config_error config
216+
(field ^ "expect each item to be either string or array"))
217+
| Some config -> Bsb_exception.config_error config (field ^ " expect an array")
218+
219+
let extract_js_post_build (map : json_map) cwd : string option =
220+
let js_post_build_cmd = ref None in
221+
map
222+
|? ( Bsb_build_schemas.js_post_build,
223+
`Obj
224+
(fun m ->
225+
m
226+
|? ( Bsb_build_schemas.cmd,
227+
`Str
228+
(fun s ->
229+
js_post_build_cmd :=
230+
Some
231+
(Bsb_build_util.resolve_bsb_magic_file ~cwd
232+
~desc:Bsb_build_schemas.js_post_build s)
233+
.path) )
234+
|> ignore) )
235+
|> ignore;
236+
!js_post_build_cmd
237+
238+
(** ATT: make sure such function is re-entrant.
239+
With a given [cwd] it works anywhere*)
240+
let interpret_json ~(package_kind : Bsb_package_kind.t) ~(per_proj_dir : string) ~(warn_legacy_config : bool)
241+
: Bsb_config_types.t =
242+
(* we should not resolve it too early,
243+
since it is external configuration, no {!Bsb_build_util.convert_and_resolve_path}
244+
*)
245+
246+
(* When we plan to add more deps here,
247+
Make sure check it is consistent that for nested deps, we have a
248+
quck check by just re-parsing deps
249+
Make sure it works with [-make-world] [-clean-world]
250+
*)
251+
252+
(* Setting ninja is a bit complex
253+
1. if [build.ninja] does use [ninja] we need set a variable
254+
2. we need store it so that we can call ninja correctly
255+
*)
256+
match
257+
Bsb_config_parse.parse_json ~per_proj_dir ~warn_legacy_config
258+
with
259+
| filename, _, Obj { map } -> (
260+
let package_name, namespace = extract_package_name_and_namespace map in
261+
let gentype_config = extract_gentype_config map in
262+
263+
(* This line has to be before any calls to Bsb_global_backend.backend, because it'll read the entries
264+
array from the bsconfig and set the backend_ref to the first entry, if any. *)
265+
266+
(* The default situation is empty *)
267+
let built_in_package : bool = check_stdlib map in
268+
269+
let pp_flags : string option =
270+
extract_string map Bsb_build_schemas.pp_flags (fun p ->
271+
if p = "" then
272+
Bsb_exception.invalid_spec "invalid pp, empty string found"
273+
else
274+
Some
275+
(Bsb_build_util.resolve_bsb_magic_file ~cwd:per_proj_dir
276+
~desc:Bsb_build_schemas.pp_flags p)
277+
.path)
278+
in
279+
let reason_react_jsx = extract_reason_react_jsx map in
280+
let bs_dependencies =
281+
extract_dependencies map per_proj_dir Bsb_build_schemas.bs_dependencies
282+
in
283+
let bs_dev_dependencies =
284+
match package_kind with
285+
| Toplevel | Pinned_dependency _ ->
286+
extract_dependencies map per_proj_dir
287+
Bsb_build_schemas.bs_dev_dependencies
288+
| Dependency _ -> []
289+
in
290+
let pinned_dependencies = Bsb_build_util.extract_pinned_dependencies map in
291+
match map.?(Bsb_build_schemas.sources) with
292+
| Some sources ->
293+
let cut_generators =
294+
extract_boolean map Bsb_build_schemas.cut_generators false
295+
in
296+
let groups =
297+
Bsb_parse_sources.scan ~ignored_dirs:(extract_ignored_dirs map)
298+
~package_kind ~root:per_proj_dir ~cut_generators
299+
(* ~namespace *)
300+
sources
301+
in
302+
let bsc_flags = extract_string_list map Bsb_build_schemas.bsc_flags in
303+
let jsx = Bsb_jsx.from_map map in
304+
let jsx, bsc_flags =
305+
match package_kind with
306+
| Pinned_dependency x | Dependency x ->
307+
if List.mem package_name x.jsx.v3_dependencies then
308+
( { jsx with version = Some Jsx_v3 },
309+
"-open ReactV3" :: bsc_flags )
310+
else (x.jsx, bsc_flags)
311+
| _ -> (jsx, bsc_flags)
312+
in
313+
{
314+
pinned_dependencies;
315+
gentype_config;
316+
package_name;
317+
namespace;
318+
warning = extract_warning map;
319+
external_includes =
320+
extract_string_list map Bsb_build_schemas.bs_external_includes;
321+
bsc_flags;
322+
ppx_files =
323+
extract_ppx map ~cwd:per_proj_dir Bsb_build_schemas.ppx_flags;
324+
pp_file = pp_flags;
325+
bs_dependencies;
326+
bs_dev_dependencies;
327+
(*
328+
reference for quoting
329+
{[
330+
let tmpfile = Filename.temp_file "ocamlpp" "" in
331+
let comm = Printf.sprintf "%s %s > %s"
332+
pp (Filename.quote sourcefile) tmpfile
333+
in
334+
]}
335+
*)
336+
js_post_build_cmd = extract_js_post_build map per_proj_dir;
337+
package_specs =
338+
(match package_kind with
339+
| Toplevel -> Bsb_package_specs.from_map ~cwd:per_proj_dir map
340+
| Pinned_dependency x | Dependency x -> x.package_specs);
341+
file_groups = groups;
342+
files_to_install = Queue.create ();
343+
built_in_dependency = built_in_package;
344+
reason_react_jsx;
345+
jsx;
346+
generators = extract_generators map;
347+
cut_generators;
348+
uncurried =
349+
(match package_kind with
350+
| Toplevel -> extract_uncurried map
351+
| Pinned_dependency x | Dependency x -> x.uncurried);
352+
filename;
353+
}
354+
| None ->
355+
Bsb_exception.invalid_spec "no sources specified in bsconfig.json")
356+
| _, _, _ -> Bsb_exception.invalid_spec "bsconfig.json expect a json object {}"
357+
358+
let deps_from_bsconfig () =
359+
let cwd = Bsb_global_paths.cwd in
360+
let json = Bsb_config_parse.parse_json ~per_proj_dir:cwd ~warn_legacy_config:false in
361+
match json with
362+
| _, _, Obj { map } ->
363+
( Bsb_package_specs.from_map ~cwd map,
364+
Bsb_jsx.from_map map,
365+
extract_uncurried map,
366+
Bsb_build_util.extract_pinned_dependencies map )
367+
| _, _, _ -> assert false
File renamed without changes.

0 commit comments

Comments
 (0)